From b30c103eccf18225ac8033fdb2f6ca810dbb7445 Mon Sep 17 00:00:00 2001 From: "shiyangyangwork@yahoo.cn" Date: Thu, 9 Feb 2012 06:56:35 +0000 Subject: [PATCH] finish the task #689. --- bin/initext.php | 120 +- bin/ztcli | 92 +- config/config.php | 242 +- lib/api/api.class.php | 3010 +++++++++---------- module/action/control.php | 132 +- module/action/lang/en.php | 362 +-- module/action/lang/zh-cn.php | 362 +-- module/action/lang/zh-tw.php | 362 +-- module/action/model.php | 1056 +++---- module/action/view/trash.html.php | 98 +- module/admin/control.php | 48 +- module/admin/lang/en.php | 38 +- module/admin/lang/zh-cn.php | 38 +- module/admin/lang/zh-tw.php | 38 +- module/admin/model.php | 96 +- module/admin/view/browsecompany.html.php | 94 +- module/api/control.php | 100 +- module/api/lang/en.php | 26 +- module/api/lang/zh-cn.php | 26 +- module/api/lang/zh-tw.php | 26 +- module/api/model.php | 30 +- module/bug/control.php | 1894 ++++++------ module/bug/lang/en.php | 624 ++-- module/bug/lang/zh-cn.php | 624 ++-- module/bug/lang/zh-tw.php | 624 ++-- module/bug/model.php | 1976 ++++++------ module/bug/view/activate.html.php | 86 +- module/bug/view/browse.html.php | 350 +-- module/bug/view/close.html.php | 62 +- module/bug/view/confirmbug.html.php | 62 +- module/bug/view/create.html.php | 204 +- module/bug/view/customfields.html.php | 98 +- module/bug/view/edit.html.php | 412 +-- module/bug/view/export.html.php | 26 +- module/bug/view/report.html.php | 124 +- module/bug/view/resolve.html.php | 94 +- module/bug/view/sendmail.html.php | 44 +- module/bug/view/view.html.php | 544 ++-- module/build/control.php | 372 +-- module/build/lang/en.php | 70 +- module/build/lang/zh-cn.php | 70 +- module/build/lang/zh-tw.php | 70 +- module/build/model.php | 304 +- module/build/view/create.html.php | 194 +- module/build/view/edit.html.php | 194 +- module/build/view/view.html.php | 234 +- module/common/control.php | 530 ++-- module/common/lang/en.php | 592 ++-- module/common/lang/zh-cn.php | 592 ++-- module/common/lang/zh-tw.php | 592 ++-- module/common/model.php | 732 ++--- module/company/control.php | 472 +-- module/company/lang/en.php | 78 +- module/company/lang/zh-cn.php | 78 +- module/company/lang/zh-tw.php | 78 +- module/company/model.php | 246 +- module/company/view/browse.html.php | 156 +- module/company/view/create.html.php | 112 +- module/company/view/dynamic.html.php | 124 +- module/company/view/edit.html.php | 112 +- module/convert/control.php | 480 +-- module/convert/converter/bugfree.php | 176 +- module/convert/converter/bugfree1.php | 636 ++-- module/convert/converter/bugfree2.php | 1060 +++---- module/convert/converter/redmine.php | 176 +- module/convert/converter/redmine1.1.php | 1644 +++++----- module/convert/lang/en.php | 218 +- module/convert/lang/zh-cn.php | 218 +- module/convert/lang/zh-tw.php | 218 +- module/convert/model.php | 188 +- module/convert/view/checkconfig.html.php | 58 +- module/convert/view/execute.html.php | 36 +- module/convert/view/index.html.php | 36 +- module/convert/view/selectsource.html.php | 62 +- module/convert/view/setconfig.html.php | 46 +- module/dept/control.php | 202 +- module/dept/lang/en.php | 46 +- module/dept/lang/zh-cn.php | 46 +- module/dept/lang/zh-tw.php | 46 +- module/dept/model.php | 604 ++-- module/dept/view/browse.html.php | 134 +- module/doc/control.php | 840 +++--- module/doc/lang/en.php | 130 +- module/doc/lang/zh-cn.php | 130 +- module/doc/lang/zh-tw.php | 130 +- module/doc/model.php | 562 ++-- module/doc/view/browse.html.php | 164 +- module/doc/view/create.html.php | 140 +- module/doc/view/createlib.html.php | 52 +- module/doc/view/edit.html.php | 136 +- module/doc/view/editlib.html.php | 56 +- module/doc/view/view.html.php | 150 +- module/editor/control.php | 328 +- module/editor/model.php | 1122 +++---- module/editor/view/edit.html.php | 140 +- module/editor/view/extend.html.php | 58 +- module/editor/view/index.html.php | 48 +- module/editor/view/newpage.html.php | 66 +- module/extension/control.php | 706 ++--- module/extension/lang/en.php | 186 +- module/extension/lang/zh-cn.php | 186 +- module/extension/lang/zh-tw.php | 186 +- module/extension/model.php | 1508 +++++----- module/extension/view/activate.html.php | 66 +- module/extension/view/browse.html.php | 104 +- module/extension/view/checkscore.html.php | 56 +- module/extension/view/deactivate.html.php | 62 +- module/extension/view/erase.html.php | 62 +- module/extension/view/install.html.php | 98 +- module/extension/view/obtain.html.php | 226 +- module/extension/view/uninstall.html.php | 62 +- module/extension/view/upload.html.php | 38 +- module/extension/view/waring.htm.php | 58 +- module/file/control.php | 532 ++-- module/file/lang/en.php | 46 +- module/file/lang/zh-cn.php | 46 +- module/file/lang/zh-tw.php | 46 +- module/file/model.php | 420 +-- module/file/view/edit.html.php | 82 +- module/file/view/export.html.php | 102 +- module/file/view/export2csv.html.php | 48 +- module/file/view/export2html.html.php | 88 +- module/file/view/export2xml.html.php | 72 +- module/group/control.php | 448 +-- module/group/lang/en.php | 114 +- module/group/lang/resource.php | 716 ++--- module/group/lang/zh-cn.php | 114 +- module/group/lang/zh-tw.php | 114 +- module/group/model.php | 502 ++-- module/group/view/browse.html.php | 100 +- module/group/view/copy.html.php | 64 +- module/group/view/create.html.php | 56 +- module/group/view/edit.html.php | 56 +- module/group/view/managemember.html.php | 94 +- module/group/view/managepriv.html.php | 34 +- module/group/view/privbygroup.html.php | 112 +- module/group/view/privbymodule.html.php | 90 +- module/help/control.php | 92 +- module/help/model.php | 30 +- module/help/view/field.html.php | 38 +- module/index/control.php | 96 +- module/index/model.php | 30 +- module/install/control.php | 288 +- module/install/lang/en.php | 210 +- module/install/lang/zh-cn.php | 212 +- module/install/lang/zh-tw.php | 212 +- module/install/model.php | 746 ++--- module/install/view/index.html.php | 66 +- module/install/view/step1.html.php | 192 +- module/install/view/step2.html.php | 124 +- module/install/view/step3.html.php | 144 +- module/install/view/step4.html.php | 104 +- module/mail/control.php | 226 +- module/mail/model.php | 536 ++-- module/mail/view/save.html.php | 50 +- module/mail/view/set.html.php | 220 +- module/misc/control.php | 116 +- module/misc/lang/en.php | 116 +- module/misc/lang/zh-cn.php | 116 +- module/misc/lang/zh-tw.php | 116 +- module/misc/model.php | 32 +- module/my/control.php | 758 ++--- module/my/model.php | 52 +- module/my/view/bug.html.php | 130 +- module/my/view/dynamic.html.php | 110 +- module/my/view/editprofile.html.php | 200 +- module/my/view/index.html.php | 62 +- module/my/view/profile.html.php | 240 +- module/my/view/project.html.php | 92 +- module/my/view/story.html.php | 130 +- module/my/view/task.html.php | 164 +- module/my/view/team.html.php | 28 +- module/my/view/testcase.html.php | 118 +- module/my/view/testtask.html.php | 120 +- module/my/view/todo.html.php | 178 +- module/product/control.php | 760 ++--- module/product/lang/en.php | 152 +- module/product/lang/zh-cn.php | 152 +- module/product/lang/zh-tw.php | 152 +- module/product/model.php | 854 +++--- module/product/view/browse.html.php | 240 +- module/product/view/create.html.php | 106 +- module/product/view/doc.html.php | 108 +- module/product/view/dynamic.html.php | 112 +- module/product/view/edit.html.php | 114 +- module/product/view/index.html.php | 108 +- module/product/view/project.html.php | 88 +- module/product/view/roadmap.html.php | 98 +- module/product/view/view.html.php | 140 +- module/productplan/control.php | 384 +-- module/productplan/lang/en.php | 68 +- module/productplan/lang/zh-cn.php | 64 +- module/productplan/lang/zh-tw.php | 64 +- module/productplan/model.php | 250 +- module/productplan/view/browse.html.php | 98 +- module/productplan/view/create.html.php | 100 +- module/productplan/view/edit.html.php | 100 +- module/productplan/view/linkstory.html.php | 178 +- module/productplan/view/view.html.php | 168 +- module/project/control.php | 2 +- module/project/lang/en.php | 328 +- module/project/lang/zh-cn.php | 2 +- module/project/lang/zh-tw.php | 2 +- module/project/model.php | 2066 ++++++------- module/project/view/browse.html.php | 308 +- module/project/view/bug.html.php | 126 +- module/project/view/build.html.php | 108 +- module/project/view/burn.html.php | 42 +- module/project/view/computeburn.html.php | 36 +- module/project/view/create.html.php | 174 +- module/project/view/doc.html.php | 102 +- module/project/view/dynamic.html.php | 112 +- module/project/view/edit.html.php | 172 +- module/project/view/grouptask.html.php | 236 +- module/project/view/importbug.html.php | 124 +- module/project/view/importtask.html.php | 118 +- module/project/view/index.html.php | 96 +- module/project/view/linkstory.html.php | 106 +- module/project/view/managechilds.html.php | 58 +- module/project/view/managemembers.html.php | 120 +- module/project/view/manageproducts.html.php | 46 +- module/project/view/sendmail.html.php | 44 +- module/project/view/story.html.php | 148 +- module/project/view/task.html.php | 248 +- module/project/view/team.html.php | 112 +- module/project/view/testtask.html.php | 108 +- module/project/view/view.html.php | 192 +- module/qa/control.php | 48 +- module/qa/lang/en.php | 26 +- module/qa/lang/zh-cn.php | 26 +- module/qa/lang/zh-tw.php | 26 +- module/qa/model.php | 30 +- module/qa/view/index.html.php | 32 +- module/release/control.php | 388 +-- module/release/lang/en.php | 64 +- module/release/lang/zh-cn.php | 64 +- module/release/lang/zh-tw.php | 64 +- module/release/model.php | 204 +- module/release/view/browse.html.php | 92 +- module/release/view/create.html.php | 80 +- module/release/view/edit.html.php | 174 +- module/release/view/view.html.php | 218 +- module/report/control.php | 28 +- module/report/lang/en.php | 62 +- module/report/lang/zh-cn.php | 62 +- module/report/lang/zh-tw.php | 62 +- module/report/model.php | 462 +-- module/search/control.php | 232 +- module/search/lang/en.php | 92 +- module/search/lang/zh-cn.php | 92 +- module/search/lang/zh-tw.php | 90 +- module/search/model.php | 538 ++-- module/search/view/buildform.html.php | 524 ++-- module/search/view/select.html.php | 182 +- module/setting/model.php | 248 +- module/story/control.php | 1630 +++++----- module/story/lang/en.php | 444 +-- module/story/lang/zh-cn.php | 444 +-- module/story/lang/zh-tw.php | 444 +-- module/story/model.php | 2424 +++++++-------- module/story/view/activate.html.php | 72 +- module/story/view/batchcreate.html.php | 98 +- module/story/view/change.html.php | 104 +- module/story/view/close.html.php | 84 +- module/story/view/create.html.php | 146 +- module/story/view/edit.html.php | 278 +- module/story/view/export.html.php | 26 +- module/story/view/report.html.php | 124 +- module/story/view/review.html.php | 136 +- module/story/view/sendmail.html.php | 44 +- module/story/view/view.html.php | 546 ++-- module/svn/control.php | 196 +- module/svn/lang/en.php | 32 +- module/svn/lang/zh-cn.php | 32 +- module/svn/lang/zh-tw.php | 32 +- module/svn/model.php | 1268 ++++---- module/svn/syncer/syncer.php | 598 ++-- module/svn/view/cat.html.php | 32 +- module/svn/view/diff.html.php | 34 +- module/task/control.php | 1460 ++++----- module/task/lang/en.php | 358 +-- module/task/lang/zh-cn.php | 358 +-- module/task/lang/zh-tw.php | 358 +-- module/task/model.php | 1800 +++++------ module/task/view/activate.html.php | 80 +- module/task/view/assignto.html.php | 62 +- module/task/view/batchcreate.html.php | 102 +- module/task/view/browse.html.php | 72 +- module/task/view/cancel.html.php | 54 +- module/task/view/close.html.php | 54 +- module/task/view/create.html.php | 172 +- module/task/view/edit.html.php | 290 +- module/task/view/export.html.php | 26 +- module/task/view/finish.html.php | 62 +- module/task/view/import.html.php | 116 +- module/task/view/report.html.php | 126 +- module/task/view/sendmail.html.php | 44 +- module/task/view/start.html.php | 70 +- module/task/view/view.html.php | 364 +-- module/testcase/control.php | 1090 +++---- module/testcase/lang/en.php | 270 +- module/testcase/lang/zh-cn.php | 270 +- module/testcase/lang/zh-tw.php | 270 +- module/testcase/model.php | 602 ++-- module/testcase/view/batchcreate.html.php | 90 +- module/testcase/view/browse.html.php | 212 +- module/testcase/view/create.html.php | 194 +- module/testcase/view/edit.html.php | 264 +- module/testcase/view/export.html.php | 26 +- module/testcase/view/index.html.php | 30 +- module/testcase/view/view.html.php | 396 +-- module/testtask/control.php | 942 +++--- module/testtask/lang/en.php | 132 +- module/testtask/lang/zh-cn.php | 132 +- module/testtask/lang/zh-tw.php | 132 +- module/testtask/model.php | 690 ++--- module/testtask/view/browse.html.php | 112 +- module/testtask/view/cases.html.php | 202 +- module/testtask/view/create.html.php | 134 +- module/testtask/view/edit.html.php | 112 +- module/testtask/view/linkcase.html.php | 136 +- module/testtask/view/results.html.php | 98 +- module/testtask/view/runcase.html.php | 118 +- module/testtask/view/view.html.php | 128 +- module/todo/control.php | 504 ++-- module/todo/lang/en.php | 156 +- module/todo/lang/zh-cn.php | 156 +- module/todo/lang/zh-tw.php | 154 +- module/todo/model.php | 856 +++--- module/todo/view/create.html.php | 122 +- module/todo/view/edit.html.php | 134 +- module/todo/view/export.html.php | 26 +- module/todo/view/view.html.php | 174 +- module/tree/control.php | 474 +-- module/tree/lang/en.php | 80 +- module/tree/lang/zh-cn.php | 80 +- module/tree/lang/zh-tw.php | 76 +- module/tree/model.php | 1094 +++---- module/tree/view/browse.html.php | 192 +- module/tree/view/edit.html.php | 76 +- module/upgrade/control.php | 162 +- module/upgrade/lang/en.php | 120 +- module/upgrade/lang/zh-cn.php | 120 +- module/upgrade/lang/zh-tw.php | 120 +- module/upgrade/model.php | 2174 +++++++------- module/upgrade/view/confirm.html.php | 52 +- module/upgrade/view/execute.html.php | 60 +- module/upgrade/view/index.html.php | 44 +- module/upgrade/view/selectversion.html.php | 58 +- module/user/control.php | 1012 +++---- module/user/lang/en.php | 164 +- module/user/lang/zh-cn.php | 164 +- module/user/lang/zh-tw.php | 164 +- module/user/model.php | 822 ++--- module/user/view/bug.html.php | 86 +- module/user/view/create.html.php | 114 +- module/user/view/deny.html.php | 62 +- module/user/view/dynamic.html.php | 116 +- module/user/view/edit.html.php | 186 +- module/user/view/login.html.php | 94 +- module/user/view/profile.html.php | 238 +- module/user/view/project.html.php | 92 +- module/user/view/story.html.php | 30 +- module/user/view/task.html.php | 88 +- module/user/view/team.html.php | 28 +- module/user/view/todo.html.php | 120 +- module/user/view/view.html.php | 156 +- www/index.php | 86 +- www/install.php | 76 +- www/upgrade.php | 74 +- 370 files changed, 46270 insertions(+), 46270 deletions(-) diff --git a/bin/initext.php b/bin/initext.php index 78172202f8..c2dc053dbe 100644 --- a/bin/initext.php +++ b/bin/initext.php @@ -1,60 +1,60 @@ - - * @package common - * @version $Id$ - * @link http://www.zentao.net - */ -include '../config/config.php'; - -$modules = array(); -$moduleRoot = realpath('../module/') . '/'; - -if(is_dir($moduleRoot)) -{ - if($dh = opendir($moduleRoot)) - { - while($module = readdir($dh)) - { - if(strpos(basename($module), '.') === false) $modules[] = $module; - } - closedir($dh); - } -} -else -{ - die("The module you input does not exist. \n"); -} - -foreach($modules as $module) -{ - /* 设定各个目录。*/ - $extRoot = $moduleRoot . DIRECTORY_SEPARATOR. $module . DIRECTORY_SEPARATOR . 'ext'; - $extControl = $extRoot . DIRECTORY_SEPARATOR . 'control'; - $extModel = $extRoot . DIRECTORY_SEPARATOR . 'model'; - $extView = $extRoot . DIRECTORY_SEPARATOR . 'view'; - $extConfig = $extRoot . DIRECTORY_SEPARATOR . 'config'; - $extLang = $extRoot . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; - - /* 建立各个扩展目录 */ - if(!file_exists($extRoot)) mkdir($extRoot, 0777); - if(!file_exists($extControl)) mkdir($extControl, 0777); - if(!file_exists($extModel)) mkdir($extModel, 0777); - if(!file_exists($extView)) mkdir($extView, 0777); - if(!file_exists($extConfig)) mkdir($extConfig, 0777); - if(!file_exists($extLang)) mkdir($extLang, 0777); - - /* 创建语言目录。*/ - $langs = array_keys($config->langs); - foreach($langs as $lang) - { - $langPath = $extLang . $lang; - if(!file_exists($langPath)) mkdir($langPath, 0777); - } - - echo "init $module ... \n"; -} + + * @package common + * @version $Id$ + * @link http://www.zentao.net + */ +include '../config/config.php'; + +$modules = array(); +$moduleRoot = realpath('../module/') . '/'; + +if(is_dir($moduleRoot)) +{ + if($dh = opendir($moduleRoot)) + { + while($module = readdir($dh)) + { + if(strpos(basename($module), '.') === false) $modules[] = $module; + } + closedir($dh); + } +} +else +{ + die("The module you input does not exist. \n"); +} + +foreach($modules as $module) +{ + /* 设定各个目录。*/ + $extRoot = $moduleRoot . DIRECTORY_SEPARATOR. $module . DIRECTORY_SEPARATOR . 'ext'; + $extControl = $extRoot . DIRECTORY_SEPARATOR . 'control'; + $extModel = $extRoot . DIRECTORY_SEPARATOR . 'model'; + $extView = $extRoot . DIRECTORY_SEPARATOR . 'view'; + $extConfig = $extRoot . DIRECTORY_SEPARATOR . 'config'; + $extLang = $extRoot . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR; + + /* 建立各个扩展目录 */ + if(!file_exists($extRoot)) mkdir($extRoot, 0777); + if(!file_exists($extControl)) mkdir($extControl, 0777); + if(!file_exists($extModel)) mkdir($extModel, 0777); + if(!file_exists($extView)) mkdir($extView, 0777); + if(!file_exists($extConfig)) mkdir($extConfig, 0777); + if(!file_exists($extLang)) mkdir($extLang, 0777); + + /* 创建语言目录。*/ + $langs = array_keys($config->langs); + foreach($langs as $lang) + { + $langPath = $extLang . $lang; + if(!file_exists($langPath)) mkdir($langPath, 0777); + } + + echo "init $module ... \n"; +} diff --git a/bin/ztcli b/bin/ztcli index 6fba68992a..6c7f66c7ae 100755 --- a/bin/ztcli +++ b/bin/ztcli @@ -1,46 +1,46 @@ -#!/usr/bin/env php - - * @package bin - * @version $Id$ - * @link http://www.ZenTaoPMS.com - */ -//error_reporting(0); -define('IN_SHELL', true); - -/* Judge the args. */ -if($argc != 2) die('Usage: ' . basename(__FILE__) . " \n"); - -/* Parse the request into params. */ -$request = parse_url(trim($argv[1])); -$_SERVER['HTTP_HOST'] = $request['host']; - -/* Load the framework. */ -chdir(dirname(__FILE__)); -include '../framework/router.class.php'; -include '../framework/control.class.php'; -include '../framework/model.class.php'; -include '../framework/helper.class.php'; -include '../config/config.php'; - -if($config->requestType == 'PATH_INFO') -{ - $_SERVER['PATH_INFO'] = str_replace($config->webRoot, '', $request['path']); -} -else -{ - parse_str($request['query'], $_GET); - $_SERVER['SCRIPT_NAME'] = $_SERVER['PATH_INFO'] . 'index.php'; - $_SERVER['REQUEST_URI'] = isset($request['query']) ? $request['query'] : ''; -} - -/* Instance the app and run it. */ -$app = router::createApp('pms', dirname(dirname(__FILE__))); -$common = $app->loadCommon(); -$app->parseRequest(); -$app->loadModule(); +#!/usr/bin/env php + + * @package bin + * @version $Id$ + * @link http://www.ZenTaoPMS.com + */ +//error_reporting(0); +define('IN_SHELL', true); + +/* Judge the args. */ +if($argc != 2) die('Usage: ' . basename(__FILE__) . " \n"); + +/* Parse the request into params. */ +$request = parse_url(trim($argv[1])); +$_SERVER['HTTP_HOST'] = $request['host']; + +/* Load the framework. */ +chdir(dirname(__FILE__)); +include '../framework/router.class.php'; +include '../framework/control.class.php'; +include '../framework/model.class.php'; +include '../framework/helper.class.php'; +include '../config/config.php'; + +if($config->requestType == 'PATH_INFO') +{ + $_SERVER['PATH_INFO'] = str_replace($config->webRoot, '', $request['path']); +} +else +{ + parse_str($request['query'], $_GET); + $_SERVER['SCRIPT_NAME'] = $_SERVER['PATH_INFO'] . 'index.php'; + $_SERVER['REQUEST_URI'] = isset($request['query']) ? $request['query'] : ''; +} + +/* Instance the app and run it. */ +$app = router::createApp('pms', dirname(dirname(__FILE__))); +$common = $app->loadCommon(); +$app->parseRequest(); +$app->loadModule(); diff --git a/config/config.php b/config/config.php index 5c64e509a1..dd1a5cee83 100644 --- a/config/config.php +++ b/config/config.php @@ -1,121 +1,121 @@ - - * @package config - * @version $Id$ - * @link http://www.zentao.net - */ -/* Basic settings. */ -$config->version = '3.0.beta1'; // The version of zentaopms. Don't change it. -$config->encoding = 'UTF-8'; // The encoding of znetaopms. -$config->cookieLife = time() + 2592000; // The cookie life time. -$config->timezone = 'Asia/Shanghai'; // The time zone setting, for more see http://www.php.net/manual/en/timezones.php -$config->webRoot = ''; // The root path of the pms. - -/* The request settings. */ -$config->requestType = 'PATH_INFO'; // The request type: PATH_INFO|GET, if PATH_INFO, must use url rewrite. -$config->pathType = 'clean'; // If the request type is PATH_INFO, the path type. -$config->requestFix = '-'; // The divider in the url when PATH_INFO. -$config->moduleVar = 'm'; // requestType=GET: the module var name. -$config->methodVar = 'f'; // requestType=GET: the method var name. -$config->viewVar = 't'; // requestType=GET: the view var name. -$config->sessionVar = 'sid'; // requestType=GET: the session var name. - -/* Supported views. */ -$config->views = ',html,json,'; - -/* Set the wide window size. */ -$config->wideSize = 1400; - -/* Supported languages. */ -$config->langs['zh-cn'] = '中文简体'; -$config->langs['zh-tw'] = '中文繁體'; -$config->langs['en'] = 'English'; - -/* Default settings. */ -$config->default->view = 'html'; // Default view. -$config->default->lang = 'en'; // Default language. -$config->default->theme = 'default'; // Default theme. -$config->default->module = 'index'; // Default module. -$config->default->method = 'index'; // Default method. - -/* Upload settings. */ -$config->file->dangers = 'php,jsp,py,rb,asp,'; // Dangerous files. -$config->file->maxSize = 1024 * 1024; // Max size. - -/* Master database settings. */ -$config->db->persistant = false; // Pconnect or not. -$config->db->driver = 'mysql'; // Must be MySQL. Don't support other database server yet. -$config->db->encoding = 'UTF8'; // Encoding of database. -$config->db->strictMode = false; // Turn off the strict mode of MySQL. -//$config->db->emulatePrepare = true; // PDO::ATTR_EMULATE_PREPARES -//$config->db->bufferQuery = true; // PDO::MYSQL_ATTR_USE_BUFFERED_QUERY - -/* Slave database settings. */ -$config->slaveDB->persistant = false; -$config->slaveDB->driver = 'mysql'; -$config->slaveDB->encoding = 'UTF8'; -$config->slaveDB->strictMode = false; -$config->slaveDB->checkCentOS= true; - -/* Include the custom config file. */ -$configRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR; -$myConfig = $configRoot . 'my.php'; -if(file_exists($myConfig)) include $myConfig; - -/* Include extension config files. */ -$extConfigFiles = glob($configRoot . 'ext/*.php'); -foreach($extConfigFiles as $extConfigFile) include $extConfigFile; - -/* Set default table prefix. */ -if(!isset($config->db->prefix)) $config->db->prefix = 'zt_'; - -/* Define the tables. */ -define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`'); -define('TABLE_DEPT', '`' . $config->db->prefix . 'dept`'); -define('TABLE_CONFIG', '`' . $config->db->prefix . 'config`'); -define('TABLE_USER', '`' . $config->db->prefix . 'user`'); -define('TABLE_TODO', '`' . $config->db->prefix . 'todo`'); -define('TABLE_GROUP', '`' . $config->db->prefix . 'group`'); -define('TABLE_GROUPPRIV', '`' . $config->db->prefix . 'groupPriv`'); -define('TABLE_USERGROUP', '`' . $config->db->prefix . 'userGroup`'); -define('TABLE_USERQUERY', '`' . $config->db->prefix . 'userQuery`'); - -define('TABLE_BUG', '`' . $config->db->prefix . 'bug`'); -define('TABLE_CASE', '`' . $config->db->prefix . 'case`'); -define('TABLE_CASESTEP', '`' . $config->db->prefix . 'caseStep`'); -define('TABLE_TESTTASK', '`' . $config->db->prefix . 'testTask`'); -define('TABLE_TESTRUN', '`' . $config->db->prefix . 'testRun`'); -define('TABLE_TESTRESULT', '`' . $config->db->prefix . 'testResult`'); -define('TABLE_USERTPL', '`' . $config->db->prefix . 'userTPL`'); - -define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`'); -define('TABLE_STORY', '`' . $config->db->prefix . 'story`'); -define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storySpec`'); -define('TABLE_PRODUCTPLAN', '`' . $config->db->prefix . 'productPlan`'); -define('TABLE_RELEASE', '`' . $config->db->prefix . 'release`'); - -define('TABLE_PROJECT', '`' . $config->db->prefix . 'project`'); -define('TABLE_TASK', '`' . $config->db->prefix . 'task`'); -define('TABLE_TEAM', '`' . $config->db->prefix . 'team`'); -define('TABLE_PROJECTPRODUCT','`' . $config->db->prefix . 'projectProduct`'); -define('TABLE_PROJECTSTORY', '`' . $config->db->prefix . 'projectStory`'); -define('TABLE_TASKESTIMATE', '`' . $config->db->prefix . 'taskEstimate`'); -define('TABLE_EFFORT', '`' . $config->db->prefix . 'effort`'); -define('TABLE_BURN', '`' . $config->db->prefix . 'burn`'); -define('TABLE_BUILD', '`' . $config->db->prefix . 'build`'); - -define('TABLE_DOCLIB', '`' . $config->db->prefix . 'docLib`'); -define('TABLE_DOC', '`' . $config->db->prefix . 'doc`'); - -define('TABLE_MODULE', '`' . $config->db->prefix . 'module`'); -define('TABLE_ACTION', '`' . $config->db->prefix . 'action`'); -define('TABLE_FILE', '`' . $config->db->prefix . 'file`'); -define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`'); -define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`'); + + * @package config + * @version $Id$ + * @link http://www.zentao.net + */ +/* Basic settings. */ +$config->version = '3.0.beta1'; // The version of zentaopms. Don't change it. +$config->encoding = 'UTF-8'; // The encoding of znetaopms. +$config->cookieLife = time() + 2592000; // The cookie life time. +$config->timezone = 'Asia/Shanghai'; // The time zone setting, for more see http://www.php.net/manual/en/timezones.php +$config->webRoot = ''; // The root path of the pms. + +/* The request settings. */ +$config->requestType = 'PATH_INFO'; // The request type: PATH_INFO|GET, if PATH_INFO, must use url rewrite. +$config->pathType = 'clean'; // If the request type is PATH_INFO, the path type. +$config->requestFix = '-'; // The divider in the url when PATH_INFO. +$config->moduleVar = 'm'; // requestType=GET: the module var name. +$config->methodVar = 'f'; // requestType=GET: the method var name. +$config->viewVar = 't'; // requestType=GET: the view var name. +$config->sessionVar = 'sid'; // requestType=GET: the session var name. + +/* Supported views. */ +$config->views = ',html,json,'; + +/* Set the wide window size. */ +$config->wideSize = 1400; + +/* Supported languages. */ +$config->langs['zh-cn'] = '中文简体'; +$config->langs['zh-tw'] = '中文繁體'; +$config->langs['en'] = 'English'; + +/* Default settings. */ +$config->default->view = 'html'; // Default view. +$config->default->lang = 'en'; // Default language. +$config->default->theme = 'default'; // Default theme. +$config->default->module = 'index'; // Default module. +$config->default->method = 'index'; // Default method. + +/* Upload settings. */ +$config->file->dangers = 'php,jsp,py,rb,asp,'; // Dangerous files. +$config->file->maxSize = 1024 * 1024; // Max size. + +/* Master database settings. */ +$config->db->persistant = false; // Pconnect or not. +$config->db->driver = 'mysql'; // Must be MySQL. Don't support other database server yet. +$config->db->encoding = 'UTF8'; // Encoding of database. +$config->db->strictMode = false; // Turn off the strict mode of MySQL. +//$config->db->emulatePrepare = true; // PDO::ATTR_EMULATE_PREPARES +//$config->db->bufferQuery = true; // PDO::MYSQL_ATTR_USE_BUFFERED_QUERY + +/* Slave database settings. */ +$config->slaveDB->persistant = false; +$config->slaveDB->driver = 'mysql'; +$config->slaveDB->encoding = 'UTF8'; +$config->slaveDB->strictMode = false; +$config->slaveDB->checkCentOS= true; + +/* Include the custom config file. */ +$configRoot = dirname(__FILE__) . DIRECTORY_SEPARATOR; +$myConfig = $configRoot . 'my.php'; +if(file_exists($myConfig)) include $myConfig; + +/* Include extension config files. */ +$extConfigFiles = glob($configRoot . 'ext/*.php'); +foreach($extConfigFiles as $extConfigFile) include $extConfigFile; + +/* Set default table prefix. */ +if(!isset($config->db->prefix)) $config->db->prefix = 'zt_'; + +/* Define the tables. */ +define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`'); +define('TABLE_DEPT', '`' . $config->db->prefix . 'dept`'); +define('TABLE_CONFIG', '`' . $config->db->prefix . 'config`'); +define('TABLE_USER', '`' . $config->db->prefix . 'user`'); +define('TABLE_TODO', '`' . $config->db->prefix . 'todo`'); +define('TABLE_GROUP', '`' . $config->db->prefix . 'group`'); +define('TABLE_GROUPPRIV', '`' . $config->db->prefix . 'groupPriv`'); +define('TABLE_USERGROUP', '`' . $config->db->prefix . 'userGroup`'); +define('TABLE_USERQUERY', '`' . $config->db->prefix . 'userQuery`'); + +define('TABLE_BUG', '`' . $config->db->prefix . 'bug`'); +define('TABLE_CASE', '`' . $config->db->prefix . 'case`'); +define('TABLE_CASESTEP', '`' . $config->db->prefix . 'caseStep`'); +define('TABLE_TESTTASK', '`' . $config->db->prefix . 'testTask`'); +define('TABLE_TESTRUN', '`' . $config->db->prefix . 'testRun`'); +define('TABLE_TESTRESULT', '`' . $config->db->prefix . 'testResult`'); +define('TABLE_USERTPL', '`' . $config->db->prefix . 'userTPL`'); + +define('TABLE_PRODUCT', '`' . $config->db->prefix . 'product`'); +define('TABLE_STORY', '`' . $config->db->prefix . 'story`'); +define('TABLE_STORYSPEC', '`' . $config->db->prefix . 'storySpec`'); +define('TABLE_PRODUCTPLAN', '`' . $config->db->prefix . 'productPlan`'); +define('TABLE_RELEASE', '`' . $config->db->prefix . 'release`'); + +define('TABLE_PROJECT', '`' . $config->db->prefix . 'project`'); +define('TABLE_TASK', '`' . $config->db->prefix . 'task`'); +define('TABLE_TEAM', '`' . $config->db->prefix . 'team`'); +define('TABLE_PROJECTPRODUCT','`' . $config->db->prefix . 'projectProduct`'); +define('TABLE_PROJECTSTORY', '`' . $config->db->prefix . 'projectStory`'); +define('TABLE_TASKESTIMATE', '`' . $config->db->prefix . 'taskEstimate`'); +define('TABLE_EFFORT', '`' . $config->db->prefix . 'effort`'); +define('TABLE_BURN', '`' . $config->db->prefix . 'burn`'); +define('TABLE_BUILD', '`' . $config->db->prefix . 'build`'); + +define('TABLE_DOCLIB', '`' . $config->db->prefix . 'docLib`'); +define('TABLE_DOC', '`' . $config->db->prefix . 'doc`'); + +define('TABLE_MODULE', '`' . $config->db->prefix . 'module`'); +define('TABLE_ACTION', '`' . $config->db->prefix . 'action`'); +define('TABLE_FILE', '`' . $config->db->prefix . 'file`'); +define('TABLE_HISTORY', '`' . $config->db->prefix . 'history`'); +define('TABLE_EXTENSION', '`' . $config->db->prefix . 'extension`'); diff --git a/lib/api/api.class.php b/lib/api/api.class.php index 190992ef41..9c619ed673 100755 --- a/lib/api/api.class.php +++ b/lib/api/api.class.php @@ -1,1505 +1,1505 @@ - - * @package API - * @version $Id$ - * @link http://www.zentao.net - */ -class ztclient -{ - public $configFile; - public $zentao; - public $agent; - public $session; - - /** - * The construce function. - * - * @param string $zentaoRoot the zentao root url - * @param string $account the login account - * @param string $password the passwod - * @access public - * @return void - */ - public function __construct($zentaoRoot = '', $account = '', $password = '') - { - $this->agent = new snoopy(); - - /* Assign to $this->zentao. */ - $this->zentao->root = rtrim($zentaoRoot, '/') . '/'; - $this->zentao->account = $account; - $this->zentao->password = md5($password); - - /* Load the remote settings. */ - $config = $this->getRemoteConfig(); - foreach($config as $key => $value) $this->zentao->$key = $value; - - $this->startSession(); - $this->login(); - } - - /** - * Get the settings through getconfig api from remote. - * - * @access private - * @return object - */ - private function getRemoteConfig() - { - $url = $this->zentao->root . '/index.php?mode=getconfig'; - $this->agent->fetchText($url); - $config = json_decode($this->agent->results); - return $config; - } - - /** - * Set the session api. - * - * @access private - * @return string the session api url. - */ - private function setSessionAPI() - { - return $this->setControlAPI('api', 'getsessionid'); - } - - /** - * Set the login api. - * - * @access private - * @return string the login api url. - */ - private function setLoginAPI() - { - return $this->setControlAPI('user', 'login'); - } - - /** - * Set the method api. - * - * @param string $module the module name - * @param string $method the methhod name - * @param string $vars the vars to passwd - * @access private - * @return string the control api string. - */ - private function setControlAPI($module, $method, $vars = '') - { - if($this->zentao->requestType == 'GET') - { - $controlAPI = $this->appendSession($this->zentao->root); - $controlAPI .= "&{$this->zentao->moduleVar}=$module&{$this->zentao->methodVar}=$method&{$this->zentao->viewVar}=json$vars"; - } - elseif($this->zentao->requestType == 'PATH_INFO') - { - $controlAPI = $this->zentao->root . $module . $this->zentao->requestFix . $method . $this->zentao->requestFix; - if($vars) - { - $vars = parse_str($vars); - foreach($vars as $var) $controlAPI .= $var . $this->zentao->requestFix; - } - $controlAPI = rtrim($controlAPI, $this->zentao->requestFix) . '.json'; - $controlAPI = $this->appendSession($controlAPI); - } - return $controlAPI; - } - - /** - * Set the method api. - * - * @param string $module the module name - * @param string $method the methhod name - * @param string $vars the vars to passed - * @access private - * @return string the model api string. - */ - private function setModelAPI($module, $method, $vars = '') - { - $vars = str_replace('&', ',', $vars); - if($this->zentao->requestType == 'GET') - { - $modelAPI = $this->appendSession($this->zentao->root); - $modelAPI .= "&{$this->zentao->moduleVar}=api&{$this->zentao->methodVar}=getModel&{$this->zentao->viewVar}=json"; - $modelAPI .="&module=$module&method=$method¶ms=$vars"; - } - elseif($this->zentao->requestType == 'PATH_INFO') - { - $modelAPI = $this->zentao->root . 'api' . $this->zentao->requestFix . 'getmodel' . $this->zentao->requestFix; - $modelAPI .= $module . $this->zentao->requestFix . $method . $this->zentao->requestFix; - $modelAPI .= $vars; - $modelAPI = rtrim($modelAPI, $this->zentao->requestFix) . '.json'; - $modelAPI = $this->appendSession($modelAPI); - } - return $modelAPI; - } - - /** - * Start session - * - * @access public - * @return void - */ - public function startSession() - { - $this->session = null; - $this->session = $this->httpGet($this->setSessionAPI()); - } - - /** - * Login. - * - * @access public - * @return void - */ - public function login() - { - $loginAPI = $this->setLoginAPI(); - $authHash = md5($this->zentao->password . $this->session->rand); - $loginAPI .= "&account={$this->zentao->account}&password=$authHash"; - $this->httpGet($loginAPI); - } - - /** - * Fetch one method of a module's control. - * - * @param string $module the module name - * @param string $method the methhod name - * @param string $vars the vars to passwd - * @access public - * @return void - */ - public function fetch($module, $method = 'index', $vars = '') - { - return $this->httpGet($this->setControlAPI($module, $method, $vars)); - } - - /** - * Fetch one method of a module's model. - * - * @param string $module the module name - * @param string $method the methhod name - * @param string $vars the vars to passwd - * @access public - * @return void - */ - public function fetchModel($module, $method, $vars = '') - { - return $this->httpGet($this->setModelAPI($module, $method, $vars)); - } - - /** - * Get a api and check it. - * - * @param string $url - * @access private - * @return bool - */ - private function httpGet($url) - { - $this->agent->fetch($url); - $result = json_decode($this->agent->results); - if($result->status != 'success') return false; - if(isset($result->data) and md5($result->data) != $result->md5) return false; - if(isset($result->data)) return json_decode($result->data); - return true; - } - - /** - * Fetch one method of a module's control. - * - * @param string $module the module name - * @param string $method the methhod name - * @param array $vars the vars to passwd - * @access public - * @return void - */ - public function post($module, $method = 'index', $vars = array()) - { - return $this->httpPost($this->setControlAPI($module, $method), $vars); - } - - /** - * Post. - * - * @param string $url - * @access private - * @return bool - */ - private function httpPost($url, $vars) - { - $this->agent->submit($url, $vars); - $result = json_decode($this->agent->results); - if($result->status != 'success') return false; - if(isset($result->data) and md5($result->data) != $result->md5) return false; - if(isset($result->data)) return json_decode($result->data); - return true; - } - - /** - * Append session param to the url. - * - * @param string $url - * @access private - * @return string - */ - private function appendSession($url) - { - if(strrpos($url, '&') === false) $url .= '?'; - if($this->session) $url .= '&' . $this->session->sessionName . '=' . $this->session->sessionID; - return str_replace('?&', '?', $url); - } -} -?> - -Copyright (c): 1999-2008 New Digital Group, all rights reserved -Version: 1.2.4 - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -You may contact the author of Snoopy by e-mail at: -monte@ohrt.com - -The latest version of Snoopy can be obtained from: -http://snoopy.sourceforge.net/ - -*************************************************/ - -class Snoopy -{ - /**** Public variables ****/ - - /* user definable vars */ - - var $host = "www.php.net"; // host name we are connecting to - var $port = 80; // port we are connecting to - var $proxy_host = ""; // proxy host to use - var $proxy_port = ""; // proxy port to use - var $proxy_user = ""; // proxy user to use - var $proxy_pass = ""; // proxy password to use - - var $agent = "Snoopy v1.2.4"; // agent we masquerade as - var $referer = ""; // referer info to pass - var $cookies = array(); // array of cookies to pass - // $cookies["username"]="joe"; - var $rawheaders = array(); // array of raw headers to send - // $rawheaders["Content-type"]="text/html"; - - var $maxredirs = 5; // http redirection depth maximum. 0 = disallow - var $lastredirectaddr = ""; // contains address of last redirected address - var $offsiteok = true; // allows redirection off-site - var $maxframes = 0; // frame content depth maximum. 0 = disallow - var $expandlinks = true; // expand links to fully qualified URLs. - // this only applies to fetchlinks() - // submitlinks(), and submittext() - var $passcookies = true; // pass set cookies back through redirects - // NOTE: this currently does not respect - // dates, domains or paths. - - var $user = ""; // user for http authentication - var $pass = ""; // password for http authentication - - // http accept types - var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; - - var $results = ""; // where the content is put - - var $error = ""; // error messages sent here - var $response_code = ""; // response code returned from server - var $headers = array(); // headers returned from server sent here - var $maxlength = 500000; // max return data length (body) - var $read_timeout = 0; // timeout on read operations, in seconds - // supported only since PHP 4 Beta 4 - // set to 0 to disallow timeouts - var $timed_out = false; // if a read operation timed out - var $status = 0; // http request status - - var $temp_dir = "/tmp"; // temporary directory that the webserver - // has permission to write to. - // under Windows, this should be C:\temp - - var $curl_path = "/usr/local/bin/curl"; - // Snoopy will use cURL for fetching - // SSL content if a full system path to - // the cURL binary is supplied here. - // set to false if you do not have - // cURL installed. See http://curl.haxx.se - // for details on installing cURL. - // Snoopy does *not* use the cURL - // library functions built into php, - // as these functions are not stable - // as of this Snoopy release. - - /**** Private variables ****/ - - var $_maxlinelen = 4096; // max line length (headers) - - var $_httpmethod = "GET"; // default http request method - var $_httpversion = "HTTP/1.0"; // default http request version - var $_submit_method = "POST"; // default submit method - var $_submit_type = "application/x-www-form-urlencoded"; // default submit type - var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type - var $_redirectaddr = false; // will be set if page fetched is a redirect - var $_redirectdepth = 0; // increments on an http redirect - var $_frameurls = array(); // frame src urls - var $_framedepth = 0; // increments on frame depth - - var $_isproxy = false; // set if using a proxy server - var $_fp_timeout = 30; // timeout for socket connection - -/*======================================================================*\ - Function: fetch - Purpose: fetch the contents of a web page - (and possibly other protocols in the - future like ftp, nntp, gopher, etc.) - Input: $URI the location of the page to fetch - Output: $this->results the output text from the fetch -\*======================================================================*/ - - function fetch($URI) - { - - //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS); - $URI_PARTS = parse_url($URI); - if (!empty($URI_PARTS["user"])) - $this->user = $URI_PARTS["user"]; - if (!empty($URI_PARTS["pass"])) - $this->pass = $URI_PARTS["pass"]; - if (empty($URI_PARTS["query"])) - $URI_PARTS["query"] = ''; - if (empty($URI_PARTS["path"])) - $URI_PARTS["path"] = ''; - - switch(strtolower($URI_PARTS["scheme"])) - { - case "http": - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_connect($fp)) - { - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httprequest($URI,$fp,$URI,$this->_httpmethod); - } - else - { - $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httprequest($path, $fp, $URI, $this->_httpmethod); - } - - $this->_disconnect($fp); - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - $this->fetch($this->_redirectaddr); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - } - else - { - return false; - } - return true; - break; - case "https": - if(!$this->curl_path) - return false; - if(function_exists("is_executable")) - if (!is_executable($this->curl_path)) - return false; - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httpsrequest($URI,$URI,$this->_httpmethod); - } - else - { - $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httpsrequest($path, $URI, $this->_httpmethod); - } - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - $this->fetch($this->_redirectaddr); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - return true; - break; - default: - // not a valid protocol - $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; - return false; - break; - } - return true; - } - -/*======================================================================*\ - Function: submit - Purpose: submit an http form - Input: $URI the location to post the data - $formvars the formvars to use. - format: $formvars["var"] = "val"; - $formfiles an array of files to submit - format: $formfiles["var"] = "/dir/filename.ext"; - Output: $this->results the text output from the post -\*======================================================================*/ - - function submit($URI, $formvars="", $formfiles="") - { - unset($postdata); - - $postdata = $this->_prepare_post_body($formvars, $formfiles); - - $URI_PARTS = parse_url($URI); - if (!empty($URI_PARTS["user"])) - $this->user = $URI_PARTS["user"]; - if (!empty($URI_PARTS["pass"])) - $this->pass = $URI_PARTS["pass"]; - if (empty($URI_PARTS["query"])) - $URI_PARTS["query"] = ''; - if (empty($URI_PARTS["path"])) - $URI_PARTS["path"] = ''; - - switch(strtolower($URI_PARTS["scheme"])) - { - case "http": - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_connect($fp)) - { - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata); - } - else - { - $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata); - } - - $this->_disconnect($fp); - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) - $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); - - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - if( strpos( $this->_redirectaddr, "?" ) > 0 ) - $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get - else - $this->submit($this->_redirectaddr,$formvars, $formfiles); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - - } - else - { - return false; - } - return true; - break; - case "https": - if(!$this->curl_path) - return false; - if(function_exists("is_executable")) - if (!is_executable($this->curl_path)) - return false; - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata); - } - else - { - $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata); - } - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) - $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); - - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - if( strpos( $this->_redirectaddr, "?" ) > 0 ) - $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get - else - $this->submit($this->_redirectaddr,$formvars, $formfiles); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - return true; - break; - - default: - // not a valid protocol - $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; - return false; - break; - } - return true; - } - -/*======================================================================*\ - Function: fetchlinks - Purpose: fetch the links from a web page - Input: $URI where you are fetching from - Output: $this->results an array of the URLs -\*======================================================================*/ - - function fetchlinks($URI) - { - if ($this->fetch($URI)) - { - if($this->lastredirectaddr) - $URI = $this->lastredirectaddr; - if(is_array($this->results)) - { - for($x=0;$xresults);$x++) - $this->results[$x] = $this->_striplinks($this->results[$x]); - } - else - $this->results = $this->_striplinks($this->results); - - if($this->expandlinks) - $this->results = $this->_expandlinks($this->results, $URI); - return true; - } - else - return false; - } - -/*======================================================================*\ - Function: fetchform - Purpose: fetch the form elements from a web page - Input: $URI where you are fetching from - Output: $this->results the resulting html form -\*======================================================================*/ - - function fetchform($URI) - { - - if ($this->fetch($URI)) - { - - if(is_array($this->results)) - { - for($x=0;$xresults);$x++) - $this->results[$x] = $this->_stripform($this->results[$x]); - } - else - $this->results = $this->_stripform($this->results); - - return true; - } - else - return false; - } - - -/*======================================================================*\ - Function: fetchtext - Purpose: fetch the text from a web page, stripping the links - Input: $URI where you are fetching from - Output: $this->results the text from the web page -\*======================================================================*/ - - function fetchtext($URI) - { - if($this->fetch($URI)) - { - if(is_array($this->results)) - { - for($x=0;$xresults);$x++) - $this->results[$x] = $this->_striptext($this->results[$x]); - } - else - $this->results = $this->_striptext($this->results); - return true; - } - else - return false; - } - -/*======================================================================*\ - Function: submitlinks - Purpose: grab links from a form submission - Input: $URI where you are submitting from - Output: $this->results an array of the links from the post -\*======================================================================*/ - - function submitlinks($URI, $formvars="", $formfiles="") - { - if($this->submit($URI,$formvars, $formfiles)) - { - if($this->lastredirectaddr) - $URI = $this->lastredirectaddr; - if(is_array($this->results)) - { - for($x=0;$xresults);$x++) - { - $this->results[$x] = $this->_striplinks($this->results[$x]); - if($this->expandlinks) - $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); - } - } - else - { - $this->results = $this->_striplinks($this->results); - if($this->expandlinks) - $this->results = $this->_expandlinks($this->results,$URI); - } - return true; - } - else - return false; - } - -/*======================================================================*\ - Function: submittext - Purpose: grab text from a form submission - Input: $URI where you are submitting from - Output: $this->results the text from the web page -\*======================================================================*/ - - function submittext($URI, $formvars = "", $formfiles = "") - { - if($this->submit($URI,$formvars, $formfiles)) - { - if($this->lastredirectaddr) - $URI = $this->lastredirectaddr; - if(is_array($this->results)) - { - for($x=0;$xresults);$x++) - { - $this->results[$x] = $this->_striptext($this->results[$x]); - if($this->expandlinks) - $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); - } - } - else - { - $this->results = $this->_striptext($this->results); - if($this->expandlinks) - $this->results = $this->_expandlinks($this->results,$URI); - } - return true; - } - else - return false; - } - - - -/*======================================================================*\ - Function: set_submit_multipart - Purpose: Set the form submission content type to - multipart/form-data -\*======================================================================*/ - function set_submit_multipart() - { - $this->_submit_type = "multipart/form-data"; - } - - -/*======================================================================*\ - Function: set_submit_normal - Purpose: Set the form submission content type to - application/x-www-form-urlencoded -\*======================================================================*/ - function set_submit_normal() - { - $this->_submit_type = "application/x-www-form-urlencoded"; - } - - - - -/*======================================================================*\ - Private functions -\*======================================================================*/ - - -/*======================================================================*\ - Function: _striplinks - Purpose: strip the hyperlinks from an html document - Input: $document document to strip. - Output: $match an array of the links -\*======================================================================*/ - - function _striplinks($document) - { - preg_match_all("'<\s*a\s.*?href\s*=\s* # find ]+)) # if quote found, match up to next matching - # quote, otherwise match up to next space - 'isx",$document,$links); - - - // catenate the non-empty matches from the conditional subpattern - - while(list($key,$val) = each($links[2])) - { - if(!empty($val)) - $match[] = $val; - } - - while(list($key,$val) = each($links[3])) - { - if(!empty($val)) - $match[] = $val; - } - - // return the links - return $match; - } - -/*======================================================================*\ - Function: _stripform - Purpose: strip the form elements from an html document - Input: $document document to strip. - Output: $match an array of the links -\*======================================================================*/ - - function _stripform($document) - { - preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements); - - // catenate the matches - $match = implode("\r\n",$elements[0]); - - // return the links - return $match; - } - - - -/*======================================================================*\ - Function: _striptext - Purpose: strip the text from an html document - Input: $document document to strip. - Output: $text the resulting text -\*======================================================================*/ - - function _striptext($document) - { - - // I didn't use preg eval (//e) since that is only available in PHP 4.0. - // so, list your entities one by one here. I included some of the - // more common ones. - - $search = array("']*?>.*?'si", // strip out javascript - "'<[\/\!]*?[^<>]*?>'si", // strip out html tags - "'([\r\n])[\s]+'", // strip out white space - "'&(quot|#34|#034|#x22);'i", // replace html entities - "'&(amp|#38|#038|#x26);'i", // added hexadecimal values - "'&(lt|#60|#060|#x3c);'i", - "'&(gt|#62|#062|#x3e);'i", - "'&(nbsp|#160|#xa0);'i", - "'&(iexcl|#161);'i", - "'&(cent|#162);'i", - "'&(pound|#163);'i", - "'&(copy|#169);'i", - "'&(reg|#174);'i", - "'&(deg|#176);'i", - "'&(#39|#039|#x27);'", - "'&(euro|#8364);'i", // europe - "'&a(uml|UML);'", // german - "'&o(uml|UML);'", - "'&u(uml|UML);'", - "'&A(uml|UML);'", - "'&O(uml|UML);'", - "'&U(uml|UML);'", - "'ß'i", - ); - $replace = array( "", - "", - "\\1", - "\"", - "&", - "<", - ">", - " ", - chr(161), - chr(162), - chr(163), - chr(169), - chr(174), - chr(176), - chr(39), - chr(128), - "?", - "?", - "?", - "?", - "?", - "?", - "?", - ); - - $text = preg_replace($search,$replace,$document); - - return $text; - } - -/*======================================================================*\ - Function: _expandlinks - Purpose: expand each link into a fully qualified URL - Input: $links the links to qualify - $URI the full URI to get the base from - Output: $expandedLinks the expanded links -\*======================================================================*/ - - function _expandlinks($links,$URI) - { - - preg_match("/^[^\?]+/",$URI,$match); - - $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]); - $match = preg_replace("|/$|","",$match); - $match_part = parse_url($match); - $match_root = - $match_part["scheme"]."://".$match_part["host"]; - - $search = array( "|^http://".preg_quote($this->host)."|i", - "|^(\/)|i", - "|^(?!http://)(?!mailto:)|i", - "|/\./|", - "|/[^\/]+/\.\./|" - ); - - $replace = array( "", - $match_root."/", - $match."/", - "/", - "/" - ); - - $expandedLinks = preg_replace($search,$replace,$links); - - return $expandedLinks; - } - -/*======================================================================*\ - Function: _httprequest - Purpose: go get the http data from the server - Input: $url the url to fetch - $fp the current open file pointer - $URI the full URI - $body body contents to send if any (POST) - Output: -\*======================================================================*/ - - function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="") - { - $cookie_headers = ''; - if($this->passcookies && $this->_redirectaddr) - $this->setcookies(); - - $URI_PARTS = parse_url($URI); - if(empty($url)) - $url = "/"; - $headers = $http_method." ".$url." ".$this->_httpversion."\r\n"; - if(!empty($this->agent)) - $headers .= "User-Agent: ".$this->agent."\r\n"; - if(!empty($this->host) && !isset($this->rawheaders['Host'])) { - $headers .= "Host: ".$this->host; - if(!empty($this->port)) - $headers .= ":".$this->port; - $headers .= "\r\n"; - } - if(!empty($this->accept)) - $headers .= "Accept: ".$this->accept."\r\n"; - if(!empty($this->referer)) - $headers .= "Referer: ".$this->referer."\r\n"; - if(!empty($this->cookies)) - { - if(!is_array($this->cookies)) - $this->cookies = (array)$this->cookies; - - reset($this->cookies); - if ( count($this->cookies) > 0 ) { - $cookie_headers .= 'Cookie: '; - foreach ( $this->cookies as $cookieKey => $cookieVal ) { - $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; "; - } - $headers .= substr($cookie_headers,0,-2) . "\r\n"; - } - } - if(!empty($this->rawheaders)) - { - if(!is_array($this->rawheaders)) - $this->rawheaders = (array)$this->rawheaders; - while(list($headerKey,$headerVal) = each($this->rawheaders)) - $headers .= $headerKey.": ".$headerVal."\r\n"; - } - if(!empty($content_type)) { - $headers .= "Content-type: $content_type"; - if ($content_type == "multipart/form-data") - $headers .= "; boundary=".$this->_mime_boundary; - $headers .= "\r\n"; - } - if(!empty($body)) - $headers .= "Content-length: ".strlen($body)."\r\n"; - if(!empty($this->user) || !empty($this->pass)) - $headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n"; - - //add proxy auth headers - if(!empty($this->proxy_user)) - $headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n"; - - - $headers .= "\r\n"; - - // set the read timeout if needed - if ($this->read_timeout > 0) - socket_set_timeout($fp, $this->read_timeout); - $this->timed_out = false; - - fwrite($fp,$headers.$body,strlen($headers.$body)); - - $this->_redirectaddr = false; - unset($this->headers); - - while($currentHeader = fgets($fp,$this->_maxlinelen)) - { - if ($this->read_timeout > 0 && $this->_check_timeout($fp)) - { - $this->status=-100; - return false; - } - - if($currentHeader == "\r\n") - break; - - // if a header begins with Location: or URI:, set the redirect - if(preg_match("/^(Location:|URI:)/i",$currentHeader)) - { - // get URL portion of the redirect - preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches); - // look for :// in the Location header to see if hostname is included - if(!preg_match("|\:\/\/|",$matches[2])) - { - // no host in the path, so prepend - $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; - // eliminate double slash - if(!preg_match("|^/|",$matches[2])) - $this->_redirectaddr .= "/".$matches[2]; - else - $this->_redirectaddr .= $matches[2]; - } - else - $this->_redirectaddr = $matches[2]; - } - - if(preg_match("|^HTTP/|",$currentHeader)) - { - if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status)) - { - $this->status= $status[1]; - } - $this->response_code = $currentHeader; - } - - $this->headers[] = $currentHeader; - } - - $results = ''; - do { - $_data = fread($fp, $this->maxlength); - if (strlen($_data) == 0) { - break; - } - $results .= $_data; - } while(true); - - if ($this->read_timeout > 0 && $this->_check_timeout($fp)) - { - $this->status=-100; - return false; - } - - // check if there is a a redirect meta tag - - if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) - - { - $this->_redirectaddr = $this->_expandlinks($match[1],$URI); - } - - // have we hit our frame depth and is there frame src to fetch? - if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) - { - $this->results[] = $results; - for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); - } - // have we already fetched framed content? - elseif(is_array($this->results)) - $this->results[] = $results; - // no framed content - else - $this->results = $results; - - return true; - } - -/*======================================================================*\ - Function: _httpsrequest - Purpose: go get the https data from the server using curl - Input: $url the url to fetch - $URI the full URI - $body body contents to send if any (POST) - Output: -\*======================================================================*/ - - function _httpsrequest($url,$URI,$http_method,$content_type="",$body="") - { - if($this->passcookies && $this->_redirectaddr) - $this->setcookies(); - - $headers = array(); - - $URI_PARTS = parse_url($URI); - if(empty($url)) - $url = "/"; - // GET ... header not needed for curl - //$headers[] = $http_method." ".$url." ".$this->_httpversion; - if(!empty($this->agent)) - $headers[] = "User-Agent: ".$this->agent; - if(!empty($this->host)) - if(!empty($this->port)) - $headers[] = "Host: ".$this->host.":".$this->port; - else - $headers[] = "Host: ".$this->host; - if(!empty($this->accept)) - $headers[] = "Accept: ".$this->accept; - if(!empty($this->referer)) - $headers[] = "Referer: ".$this->referer; - if(!empty($this->cookies)) - { - if(!is_array($this->cookies)) - $this->cookies = (array)$this->cookies; - - reset($this->cookies); - if ( count($this->cookies) > 0 ) { - $cookie_str = 'Cookie: '; - foreach ( $this->cookies as $cookieKey => $cookieVal ) { - $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; "; - } - $headers[] = substr($cookie_str,0,-2); - } - } - if(!empty($this->rawheaders)) - { - if(!is_array($this->rawheaders)) - $this->rawheaders = (array)$this->rawheaders; - while(list($headerKey,$headerVal) = each($this->rawheaders)) - $headers[] = $headerKey.": ".$headerVal; - } - if(!empty($content_type)) { - if ($content_type == "multipart/form-data") - $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary; - else - $headers[] = "Content-type: $content_type"; - } - if(!empty($body)) - $headers[] = "Content-length: ".strlen($body); - if(!empty($this->user) || !empty($this->pass)) - $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass); - - for($curr_header = 0; $curr_header < count($headers); $curr_header++) { - $safer_header = strtr( $headers[$curr_header], "\"", " " ); - $cmdline_params .= " -H \"".$safer_header."\""; - } - - if(!empty($body)) - $cmdline_params .= " -d \"$body\""; - - if($this->read_timeout > 0) - $cmdline_params .= " -m ".$this->read_timeout; - - $headerfile = tempnam($temp_dir, "sno"); - - exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return); - - if($return) - { - $this->error = "Error: cURL could not retrieve the document, error $return."; - return false; - } - - - $results = implode("\r\n",$results); - - $result_headers = file("$headerfile"); - - $this->_redirectaddr = false; - unset($this->headers); - - for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++) - { - - // if a header begins with Location: or URI:, set the redirect - if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader])) - { - // get URL portion of the redirect - preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches); - // look for :// in the Location header to see if hostname is included - if(!preg_match("|\:\/\/|",$matches[2])) - { - // no host in the path, so prepend - $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; - // eliminate double slash - if(!preg_match("|^/|",$matches[2])) - $this->_redirectaddr .= "/".$matches[2]; - else - $this->_redirectaddr .= $matches[2]; - } - else - $this->_redirectaddr = $matches[2]; - } - - if(preg_match("|^HTTP/|",$result_headers[$currentHeader])) - $this->response_code = $result_headers[$currentHeader]; - - $this->headers[] = $result_headers[$currentHeader]; - } - - // check if there is a a redirect meta tag - - if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) - { - $this->_redirectaddr = $this->_expandlinks($match[1],$URI); - } - - // have we hit our frame depth and is there frame src to fetch? - if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) - { - $this->results[] = $results; - for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); - } - // have we already fetched framed content? - elseif(is_array($this->results)) - $this->results[] = $results; - // no framed content - else - $this->results = $results; - - unlink("$headerfile"); - - return true; - } - -/*======================================================================*\ - Function: setcookies() - Purpose: set cookies for a redirection -\*======================================================================*/ - - function setcookies() - { - for($x=0; $xheaders); $x++) - { - if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match)) - $this->cookies[$match[1]] = urldecode($match[2]); - } - } - - -/*======================================================================*\ - Function: _check_timeout - Purpose: checks whether timeout has occurred - Input: $fp file pointer -\*======================================================================*/ - - function _check_timeout($fp) - { - if ($this->read_timeout > 0) { - $fp_status = socket_get_status($fp); - if ($fp_status["timed_out"]) { - $this->timed_out = true; - return true; - } - } - return false; - } - -/*======================================================================*\ - Function: _connect - Purpose: make a socket connection - Input: $fp file pointer -\*======================================================================*/ - - function _connect(&$fp) - { - if(!empty($this->proxy_host) && !empty($this->proxy_port)) - { - $this->_isproxy = true; - - $host = $this->proxy_host; - $port = $this->proxy_port; - } - else - { - $host = $this->host; - $port = $this->port; - } - - $this->status = 0; - - if($fp = fsockopen( - $host, - $port, - $errno, - $errstr, - $this->_fp_timeout - )) - { - // socket connection succeeded - - return true; - } - else - { - // socket connection failed - $this->status = $errno; - switch($errno) - { - case -3: - $this->error="socket creation failed (-3)"; - case -4: - $this->error="dns lookup failure (-4)"; - case -5: - $this->error="connection refused or timed out (-5)"; - default: - $this->error="connection failed (".$errno.")"; - } - return false; - } - } -/*======================================================================*\ - Function: _disconnect - Purpose: disconnect a socket connection - Input: $fp file pointer -\*======================================================================*/ - - function _disconnect($fp) - { - return(fclose($fp)); - } - - -/*======================================================================*\ - Function: _prepare_post_body - Purpose: Prepare post body according to encoding type - Input: $formvars - form variables - $formfiles - form upload files - Output: post body -\*======================================================================*/ - - function _prepare_post_body($formvars, $formfiles) - { - settype($formvars, "array"); - settype($formfiles, "array"); - $postdata = ''; - - if (count($formvars) == 0 && count($formfiles) == 0) - return; - - switch ($this->_submit_type) { - case "application/x-www-form-urlencoded": - reset($formvars); - while(list($key,$val) = each($formvars)) { - if (is_array($val) || is_object($val)) { - while (list($cur_key, $cur_val) = each($val)) { - $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&"; - } - } else - $postdata .= urlencode($key)."=".urlencode($val)."&"; - } - break; - - case "multipart/form-data": - $this->_mime_boundary = "Snoopy".md5(uniqid(microtime())); - - reset($formvars); - while(list($key,$val) = each($formvars)) { - if (is_array($val) || is_object($val)) { - while (list($cur_key, $cur_val) = each($val)) { - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n"; - $postdata .= "$cur_val\r\n"; - } - } else { - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n"; - $postdata .= "$val\r\n"; - } - } - - reset($formfiles); - while (list($field_name, $file_names) = each($formfiles)) { - settype($file_names, "array"); - while (list(, $file_name) = each($file_names)) { - if (!is_readable($file_name)) continue; - - $fp = fopen($file_name, "r"); - $file_content = fread($fp, filesize($file_name)); - fclose($fp); - $base_name = basename($file_name); - - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n"; - $postdata .= "$file_content\r\n"; - } - } - $postdata .= "--".$this->_mime_boundary."--\r\n"; - break; - } - - return $postdata; - } -} -?> + + * @package API + * @version $Id$ + * @link http://www.zentao.net + */ +class ztclient +{ + public $configFile; + public $zentao; + public $agent; + public $session; + + /** + * The construce function. + * + * @param string $zentaoRoot the zentao root url + * @param string $account the login account + * @param string $password the passwod + * @access public + * @return void + */ + public function __construct($zentaoRoot = '', $account = '', $password = '') + { + $this->agent = new snoopy(); + + /* Assign to $this->zentao. */ + $this->zentao->root = rtrim($zentaoRoot, '/') . '/'; + $this->zentao->account = $account; + $this->zentao->password = md5($password); + + /* Load the remote settings. */ + $config = $this->getRemoteConfig(); + foreach($config as $key => $value) $this->zentao->$key = $value; + + $this->startSession(); + $this->login(); + } + + /** + * Get the settings through getconfig api from remote. + * + * @access private + * @return object + */ + private function getRemoteConfig() + { + $url = $this->zentao->root . '/index.php?mode=getconfig'; + $this->agent->fetchText($url); + $config = json_decode($this->agent->results); + return $config; + } + + /** + * Set the session api. + * + * @access private + * @return string the session api url. + */ + private function setSessionAPI() + { + return $this->setControlAPI('api', 'getsessionid'); + } + + /** + * Set the login api. + * + * @access private + * @return string the login api url. + */ + private function setLoginAPI() + { + return $this->setControlAPI('user', 'login'); + } + + /** + * Set the method api. + * + * @param string $module the module name + * @param string $method the methhod name + * @param string $vars the vars to passwd + * @access private + * @return string the control api string. + */ + private function setControlAPI($module, $method, $vars = '') + { + if($this->zentao->requestType == 'GET') + { + $controlAPI = $this->appendSession($this->zentao->root); + $controlAPI .= "&{$this->zentao->moduleVar}=$module&{$this->zentao->methodVar}=$method&{$this->zentao->viewVar}=json$vars"; + } + elseif($this->zentao->requestType == 'PATH_INFO') + { + $controlAPI = $this->zentao->root . $module . $this->zentao->requestFix . $method . $this->zentao->requestFix; + if($vars) + { + $vars = parse_str($vars); + foreach($vars as $var) $controlAPI .= $var . $this->zentao->requestFix; + } + $controlAPI = rtrim($controlAPI, $this->zentao->requestFix) . '.json'; + $controlAPI = $this->appendSession($controlAPI); + } + return $controlAPI; + } + + /** + * Set the method api. + * + * @param string $module the module name + * @param string $method the methhod name + * @param string $vars the vars to passed + * @access private + * @return string the model api string. + */ + private function setModelAPI($module, $method, $vars = '') + { + $vars = str_replace('&', ',', $vars); + if($this->zentao->requestType == 'GET') + { + $modelAPI = $this->appendSession($this->zentao->root); + $modelAPI .= "&{$this->zentao->moduleVar}=api&{$this->zentao->methodVar}=getModel&{$this->zentao->viewVar}=json"; + $modelAPI .="&module=$module&method=$method¶ms=$vars"; + } + elseif($this->zentao->requestType == 'PATH_INFO') + { + $modelAPI = $this->zentao->root . 'api' . $this->zentao->requestFix . 'getmodel' . $this->zentao->requestFix; + $modelAPI .= $module . $this->zentao->requestFix . $method . $this->zentao->requestFix; + $modelAPI .= $vars; + $modelAPI = rtrim($modelAPI, $this->zentao->requestFix) . '.json'; + $modelAPI = $this->appendSession($modelAPI); + } + return $modelAPI; + } + + /** + * Start session + * + * @access public + * @return void + */ + public function startSession() + { + $this->session = null; + $this->session = $this->httpGet($this->setSessionAPI()); + } + + /** + * Login. + * + * @access public + * @return void + */ + public function login() + { + $loginAPI = $this->setLoginAPI(); + $authHash = md5($this->zentao->password . $this->session->rand); + $loginAPI .= "&account={$this->zentao->account}&password=$authHash"; + $this->httpGet($loginAPI); + } + + /** + * Fetch one method of a module's control. + * + * @param string $module the module name + * @param string $method the methhod name + * @param string $vars the vars to passwd + * @access public + * @return void + */ + public function fetch($module, $method = 'index', $vars = '') + { + return $this->httpGet($this->setControlAPI($module, $method, $vars)); + } + + /** + * Fetch one method of a module's model. + * + * @param string $module the module name + * @param string $method the methhod name + * @param string $vars the vars to passwd + * @access public + * @return void + */ + public function fetchModel($module, $method, $vars = '') + { + return $this->httpGet($this->setModelAPI($module, $method, $vars)); + } + + /** + * Get a api and check it. + * + * @param string $url + * @access private + * @return bool + */ + private function httpGet($url) + { + $this->agent->fetch($url); + $result = json_decode($this->agent->results); + if($result->status != 'success') return false; + if(isset($result->data) and md5($result->data) != $result->md5) return false; + if(isset($result->data)) return json_decode($result->data); + return true; + } + + /** + * Fetch one method of a module's control. + * + * @param string $module the module name + * @param string $method the methhod name + * @param array $vars the vars to passwd + * @access public + * @return void + */ + public function post($module, $method = 'index', $vars = array()) + { + return $this->httpPost($this->setControlAPI($module, $method), $vars); + } + + /** + * Post. + * + * @param string $url + * @access private + * @return bool + */ + private function httpPost($url, $vars) + { + $this->agent->submit($url, $vars); + $result = json_decode($this->agent->results); + if($result->status != 'success') return false; + if(isset($result->data) and md5($result->data) != $result->md5) return false; + if(isset($result->data)) return json_decode($result->data); + return true; + } + + /** + * Append session param to the url. + * + * @param string $url + * @access private + * @return string + */ + private function appendSession($url) + { + if(strrpos($url, '&') === false) $url .= '?'; + if($this->session) $url .= '&' . $this->session->sessionName . '=' . $this->session->sessionID; + return str_replace('?&', '?', $url); + } +} +?> + +Copyright (c): 1999-2008 New Digital Group, all rights reserved +Version: 1.2.4 + + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +You may contact the author of Snoopy by e-mail at: +monte@ohrt.com + +The latest version of Snoopy can be obtained from: +http://snoopy.sourceforge.net/ + +*************************************************/ + +class Snoopy +{ + /**** Public variables ****/ + + /* user definable vars */ + + var $host = "www.php.net"; // host name we are connecting to + var $port = 80; // port we are connecting to + var $proxy_host = ""; // proxy host to use + var $proxy_port = ""; // proxy port to use + var $proxy_user = ""; // proxy user to use + var $proxy_pass = ""; // proxy password to use + + var $agent = "Snoopy v1.2.4"; // agent we masquerade as + var $referer = ""; // referer info to pass + var $cookies = array(); // array of cookies to pass + // $cookies["username"]="joe"; + var $rawheaders = array(); // array of raw headers to send + // $rawheaders["Content-type"]="text/html"; + + var $maxredirs = 5; // http redirection depth maximum. 0 = disallow + var $lastredirectaddr = ""; // contains address of last redirected address + var $offsiteok = true; // allows redirection off-site + var $maxframes = 0; // frame content depth maximum. 0 = disallow + var $expandlinks = true; // expand links to fully qualified URLs. + // this only applies to fetchlinks() + // submitlinks(), and submittext() + var $passcookies = true; // pass set cookies back through redirects + // NOTE: this currently does not respect + // dates, domains or paths. + + var $user = ""; // user for http authentication + var $pass = ""; // password for http authentication + + // http accept types + var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + + var $results = ""; // where the content is put + + var $error = ""; // error messages sent here + var $response_code = ""; // response code returned from server + var $headers = array(); // headers returned from server sent here + var $maxlength = 500000; // max return data length (body) + var $read_timeout = 0; // timeout on read operations, in seconds + // supported only since PHP 4 Beta 4 + // set to 0 to disallow timeouts + var $timed_out = false; // if a read operation timed out + var $status = 0; // http request status + + var $temp_dir = "/tmp"; // temporary directory that the webserver + // has permission to write to. + // under Windows, this should be C:\temp + + var $curl_path = "/usr/local/bin/curl"; + // Snoopy will use cURL for fetching + // SSL content if a full system path to + // the cURL binary is supplied here. + // set to false if you do not have + // cURL installed. See http://curl.haxx.se + // for details on installing cURL. + // Snoopy does *not* use the cURL + // library functions built into php, + // as these functions are not stable + // as of this Snoopy release. + + /**** Private variables ****/ + + var $_maxlinelen = 4096; // max line length (headers) + + var $_httpmethod = "GET"; // default http request method + var $_httpversion = "HTTP/1.0"; // default http request version + var $_submit_method = "POST"; // default submit method + var $_submit_type = "application/x-www-form-urlencoded"; // default submit type + var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type + var $_redirectaddr = false; // will be set if page fetched is a redirect + var $_redirectdepth = 0; // increments on an http redirect + var $_frameurls = array(); // frame src urls + var $_framedepth = 0; // increments on frame depth + + var $_isproxy = false; // set if using a proxy server + var $_fp_timeout = 30; // timeout for socket connection + +/*======================================================================*\ + Function: fetch + Purpose: fetch the contents of a web page + (and possibly other protocols in the + future like ftp, nntp, gopher, etc.) + Input: $URI the location of the page to fetch + Output: $this->results the output text from the fetch +\*======================================================================*/ + + function fetch($URI) + { + + //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS); + $URI_PARTS = parse_url($URI); + if (!empty($URI_PARTS["user"])) + $this->user = $URI_PARTS["user"]; + if (!empty($URI_PARTS["pass"])) + $this->pass = $URI_PARTS["pass"]; + if (empty($URI_PARTS["query"])) + $URI_PARTS["query"] = ''; + if (empty($URI_PARTS["path"])) + $URI_PARTS["path"] = ''; + + switch(strtolower($URI_PARTS["scheme"])) + { + case "http": + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_connect($fp)) + { + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httprequest($URI,$fp,$URI,$this->_httpmethod); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httprequest($path, $fp, $URI, $this->_httpmethod); + } + + $this->_disconnect($fp); + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + $this->fetch($this->_redirectaddr); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + } + else + { + return false; + } + return true; + break; + case "https": + if(!$this->curl_path) + return false; + if(function_exists("is_executable")) + if (!is_executable($this->curl_path)) + return false; + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httpsrequest($URI,$URI,$this->_httpmethod); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httpsrequest($path, $URI, $this->_httpmethod); + } + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + $this->fetch($this->_redirectaddr); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + return true; + break; + default: + // not a valid protocol + $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; + return false; + break; + } + return true; + } + +/*======================================================================*\ + Function: submit + Purpose: submit an http form + Input: $URI the location to post the data + $formvars the formvars to use. + format: $formvars["var"] = "val"; + $formfiles an array of files to submit + format: $formfiles["var"] = "/dir/filename.ext"; + Output: $this->results the text output from the post +\*======================================================================*/ + + function submit($URI, $formvars="", $formfiles="") + { + unset($postdata); + + $postdata = $this->_prepare_post_body($formvars, $formfiles); + + $URI_PARTS = parse_url($URI); + if (!empty($URI_PARTS["user"])) + $this->user = $URI_PARTS["user"]; + if (!empty($URI_PARTS["pass"])) + $this->pass = $URI_PARTS["pass"]; + if (empty($URI_PARTS["query"])) + $URI_PARTS["query"] = ''; + if (empty($URI_PARTS["path"])) + $URI_PARTS["path"] = ''; + + switch(strtolower($URI_PARTS["scheme"])) + { + case "http": + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_connect($fp)) + { + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httprequest($URI,$fp,$URI,$this->_submit_method,$this->_submit_type,$postdata); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httprequest($path, $fp, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + + $this->_disconnect($fp); + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) + $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); + + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + if( strpos( $this->_redirectaddr, "?" ) > 0 ) + $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get + else + $this->submit($this->_redirectaddr,$formvars, $formfiles); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + + } + else + { + return false; + } + return true; + break; + case "https": + if(!$this->curl_path) + return false; + if(function_exists("is_executable")) + if (!is_executable($this->curl_path)) + return false; + $this->host = $URI_PARTS["host"]; + if(!empty($URI_PARTS["port"])) + $this->port = $URI_PARTS["port"]; + if($this->_isproxy) + { + // using proxy, send entire URI + $this->_httpsrequest($URI, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + else + { + $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); + // no proxy, send only the path + $this->_httpsrequest($path, $URI, $this->_submit_method, $this->_submit_type, $postdata); + } + + if($this->_redirectaddr) + { + /* url was redirected, check if we've hit the max depth */ + if($this->maxredirs > $this->_redirectdepth) + { + if(!preg_match("|^".$URI_PARTS["scheme"]."://|", $this->_redirectaddr)) + $this->_redirectaddr = $this->_expandlinks($this->_redirectaddr,$URI_PARTS["scheme"]."://".$URI_PARTS["host"]); + + // only follow redirect if it's on this site, or offsiteok is true + if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) + { + /* follow the redirect */ + $this->_redirectdepth++; + $this->lastredirectaddr=$this->_redirectaddr; + if( strpos( $this->_redirectaddr, "?" ) > 0 ) + $this->fetch($this->_redirectaddr); // the redirect has changed the request method from post to get + else + $this->submit($this->_redirectaddr,$formvars, $formfiles); + } + } + } + + if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) + { + $frameurls = $this->_frameurls; + $this->_frameurls = array(); + + while(list(,$frameurl) = each($frameurls)) + { + if($this->_framedepth < $this->maxframes) + { + $this->fetch($frameurl); + $this->_framedepth++; + } + else + break; + } + } + return true; + break; + + default: + // not a valid protocol + $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; + return false; + break; + } + return true; + } + +/*======================================================================*\ + Function: fetchlinks + Purpose: fetch the links from a web page + Input: $URI where you are fetching from + Output: $this->results an array of the URLs +\*======================================================================*/ + + function fetchlinks($URI) + { + if ($this->fetch($URI)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$xresults);$x++) + $this->results[$x] = $this->_striplinks($this->results[$x]); + } + else + $this->results = $this->_striplinks($this->results); + + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results, $URI); + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: fetchform + Purpose: fetch the form elements from a web page + Input: $URI where you are fetching from + Output: $this->results the resulting html form +\*======================================================================*/ + + function fetchform($URI) + { + + if ($this->fetch($URI)) + { + + if(is_array($this->results)) + { + for($x=0;$xresults);$x++) + $this->results[$x] = $this->_stripform($this->results[$x]); + } + else + $this->results = $this->_stripform($this->results); + + return true; + } + else + return false; + } + + +/*======================================================================*\ + Function: fetchtext + Purpose: fetch the text from a web page, stripping the links + Input: $URI where you are fetching from + Output: $this->results the text from the web page +\*======================================================================*/ + + function fetchtext($URI) + { + if($this->fetch($URI)) + { + if(is_array($this->results)) + { + for($x=0;$xresults);$x++) + $this->results[$x] = $this->_striptext($this->results[$x]); + } + else + $this->results = $this->_striptext($this->results); + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: submitlinks + Purpose: grab links from a form submission + Input: $URI where you are submitting from + Output: $this->results an array of the links from the post +\*======================================================================*/ + + function submitlinks($URI, $formvars="", $formfiles="") + { + if($this->submit($URI,$formvars, $formfiles)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$xresults);$x++) + { + $this->results[$x] = $this->_striplinks($this->results[$x]); + if($this->expandlinks) + $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); + } + } + else + { + $this->results = $this->_striplinks($this->results); + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results,$URI); + } + return true; + } + else + return false; + } + +/*======================================================================*\ + Function: submittext + Purpose: grab text from a form submission + Input: $URI where you are submitting from + Output: $this->results the text from the web page +\*======================================================================*/ + + function submittext($URI, $formvars = "", $formfiles = "") + { + if($this->submit($URI,$formvars, $formfiles)) + { + if($this->lastredirectaddr) + $URI = $this->lastredirectaddr; + if(is_array($this->results)) + { + for($x=0;$xresults);$x++) + { + $this->results[$x] = $this->_striptext($this->results[$x]); + if($this->expandlinks) + $this->results[$x] = $this->_expandlinks($this->results[$x],$URI); + } + } + else + { + $this->results = $this->_striptext($this->results); + if($this->expandlinks) + $this->results = $this->_expandlinks($this->results,$URI); + } + return true; + } + else + return false; + } + + + +/*======================================================================*\ + Function: set_submit_multipart + Purpose: Set the form submission content type to + multipart/form-data +\*======================================================================*/ + function set_submit_multipart() + { + $this->_submit_type = "multipart/form-data"; + } + + +/*======================================================================*\ + Function: set_submit_normal + Purpose: Set the form submission content type to + application/x-www-form-urlencoded +\*======================================================================*/ + function set_submit_normal() + { + $this->_submit_type = "application/x-www-form-urlencoded"; + } + + + + +/*======================================================================*\ + Private functions +\*======================================================================*/ + + +/*======================================================================*\ + Function: _striplinks + Purpose: strip the hyperlinks from an html document + Input: $document document to strip. + Output: $match an array of the links +\*======================================================================*/ + + function _striplinks($document) + { + preg_match_all("'<\s*a\s.*?href\s*=\s* # find ]+)) # if quote found, match up to next matching + # quote, otherwise match up to next space + 'isx",$document,$links); + + + // catenate the non-empty matches from the conditional subpattern + + while(list($key,$val) = each($links[2])) + { + if(!empty($val)) + $match[] = $val; + } + + while(list($key,$val) = each($links[3])) + { + if(!empty($val)) + $match[] = $val; + } + + // return the links + return $match; + } + +/*======================================================================*\ + Function: _stripform + Purpose: strip the form elements from an html document + Input: $document document to strip. + Output: $match an array of the links +\*======================================================================*/ + + function _stripform($document) + { + preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements); + + // catenate the matches + $match = implode("\r\n",$elements[0]); + + // return the links + return $match; + } + + + +/*======================================================================*\ + Function: _striptext + Purpose: strip the text from an html document + Input: $document document to strip. + Output: $text the resulting text +\*======================================================================*/ + + function _striptext($document) + { + + // I didn't use preg eval (//e) since that is only available in PHP 4.0. + // so, list your entities one by one here. I included some of the + // more common ones. + + $search = array("']*?>.*?'si", // strip out javascript + "'<[\/\!]*?[^<>]*?>'si", // strip out html tags + "'([\r\n])[\s]+'", // strip out white space + "'&(quot|#34|#034|#x22);'i", // replace html entities + "'&(amp|#38|#038|#x26);'i", // added hexadecimal values + "'&(lt|#60|#060|#x3c);'i", + "'&(gt|#62|#062|#x3e);'i", + "'&(nbsp|#160|#xa0);'i", + "'&(iexcl|#161);'i", + "'&(cent|#162);'i", + "'&(pound|#163);'i", + "'&(copy|#169);'i", + "'&(reg|#174);'i", + "'&(deg|#176);'i", + "'&(#39|#039|#x27);'", + "'&(euro|#8364);'i", // europe + "'&a(uml|UML);'", // german + "'&o(uml|UML);'", + "'&u(uml|UML);'", + "'&A(uml|UML);'", + "'&O(uml|UML);'", + "'&U(uml|UML);'", + "'ß'i", + ); + $replace = array( "", + "", + "\\1", + "\"", + "&", + "<", + ">", + " ", + chr(161), + chr(162), + chr(163), + chr(169), + chr(174), + chr(176), + chr(39), + chr(128), + "?", + "?", + "?", + "?", + "?", + "?", + "?", + ); + + $text = preg_replace($search,$replace,$document); + + return $text; + } + +/*======================================================================*\ + Function: _expandlinks + Purpose: expand each link into a fully qualified URL + Input: $links the links to qualify + $URI the full URI to get the base from + Output: $expandedLinks the expanded links +\*======================================================================*/ + + function _expandlinks($links,$URI) + { + + preg_match("/^[^\?]+/",$URI,$match); + + $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]); + $match = preg_replace("|/$|","",$match); + $match_part = parse_url($match); + $match_root = + $match_part["scheme"]."://".$match_part["host"]; + + $search = array( "|^http://".preg_quote($this->host)."|i", + "|^(\/)|i", + "|^(?!http://)(?!mailto:)|i", + "|/\./|", + "|/[^\/]+/\.\./|" + ); + + $replace = array( "", + $match_root."/", + $match."/", + "/", + "/" + ); + + $expandedLinks = preg_replace($search,$replace,$links); + + return $expandedLinks; + } + +/*======================================================================*\ + Function: _httprequest + Purpose: go get the http data from the server + Input: $url the url to fetch + $fp the current open file pointer + $URI the full URI + $body body contents to send if any (POST) + Output: +\*======================================================================*/ + + function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="") + { + $cookie_headers = ''; + if($this->passcookies && $this->_redirectaddr) + $this->setcookies(); + + $URI_PARTS = parse_url($URI); + if(empty($url)) + $url = "/"; + $headers = $http_method." ".$url." ".$this->_httpversion."\r\n"; + if(!empty($this->agent)) + $headers .= "User-Agent: ".$this->agent."\r\n"; + if(!empty($this->host) && !isset($this->rawheaders['Host'])) { + $headers .= "Host: ".$this->host; + if(!empty($this->port)) + $headers .= ":".$this->port; + $headers .= "\r\n"; + } + if(!empty($this->accept)) + $headers .= "Accept: ".$this->accept."\r\n"; + if(!empty($this->referer)) + $headers .= "Referer: ".$this->referer."\r\n"; + if(!empty($this->cookies)) + { + if(!is_array($this->cookies)) + $this->cookies = (array)$this->cookies; + + reset($this->cookies); + if ( count($this->cookies) > 0 ) { + $cookie_headers .= 'Cookie: '; + foreach ( $this->cookies as $cookieKey => $cookieVal ) { + $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; "; + } + $headers .= substr($cookie_headers,0,-2) . "\r\n"; + } + } + if(!empty($this->rawheaders)) + { + if(!is_array($this->rawheaders)) + $this->rawheaders = (array)$this->rawheaders; + while(list($headerKey,$headerVal) = each($this->rawheaders)) + $headers .= $headerKey.": ".$headerVal."\r\n"; + } + if(!empty($content_type)) { + $headers .= "Content-type: $content_type"; + if ($content_type == "multipart/form-data") + $headers .= "; boundary=".$this->_mime_boundary; + $headers .= "\r\n"; + } + if(!empty($body)) + $headers .= "Content-length: ".strlen($body)."\r\n"; + if(!empty($this->user) || !empty($this->pass)) + $headers .= "Authorization: Basic ".base64_encode($this->user.":".$this->pass)."\r\n"; + + //add proxy auth headers + if(!empty($this->proxy_user)) + $headers .= 'Proxy-Authorization: ' . 'Basic ' . base64_encode($this->proxy_user . ':' . $this->proxy_pass)."\r\n"; + + + $headers .= "\r\n"; + + // set the read timeout if needed + if ($this->read_timeout > 0) + socket_set_timeout($fp, $this->read_timeout); + $this->timed_out = false; + + fwrite($fp,$headers.$body,strlen($headers.$body)); + + $this->_redirectaddr = false; + unset($this->headers); + + while($currentHeader = fgets($fp,$this->_maxlinelen)) + { + if ($this->read_timeout > 0 && $this->_check_timeout($fp)) + { + $this->status=-100; + return false; + } + + if($currentHeader == "\r\n") + break; + + // if a header begins with Location: or URI:, set the redirect + if(preg_match("/^(Location:|URI:)/i",$currentHeader)) + { + // get URL portion of the redirect + preg_match("/^(Location:|URI:)[ ]+(.*)/i",chop($currentHeader),$matches); + // look for :// in the Location header to see if hostname is included + if(!preg_match("|\:\/\/|",$matches[2])) + { + // no host in the path, so prepend + $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; + // eliminate double slash + if(!preg_match("|^/|",$matches[2])) + $this->_redirectaddr .= "/".$matches[2]; + else + $this->_redirectaddr .= $matches[2]; + } + else + $this->_redirectaddr = $matches[2]; + } + + if(preg_match("|^HTTP/|",$currentHeader)) + { + if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status)) + { + $this->status= $status[1]; + } + $this->response_code = $currentHeader; + } + + $this->headers[] = $currentHeader; + } + + $results = ''; + do { + $_data = fread($fp, $this->maxlength); + if (strlen($_data) == 0) { + break; + } + $results .= $_data; + } while(true); + + if ($this->read_timeout > 0 && $this->_check_timeout($fp)) + { + $this->status=-100; + return false; + } + + // check if there is a a redirect meta tag + + if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) + + { + $this->_redirectaddr = $this->_expandlinks($match[1],$URI); + } + + // have we hit our frame depth and is there frame src to fetch? + if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) + { + $this->results[] = $results; + for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); + } + // have we already fetched framed content? + elseif(is_array($this->results)) + $this->results[] = $results; + // no framed content + else + $this->results = $results; + + return true; + } + +/*======================================================================*\ + Function: _httpsrequest + Purpose: go get the https data from the server using curl + Input: $url the url to fetch + $URI the full URI + $body body contents to send if any (POST) + Output: +\*======================================================================*/ + + function _httpsrequest($url,$URI,$http_method,$content_type="",$body="") + { + if($this->passcookies && $this->_redirectaddr) + $this->setcookies(); + + $headers = array(); + + $URI_PARTS = parse_url($URI); + if(empty($url)) + $url = "/"; + // GET ... header not needed for curl + //$headers[] = $http_method." ".$url." ".$this->_httpversion; + if(!empty($this->agent)) + $headers[] = "User-Agent: ".$this->agent; + if(!empty($this->host)) + if(!empty($this->port)) + $headers[] = "Host: ".$this->host.":".$this->port; + else + $headers[] = "Host: ".$this->host; + if(!empty($this->accept)) + $headers[] = "Accept: ".$this->accept; + if(!empty($this->referer)) + $headers[] = "Referer: ".$this->referer; + if(!empty($this->cookies)) + { + if(!is_array($this->cookies)) + $this->cookies = (array)$this->cookies; + + reset($this->cookies); + if ( count($this->cookies) > 0 ) { + $cookie_str = 'Cookie: '; + foreach ( $this->cookies as $cookieKey => $cookieVal ) { + $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; "; + } + $headers[] = substr($cookie_str,0,-2); + } + } + if(!empty($this->rawheaders)) + { + if(!is_array($this->rawheaders)) + $this->rawheaders = (array)$this->rawheaders; + while(list($headerKey,$headerVal) = each($this->rawheaders)) + $headers[] = $headerKey.": ".$headerVal; + } + if(!empty($content_type)) { + if ($content_type == "multipart/form-data") + $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary; + else + $headers[] = "Content-type: $content_type"; + } + if(!empty($body)) + $headers[] = "Content-length: ".strlen($body); + if(!empty($this->user) || !empty($this->pass)) + $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass); + + for($curr_header = 0; $curr_header < count($headers); $curr_header++) { + $safer_header = strtr( $headers[$curr_header], "\"", " " ); + $cmdline_params .= " -H \"".$safer_header."\""; + } + + if(!empty($body)) + $cmdline_params .= " -d \"$body\""; + + if($this->read_timeout > 0) + $cmdline_params .= " -m ".$this->read_timeout; + + $headerfile = tempnam($temp_dir, "sno"); + + exec($this->curl_path." -k -D \"$headerfile\"".$cmdline_params." \"".escapeshellcmd($URI)."\"",$results,$return); + + if($return) + { + $this->error = "Error: cURL could not retrieve the document, error $return."; + return false; + } + + + $results = implode("\r\n",$results); + + $result_headers = file("$headerfile"); + + $this->_redirectaddr = false; + unset($this->headers); + + for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++) + { + + // if a header begins with Location: or URI:, set the redirect + if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader])) + { + // get URL portion of the redirect + preg_match("/^(Location: |URI:)\s+(.*)/",chop($result_headers[$currentHeader]),$matches); + // look for :// in the Location header to see if hostname is included + if(!preg_match("|\:\/\/|",$matches[2])) + { + // no host in the path, so prepend + $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; + // eliminate double slash + if(!preg_match("|^/|",$matches[2])) + $this->_redirectaddr .= "/".$matches[2]; + else + $this->_redirectaddr .= $matches[2]; + } + else + $this->_redirectaddr = $matches[2]; + } + + if(preg_match("|^HTTP/|",$result_headers[$currentHeader])) + $this->response_code = $result_headers[$currentHeader]; + + $this->headers[] = $result_headers[$currentHeader]; + } + + // check if there is a a redirect meta tag + + if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]*URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) + { + $this->_redirectaddr = $this->_expandlinks($match[1],$URI); + } + + // have we hit our frame depth and is there frame src to fetch? + if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) + { + $this->results[] = $results; + for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); + } + // have we already fetched framed content? + elseif(is_array($this->results)) + $this->results[] = $results; + // no framed content + else + $this->results = $results; + + unlink("$headerfile"); + + return true; + } + +/*======================================================================*\ + Function: setcookies() + Purpose: set cookies for a redirection +\*======================================================================*/ + + function setcookies() + { + for($x=0; $xheaders); $x++) + { + if(preg_match('/^set-cookie:[\s]+([^=]+)=([^;]+)/i', $this->headers[$x],$match)) + $this->cookies[$match[1]] = urldecode($match[2]); + } + } + + +/*======================================================================*\ + Function: _check_timeout + Purpose: checks whether timeout has occurred + Input: $fp file pointer +\*======================================================================*/ + + function _check_timeout($fp) + { + if ($this->read_timeout > 0) { + $fp_status = socket_get_status($fp); + if ($fp_status["timed_out"]) { + $this->timed_out = true; + return true; + } + } + return false; + } + +/*======================================================================*\ + Function: _connect + Purpose: make a socket connection + Input: $fp file pointer +\*======================================================================*/ + + function _connect(&$fp) + { + if(!empty($this->proxy_host) && !empty($this->proxy_port)) + { + $this->_isproxy = true; + + $host = $this->proxy_host; + $port = $this->proxy_port; + } + else + { + $host = $this->host; + $port = $this->port; + } + + $this->status = 0; + + if($fp = fsockopen( + $host, + $port, + $errno, + $errstr, + $this->_fp_timeout + )) + { + // socket connection succeeded + + return true; + } + else + { + // socket connection failed + $this->status = $errno; + switch($errno) + { + case -3: + $this->error="socket creation failed (-3)"; + case -4: + $this->error="dns lookup failure (-4)"; + case -5: + $this->error="connection refused or timed out (-5)"; + default: + $this->error="connection failed (".$errno.")"; + } + return false; + } + } +/*======================================================================*\ + Function: _disconnect + Purpose: disconnect a socket connection + Input: $fp file pointer +\*======================================================================*/ + + function _disconnect($fp) + { + return(fclose($fp)); + } + + +/*======================================================================*\ + Function: _prepare_post_body + Purpose: Prepare post body according to encoding type + Input: $formvars - form variables + $formfiles - form upload files + Output: post body +\*======================================================================*/ + + function _prepare_post_body($formvars, $formfiles) + { + settype($formvars, "array"); + settype($formfiles, "array"); + $postdata = ''; + + if (count($formvars) == 0 && count($formfiles) == 0) + return; + + switch ($this->_submit_type) { + case "application/x-www-form-urlencoded": + reset($formvars); + while(list($key,$val) = each($formvars)) { + if (is_array($val) || is_object($val)) { + while (list($cur_key, $cur_val) = each($val)) { + $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&"; + } + } else + $postdata .= urlencode($key)."=".urlencode($val)."&"; + } + break; + + case "multipart/form-data": + $this->_mime_boundary = "Snoopy".md5(uniqid(microtime())); + + reset($formvars); + while(list($key,$val) = each($formvars)) { + if (is_array($val) || is_object($val)) { + while (list($cur_key, $cur_val) = each($val)) { + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n"; + $postdata .= "$cur_val\r\n"; + } + } else { + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n"; + $postdata .= "$val\r\n"; + } + } + + reset($formfiles); + while (list($field_name, $file_names) = each($formfiles)) { + settype($file_names, "array"); + while (list(, $file_name) = each($file_names)) { + if (!is_readable($file_name)) continue; + + $fp = fopen($file_name, "r"); + $file_content = fread($fp, filesize($file_name)); + fclose($fp); + $base_name = basename($file_name); + + $postdata .= "--".$this->_mime_boundary."\r\n"; + $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n"; + $postdata .= "$file_content\r\n"; + } + } + $postdata .= "--".$this->_mime_boundary."--\r\n"; + break; + } + + return $postdata; + } +} +?> diff --git a/module/action/control.php b/module/action/control.php index 7182ec27b9..8c881a7c2c 100644 --- a/module/action/control.php +++ b/module/action/control.php @@ -1,66 +1,66 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -class action extends control -{ - /** - * Trash - * - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function trash($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('productList', $uri); - $this->session->set('productPlanList', $uri); - $this->session->set('releaseList', $uri); - $this->session->set('storyList', $uri); - $this->session->set('projectList', $uri); - $this->session->set('taskList', $uri); - $this->session->set('buildList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('caseList', $uri); - $this->session->set('testtaskList', $uri); - - /* Header and position. */ - $this->view->header->title = $this->lang->action->trash; - $this->view->position[] = $this->lang->action->trash; - - /* Get deleted objects. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - $this->view->trashes = $this->action->getTrashes($orderBy, $pager); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->users['system'] = 'system'; - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->display(); - } - - /** - * Undelete an object. - * - * @param int $actionID - * @access public - * @return void - */ - public function undelete($actionID) - { - $this->action->undelete($actionID); - die(js::locate(inlink('trash'), 'parent')); - } -} + + * @package action + * @version $Id$ + * @link http://www.zentao.net + */ +class action extends control +{ + /** + * Trash + * + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function trash($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('productList', $uri); + $this->session->set('productPlanList', $uri); + $this->session->set('releaseList', $uri); + $this->session->set('storyList', $uri); + $this->session->set('projectList', $uri); + $this->session->set('taskList', $uri); + $this->session->set('buildList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('caseList', $uri); + $this->session->set('testtaskList', $uri); + + /* Header and position. */ + $this->view->header->title = $this->lang->action->trash; + $this->view->position[] = $this->lang->action->trash; + + /* Get deleted objects. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + $this->view->trashes = $this->action->getTrashes($orderBy, $pager); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->users['system'] = 'system'; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->display(); + } + + /** + * Undelete an object. + * + * @param int $actionID + * @access public + * @return void + */ + public function undelete($actionID) + { + $this->action->undelete($actionID); + die(js::locate(inlink('trash'), 'parent')); + } +} diff --git a/module/action/lang/en.php b/module/action/lang/en.php index aaf6727c75..7671f1bcea 100644 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -1,181 +1,181 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->action->common = 'Logs'; -$lang->action->trash = 'Trash'; -$lang->action->undelete = 'Restore'; - -$lang->action->product = 'Product'; -$lang->action->project = 'Project'; -$lang->action->objectType = 'Object'; -$lang->action->objectID = 'ID'; -$lang->action->objectName = 'Name'; -$lang->action->actor = 'Actor'; -$lang->action->action = 'Action'; -$lang->action->actionID = 'ActionID'; -$lang->action->date = 'Date'; -$lang->action->trashTips = "Tips:The deleting actions in zentao are all logic"; - -$lang->action->dynamic->today = 'Today'; -$lang->action->dynamic->yesterday = 'Yesterday'; -$lang->action->dynamic->twoDaysAgo = 'Two days ago'; -$lang->action->dynamic->thisWeek = 'This week'; -$lang->action->dynamic->lastWeek = 'Last week'; -$lang->action->dynamic->thisMonth = 'This month'; -$lang->action->dynamic->lastMonth = 'Last month'; -$lang->action->dynamic->all = 'All'; -$lang->action->dynamic->search = 'Search'; - -$lang->action->objectTypes['product'] = 'PRODUCT'; -$lang->action->objectTypes['story'] = 'STORY'; -$lang->action->objectTypes['productplan'] = 'PLAN'; -$lang->action->objectTypes['release'] = 'RELEASE'; -$lang->action->objectTypes['project'] = 'PROJECT'; -$lang->action->objectTypes['task'] = 'TASK'; -$lang->action->objectTypes['build'] = 'Build'; -$lang->action->objectTypes['bug'] = 'Bug'; -$lang->action->objectTypes['case'] = 'Case'; -$lang->action->objectTypes['testtask'] = 'Test Task'; -$lang->action->objectTypes['user'] = 'User'; -$lang->action->objectTypes['doc'] = 'DOC'; -$lang->action->objectTypes['doclib'] = 'DocLib'; -$lang->action->objectTypes['todo'] = 'TODO'; - -/* The desc of actions. */ -$lang->action->desc->common = '$date, $action by $actor'; -$lang->action->desc->extra = '$date, $action as $extra by $actor'; -$lang->action->desc->opened = '$date, Opened by $actor.'; -$lang->action->desc->created = '$date, Created by $actor.'; -$lang->action->desc->changed = '$date, Changed by $actor.'; -$lang->action->desc->edited = '$date, Edited by $actor.'; -$lang->action->desc->assigned = '$date, $actor assigned task to $extra.' . "\n"; -$lang->action->desc->closed = '$date, Closed by $actor.'; -$lang->action->desc->deleted = '$date, Deleted by $actor.'; -$lang->action->desc->deletedfile = '$date, Deleted file by $actor, the file is $extra'; -$lang->action->desc->editfile = '$date, Edit file by $actor, the file is $extra'; -$lang->action->desc->erased = '$date, Erased by $actor.'; -$lang->action->desc->undeleted = '$date, Restored by $actor.'; -$lang->action->desc->commented = '$date, Commented by $actor.'; -$lang->action->desc->activated = '$date, Activated by $actor.'; -$lang->action->desc->moved = '$date, Moved by $actor, previouse is "$extra"'; -$lang->action->desc->confirmed = '$date, Confirmed by $actor, version is#$extra'; -$lang->action->desc->bugconfirmed = '$date, Confirmed by $actor'; -$lang->action->desc->frombug = '$date, From Bug by $actor BugID:$extra。'; -$lang->action->desc->started = '$date, Started by $actor.'; -$lang->action->desc->canceled = '$date, Canceled by $actor.'; -$lang->action->desc->svncommited = '$date, $actor commited to svn,revision is #$extra' . "\n"; -$lang->action->desc->finished = '$date, Finished by $actor.'; -$lang->action->desc->diff1 = 'Changed %s, old is "%s", new is "%s".
'; -$lang->action->desc->diff2 = 'Changed %s, the diff is:
%s
' . "\n"; -$lang->action->desc->diff3 = "Changed file's name %s to %s "; - -/* The action labels. */ -$lang->action->label->created = 'created'; -$lang->action->label->opened = 'opened'; -$lang->action->label->changed = 'changed'; -$lang->action->label->edited = 'edited'; -$lang->action->label->assigned = 'assigned'; -$lang->action->label->closed = 'closed'; -$lang->action->label->deleted = 'deleted'; -$lang->action->label->deletedfile = 'deleted file'; -$lang->action->label->editfile = 'edit file name'; -$lang->action->label->erased = 'deleted'; -$lang->action->label->undeleted = 'restore'; -$lang->action->label->commented = 'commented'; -$lang->action->label->activated = 'activated'; -$lang->action->label->resolved = 'resolved'; -$lang->action->label->reviewed = 'reviewed'; -$lang->action->label->moved = 'moded'; -$lang->action->label->confirmed = 'confirmed,'; -$lang->action->label->bugconfirmed = 'confirmed'; -$lang->action->label->tostory = 'converted to story'; -$lang->action->label->frombug = 'converted from bug'; -$lang->action->label->totask = 'converted to task'; -$lang->action->label->svncommited = 'commited code'; -$lang->action->label->linked2plan = 'link to plan'; -$lang->action->label->unlinkedfromplan = 'unlink from plan'; -$lang->action->label->linked2project = 'link to project'; -$lang->action->label->unlinkedfromproject = 'unlik from project'; -$lang->action->label->marked = 'edited'; -$lang->action->label->started = 'started'; -$lang->action->label->canceled = 'canceled'; -$lang->action->label->finished = 'finished'; -$lang->action->label->login = 'login'; -$lang->action->label->logout = "logout"; - -/* Link of every action. */ -$lang->action->label->product = 'product|product|view|productID=%s'; -$lang->action->label->productplan = 'plan|productplan|view|productID=%s'; -$lang->action->label->release = 'release|release|view|productID=%s'; -$lang->action->label->story = 'story|story|view|storyID=%s'; -$lang->action->label->project = 'project|project|view|projectID=%s'; -$lang->action->label->task = 'task|task|view|taskID=%s'; -$lang->action->label->build = 'build|build|view|buildID=%s'; -$lang->action->label->bug = 'bug|bug|view|bugID=%s'; -$lang->action->label->case = 'case|testcase|view|caseID=%s'; -$lang->action->label->testtask = 'test task|testtask|view|caseID=%s'; -$lang->action->label->todo = 'todo|todo|view|todoID=%s'; -$lang->action->label->doclib = 'doc library|doc|browse|libID=%s'; -$lang->action->label->doc = 'doc|doc|view|docID=%s'; -$lang->action->label->user = 'user'; -$lang->action->label->space = ' '; - -/* Object type. */ -$lang->action->search->objectTypeList[''] = ''; -$lang->action->search->objectTypeList['product'] = 'product'; -$lang->action->search->objectTypeList['project'] = 'project'; -$lang->action->search->objectTypeList['bug'] = 'bug'; -$lang->action->search->objectTypeList['case'] = 'case'; -$lang->action->search->objectTypeList['story'] = 'story'; -$lang->action->search->objectTypeList['task'] = 'task'; -$lang->action->search->objectTypeList['testtask'] = 'testtask'; -$lang->action->search->objectTypeList['user'] = 'user'; -$lang->action->search->objectTypeList['doc'] = 'doc'; -$lang->action->search->objectTypeList['doclib'] = 'doclib'; -$lang->action->search->objectTypeList['todo'] = 'todo'; -$lang->action->search->objectTypeList['build'] = 'build'; -$lang->action->search->objectTypeList['release'] = 'release'; -$lang->action->search->objectTypeList['productplan'] = 'productplan'; - -/* Display action for search. */ -$lang->action->search->label[''] = ''; -$lang->action->search->label['created'] = $lang->action->label->created; -$lang->action->search->label['opened'] = $lang->action->label->opened; -$lang->action->search->label['changed'] = $lang->action->label->changed; -$lang->action->search->label['edited'] = $lang->action->label->edited; -$lang->action->search->label['assigned'] = $lang->action->label->assigned; -$lang->action->search->label['closed'] = $lang->action->label->closed; -$lang->action->search->label['deleted'] = $lang->action->label->deleted; -$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; -$lang->action->search->label['editfile'] = $lang->action->label->editfile; -$lang->action->search->label['erased'] = $lang->action->label->erased; -$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; -$lang->action->search->label['commented'] = $lang->action->label->commented; -$lang->action->search->label['activated'] = $lang->action->label->activated; -$lang->action->search->label['resolved'] = $lang->action->label->resolved; -$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; -$lang->action->search->label['moved'] = $lang->action->label->moved; -$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; -$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; -$lang->action->search->label['tostory'] = $lang->action->label->tostory; -$lang->action->search->label['frombug'] = $lang->action->label->frombug; -$lang->action->search->label['totask'] = $lang->action->label->totask; -$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; -$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; -$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; -$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; -$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; -$lang->action->search->label['marked'] = $lang->action->label->marked; -$lang->action->search->label['started'] = $lang->action->label->started; -$lang->action->search->label['canceled'] = $lang->action->label->canceled; -$lang->action->search->label['finished'] = $lang->action->label->finished; -$lang->action->search->label['login'] = $lang->action->label->login; -$lang->action->search->label['logout'] = $lang->action->label->logout; + + * @package action + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->action->common = 'Logs'; +$lang->action->trash = 'Trash'; +$lang->action->undelete = 'Restore'; + +$lang->action->product = 'Product'; +$lang->action->project = 'Project'; +$lang->action->objectType = 'Object'; +$lang->action->objectID = 'ID'; +$lang->action->objectName = 'Name'; +$lang->action->actor = 'Actor'; +$lang->action->action = 'Action'; +$lang->action->actionID = 'ActionID'; +$lang->action->date = 'Date'; +$lang->action->trashTips = "Tips:The deleting actions in zentao are all logic"; + +$lang->action->dynamic->today = 'Today'; +$lang->action->dynamic->yesterday = 'Yesterday'; +$lang->action->dynamic->twoDaysAgo = 'Two days ago'; +$lang->action->dynamic->thisWeek = 'This week'; +$lang->action->dynamic->lastWeek = 'Last week'; +$lang->action->dynamic->thisMonth = 'This month'; +$lang->action->dynamic->lastMonth = 'Last month'; +$lang->action->dynamic->all = 'All'; +$lang->action->dynamic->search = 'Search'; + +$lang->action->objectTypes['product'] = 'PRODUCT'; +$lang->action->objectTypes['story'] = 'STORY'; +$lang->action->objectTypes['productplan'] = 'PLAN'; +$lang->action->objectTypes['release'] = 'RELEASE'; +$lang->action->objectTypes['project'] = 'PROJECT'; +$lang->action->objectTypes['task'] = 'TASK'; +$lang->action->objectTypes['build'] = 'Build'; +$lang->action->objectTypes['bug'] = 'Bug'; +$lang->action->objectTypes['case'] = 'Case'; +$lang->action->objectTypes['testtask'] = 'Test Task'; +$lang->action->objectTypes['user'] = 'User'; +$lang->action->objectTypes['doc'] = 'DOC'; +$lang->action->objectTypes['doclib'] = 'DocLib'; +$lang->action->objectTypes['todo'] = 'TODO'; + +/* The desc of actions. */ +$lang->action->desc->common = '$date, $action by $actor'; +$lang->action->desc->extra = '$date, $action as $extra by $actor'; +$lang->action->desc->opened = '$date, Opened by $actor.'; +$lang->action->desc->created = '$date, Created by $actor.'; +$lang->action->desc->changed = '$date, Changed by $actor.'; +$lang->action->desc->edited = '$date, Edited by $actor.'; +$lang->action->desc->assigned = '$date, $actor assigned task to $extra.' . "\n"; +$lang->action->desc->closed = '$date, Closed by $actor.'; +$lang->action->desc->deleted = '$date, Deleted by $actor.'; +$lang->action->desc->deletedfile = '$date, Deleted file by $actor, the file is $extra'; +$lang->action->desc->editfile = '$date, Edit file by $actor, the file is $extra'; +$lang->action->desc->erased = '$date, Erased by $actor.'; +$lang->action->desc->undeleted = '$date, Restored by $actor.'; +$lang->action->desc->commented = '$date, Commented by $actor.'; +$lang->action->desc->activated = '$date, Activated by $actor.'; +$lang->action->desc->moved = '$date, Moved by $actor, previouse is "$extra"'; +$lang->action->desc->confirmed = '$date, Confirmed by $actor, version is#$extra'; +$lang->action->desc->bugconfirmed = '$date, Confirmed by $actor'; +$lang->action->desc->frombug = '$date, From Bug by $actor BugID:$extra。'; +$lang->action->desc->started = '$date, Started by $actor.'; +$lang->action->desc->canceled = '$date, Canceled by $actor.'; +$lang->action->desc->svncommited = '$date, $actor commited to svn,revision is #$extra' . "\n"; +$lang->action->desc->finished = '$date, Finished by $actor.'; +$lang->action->desc->diff1 = 'Changed %s, old is "%s", new is "%s".
'; +$lang->action->desc->diff2 = 'Changed %s, the diff is:
%s
' . "\n"; +$lang->action->desc->diff3 = "Changed file's name %s to %s "; + +/* The action labels. */ +$lang->action->label->created = 'created'; +$lang->action->label->opened = 'opened'; +$lang->action->label->changed = 'changed'; +$lang->action->label->edited = 'edited'; +$lang->action->label->assigned = 'assigned'; +$lang->action->label->closed = 'closed'; +$lang->action->label->deleted = 'deleted'; +$lang->action->label->deletedfile = 'deleted file'; +$lang->action->label->editfile = 'edit file name'; +$lang->action->label->erased = 'deleted'; +$lang->action->label->undeleted = 'restore'; +$lang->action->label->commented = 'commented'; +$lang->action->label->activated = 'activated'; +$lang->action->label->resolved = 'resolved'; +$lang->action->label->reviewed = 'reviewed'; +$lang->action->label->moved = 'moded'; +$lang->action->label->confirmed = 'confirmed,'; +$lang->action->label->bugconfirmed = 'confirmed'; +$lang->action->label->tostory = 'converted to story'; +$lang->action->label->frombug = 'converted from bug'; +$lang->action->label->totask = 'converted to task'; +$lang->action->label->svncommited = 'commited code'; +$lang->action->label->linked2plan = 'link to plan'; +$lang->action->label->unlinkedfromplan = 'unlink from plan'; +$lang->action->label->linked2project = 'link to project'; +$lang->action->label->unlinkedfromproject = 'unlik from project'; +$lang->action->label->marked = 'edited'; +$lang->action->label->started = 'started'; +$lang->action->label->canceled = 'canceled'; +$lang->action->label->finished = 'finished'; +$lang->action->label->login = 'login'; +$lang->action->label->logout = "logout"; + +/* Link of every action. */ +$lang->action->label->product = 'product|product|view|productID=%s'; +$lang->action->label->productplan = 'plan|productplan|view|productID=%s'; +$lang->action->label->release = 'release|release|view|productID=%s'; +$lang->action->label->story = 'story|story|view|storyID=%s'; +$lang->action->label->project = 'project|project|view|projectID=%s'; +$lang->action->label->task = 'task|task|view|taskID=%s'; +$lang->action->label->build = 'build|build|view|buildID=%s'; +$lang->action->label->bug = 'bug|bug|view|bugID=%s'; +$lang->action->label->case = 'case|testcase|view|caseID=%s'; +$lang->action->label->testtask = 'test task|testtask|view|caseID=%s'; +$lang->action->label->todo = 'todo|todo|view|todoID=%s'; +$lang->action->label->doclib = 'doc library|doc|browse|libID=%s'; +$lang->action->label->doc = 'doc|doc|view|docID=%s'; +$lang->action->label->user = 'user'; +$lang->action->label->space = ' '; + +/* Object type. */ +$lang->action->search->objectTypeList[''] = ''; +$lang->action->search->objectTypeList['product'] = 'product'; +$lang->action->search->objectTypeList['project'] = 'project'; +$lang->action->search->objectTypeList['bug'] = 'bug'; +$lang->action->search->objectTypeList['case'] = 'case'; +$lang->action->search->objectTypeList['story'] = 'story'; +$lang->action->search->objectTypeList['task'] = 'task'; +$lang->action->search->objectTypeList['testtask'] = 'testtask'; +$lang->action->search->objectTypeList['user'] = 'user'; +$lang->action->search->objectTypeList['doc'] = 'doc'; +$lang->action->search->objectTypeList['doclib'] = 'doclib'; +$lang->action->search->objectTypeList['todo'] = 'todo'; +$lang->action->search->objectTypeList['build'] = 'build'; +$lang->action->search->objectTypeList['release'] = 'release'; +$lang->action->search->objectTypeList['productplan'] = 'productplan'; + +/* Display action for search. */ +$lang->action->search->label[''] = ''; +$lang->action->search->label['created'] = $lang->action->label->created; +$lang->action->search->label['opened'] = $lang->action->label->opened; +$lang->action->search->label['changed'] = $lang->action->label->changed; +$lang->action->search->label['edited'] = $lang->action->label->edited; +$lang->action->search->label['assigned'] = $lang->action->label->assigned; +$lang->action->search->label['closed'] = $lang->action->label->closed; +$lang->action->search->label['deleted'] = $lang->action->label->deleted; +$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; +$lang->action->search->label['editfile'] = $lang->action->label->editfile; +$lang->action->search->label['erased'] = $lang->action->label->erased; +$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; +$lang->action->search->label['commented'] = $lang->action->label->commented; +$lang->action->search->label['activated'] = $lang->action->label->activated; +$lang->action->search->label['resolved'] = $lang->action->label->resolved; +$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; +$lang->action->search->label['moved'] = $lang->action->label->moved; +$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; +$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; +$lang->action->search->label['tostory'] = $lang->action->label->tostory; +$lang->action->search->label['frombug'] = $lang->action->label->frombug; +$lang->action->search->label['totask'] = $lang->action->label->totask; +$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; +$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; +$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; +$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; +$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; +$lang->action->search->label['marked'] = $lang->action->label->marked; +$lang->action->search->label['started'] = $lang->action->label->started; +$lang->action->search->label['canceled'] = $lang->action->label->canceled; +$lang->action->search->label['finished'] = $lang->action->label->finished; +$lang->action->search->label['login'] = $lang->action->label->login; +$lang->action->search->label['logout'] = $lang->action->label->logout; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 003065bf7f..322adcba1d 100644 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -1,181 +1,181 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->action->common = '系统日志'; -$lang->action->trash = '回收站'; -$lang->action->undelete = '还原'; - -$lang->action->product = '产品'; -$lang->action->project = '项目'; -$lang->action->objectType = '对象类型'; -$lang->action->objectID = '对象ID'; -$lang->action->objectName = '对象名称'; -$lang->action->actor = '操作者'; -$lang->action->action = '动作'; -$lang->action->actionID = '记录ID'; -$lang->action->date = '日期'; -$lang->action->trashTips = '提示:为了保证系统的完整性,禅道系统的删除都是标记删除。'; - -$lang->action->dynamic->today = '今天'; -$lang->action->dynamic->yesterday = '昨天'; -$lang->action->dynamic->twoDaysAgo = '前天'; -$lang->action->dynamic->thisWeek = '本周'; -$lang->action->dynamic->lastWeek = '上周'; -$lang->action->dynamic->thisMonth = '本月'; -$lang->action->dynamic->lastMonth = '上月'; -$lang->action->dynamic->all = '所有'; -$lang->action->dynamic->search = '搜索'; - -$lang->action->objectTypes['product'] = '产品'; -$lang->action->objectTypes['story'] = '需求'; -$lang->action->objectTypes['productplan'] = '产品计划'; -$lang->action->objectTypes['release'] = '发布'; -$lang->action->objectTypes['project'] = '项目'; -$lang->action->objectTypes['task'] = '任务'; -$lang->action->objectTypes['build'] = 'Build'; -$lang->action->objectTypes['bug'] = 'Bug'; -$lang->action->objectTypes['case'] = '用例'; -$lang->action->objectTypes['testtask'] = '测试任务'; -$lang->action->objectTypes['user'] = '用户'; -$lang->action->objectTypes['doc'] = '文档'; -$lang->action->objectTypes['doclib'] = '文档库'; -$lang->action->objectTypes['todo'] = 'TODO'; - -/* 用来描述操作历史记录。*/ -$lang->action->desc->common = '$date, $action by $actor' . "\n"; -$lang->action->desc->extra = '$date, $action as $extra by $actor' . "\n"; -$lang->action->desc->opened = '$date, 由 $actor 创建。' . "\n"; -$lang->action->desc->created = '$date, 由 $actor 创建。' . "\n"; -$lang->action->desc->changed = '$date, 由 $actor 变更。' . "\n"; -$lang->action->desc->edited = '$date, 由 $actor 编辑。' . "\n"; -$lang->action->desc->assigned = '$date, 由 $actor 指派给 $extra' . "\n"; -$lang->action->desc->closed = '$date, 由 $actor 关闭。' . "\n"; -$lang->action->desc->deleted = '$date, 由 $actor 删除。' . "\n"; -$lang->action->desc->deletedfile = '$date, 由 $actor 删除了附件:$extra' . "\n"; -$lang->action->desc->editfile = '$date, 由 $actor 编辑了附件:$extra' . "\n"; -$lang->action->desc->erased = '$date, 由 $actor 删除。' . "\n"; -$lang->action->desc->undeleted = '$date, 由 $actor 还原。' . "\n"; -$lang->action->desc->commented = '$date, 由 $actor 添加备注。' . "\n"; -$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; -$lang->action->desc->moved = '$date, 由 $actor 移动,之前为 "$extra"' . "\n"; -$lang->action->desc->confirmed = '$date, 由 $actor 确认需求变动,最新版本为#$extra' . "\n"; -$lang->action->desc->bugconfirmed = '$date, 由 $actor 确认Bug' . "\n"; -$lang->action->desc->frombug = '$date, 由 $actor Bug转化而来,Bug编号为 $extra。'; -$lang->action->desc->started = '$date, 由 $actor 启动。' . "\n"; -$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; -$lang->action->desc->svncommited = '$date, 由 $actor 提交代码,版本为#$extra' . "\n"; -$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; -$lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
' . "\n"; -$lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . '
%s
' . "\n"; -$lang->action->desc->diff3 = '将文件名 %s 改为 %s ' . "\n"; - -/* 用来显示动态信息。*/ -$lang->action->label->created = '创建了'; -$lang->action->label->opened = '创建了'; -$lang->action->label->changed = '变更了'; -$lang->action->label->edited = '编辑了'; -$lang->action->label->assigned = '指派了'; -$lang->action->label->closed = '关闭了'; -$lang->action->label->deleted = '删除了'; -$lang->action->label->deletedfile = '删除附件'; -$lang->action->label->editfile = '编辑附件'; -$lang->action->label->erased = '删除了'; -$lang->action->label->undeleted = '还原了'; -$lang->action->label->commented = '评论了'; -$lang->action->label->activated = '激活了'; -$lang->action->label->resolved = '解决了'; -$lang->action->label->reviewed = '评审了'; -$lang->action->label->moved = '移动了'; -$lang->action->label->confirmed = '确认了需求,'; -$lang->action->label->bugconfirmed = '确认了'; -$lang->action->label->tostory = '转需求'; -$lang->action->label->frombug = '转需求'; -$lang->action->label->totask = '转任务'; -$lang->action->label->svncommited = '提交代码'; -$lang->action->label->linked2plan = '关联计划'; -$lang->action->label->unlinkedfromplan = '移除计划'; -$lang->action->label->linked2project = '关联项目'; -$lang->action->label->unlinkedfromproject = '移除项目'; -$lang->action->label->marked = '编辑了'; -$lang->action->label->started = '开始了'; -$lang->action->label->canceled = '取消了'; -$lang->action->label->finished = '完成了'; -$lang->action->label->login = '登录系统'; -$lang->action->label->logout = "退出登录"; - -/* 用来生成相应对象的链接。*/ -$lang->action->label->product = '产品|product|view|productID=%s'; -$lang->action->label->productplan = '计划|productplan|view|productID=%s'; -$lang->action->label->release = '发布|release|view|productID=%s'; -$lang->action->label->story = '需求|story|view|storyID=%s'; -$lang->action->label->project = '项目|project|view|projectID=%s'; -$lang->action->label->task = '任务|task|view|taskID=%s'; -$lang->action->label->build = 'Build|build|view|buildID=%s'; -$lang->action->label->bug = 'Bug|bug|view|bugID=%s'; -$lang->action->label->case = '用例|testcase|view|caseID=%s'; -$lang->action->label->testtask = '测试任务|testtask|view|caseID=%s'; -$lang->action->label->todo = 'todo|todo|view|todoID=%s'; -$lang->action->label->doclib = '文档库|doc|browse|libID=%s'; -$lang->action->label->doc = '文档|doc|view|docID=%s'; -$lang->action->label->user = '用户'; -$lang->action->label->space = ' '; - -/* Object type. */ -$lang->action->search->objectTypeList[''] = ''; -$lang->action->search->objectTypeList['product'] = '产品'; -$lang->action->search->objectTypeList['project'] = '项目'; -$lang->action->search->objectTypeList['bug'] = 'Bug'; -$lang->action->search->objectTypeList['case'] = '用例'; -$lang->action->search->objectTypeList['story'] = '需求'; -$lang->action->search->objectTypeList['task'] = '任务'; -$lang->action->search->objectTypeList['testtask'] = '测试任务'; -$lang->action->search->objectTypeList['user'] = '用户'; -$lang->action->search->objectTypeList['doc'] = '文档'; -$lang->action->search->objectTypeList['doclib'] = '文档库'; -$lang->action->search->objectTypeList['todo'] = 'TODO'; -$lang->action->search->objectTypeList['build'] = 'Build'; -$lang->action->search->objectTypeList['release'] = '发布'; -$lang->action->search->objectTypeList['productplan'] = '计划'; - -/* 用来在动态显示中显示动作 */ -$lang->action->search->label[''] = ''; -$lang->action->search->label['created'] = $lang->action->label->created; -$lang->action->search->label['opened'] = $lang->action->label->opened; -$lang->action->search->label['changed'] = $lang->action->label->changed; -$lang->action->search->label['edited'] = $lang->action->label->edited; -$lang->action->search->label['assigned'] = $lang->action->label->assigned; -$lang->action->search->label['closed'] = $lang->action->label->closed; -$lang->action->search->label['deleted'] = $lang->action->label->deleted; -$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; -$lang->action->search->label['editfile'] = $lang->action->label->editfile; -$lang->action->search->label['erased'] = $lang->action->label->erased; -$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; -$lang->action->search->label['commented'] = $lang->action->label->commented; -$lang->action->search->label['activated'] = $lang->action->label->activated; -$lang->action->search->label['resolved'] = $lang->action->label->resolved; -$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; -$lang->action->search->label['moved'] = $lang->action->label->moved; -$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; -$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; -$lang->action->search->label['tostory'] = $lang->action->label->tostory; -$lang->action->search->label['frombug'] = $lang->action->label->frombug; -$lang->action->search->label['totask'] = $lang->action->label->totask; -$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; -$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; -$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; -$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; -$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; -$lang->action->search->label['marked'] = $lang->action->label->marked; -$lang->action->search->label['started'] = $lang->action->label->started; -$lang->action->search->label['canceled'] = $lang->action->label->canceled; -$lang->action->search->label['finished'] = $lang->action->label->finished; -$lang->action->search->label['login'] = $lang->action->label->login; -$lang->action->search->label['logout'] = $lang->action->label->logout; + + * @package action + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->action->common = '系统日志'; +$lang->action->trash = '回收站'; +$lang->action->undelete = '还原'; + +$lang->action->product = '产品'; +$lang->action->project = '项目'; +$lang->action->objectType = '对象类型'; +$lang->action->objectID = '对象ID'; +$lang->action->objectName = '对象名称'; +$lang->action->actor = '操作者'; +$lang->action->action = '动作'; +$lang->action->actionID = '记录ID'; +$lang->action->date = '日期'; +$lang->action->trashTips = '提示:为了保证系统的完整性,禅道系统的删除都是标记删除。'; + +$lang->action->dynamic->today = '今天'; +$lang->action->dynamic->yesterday = '昨天'; +$lang->action->dynamic->twoDaysAgo = '前天'; +$lang->action->dynamic->thisWeek = '本周'; +$lang->action->dynamic->lastWeek = '上周'; +$lang->action->dynamic->thisMonth = '本月'; +$lang->action->dynamic->lastMonth = '上月'; +$lang->action->dynamic->all = '所有'; +$lang->action->dynamic->search = '搜索'; + +$lang->action->objectTypes['product'] = '产品'; +$lang->action->objectTypes['story'] = '需求'; +$lang->action->objectTypes['productplan'] = '产品计划'; +$lang->action->objectTypes['release'] = '发布'; +$lang->action->objectTypes['project'] = '项目'; +$lang->action->objectTypes['task'] = '任务'; +$lang->action->objectTypes['build'] = 'Build'; +$lang->action->objectTypes['bug'] = 'Bug'; +$lang->action->objectTypes['case'] = '用例'; +$lang->action->objectTypes['testtask'] = '测试任务'; +$lang->action->objectTypes['user'] = '用户'; +$lang->action->objectTypes['doc'] = '文档'; +$lang->action->objectTypes['doclib'] = '文档库'; +$lang->action->objectTypes['todo'] = 'TODO'; + +/* 用来描述操作历史记录。*/ +$lang->action->desc->common = '$date, $action by $actor' . "\n"; +$lang->action->desc->extra = '$date, $action as $extra by $actor' . "\n"; +$lang->action->desc->opened = '$date, 由 $actor 创建。' . "\n"; +$lang->action->desc->created = '$date, 由 $actor 创建。' . "\n"; +$lang->action->desc->changed = '$date, 由 $actor 变更。' . "\n"; +$lang->action->desc->edited = '$date, 由 $actor 编辑。' . "\n"; +$lang->action->desc->assigned = '$date, 由 $actor 指派给 $extra' . "\n"; +$lang->action->desc->closed = '$date, 由 $actor 关闭。' . "\n"; +$lang->action->desc->deleted = '$date, 由 $actor 删除。' . "\n"; +$lang->action->desc->deletedfile = '$date, 由 $actor 删除了附件:$extra' . "\n"; +$lang->action->desc->editfile = '$date, 由 $actor 编辑了附件:$extra' . "\n"; +$lang->action->desc->erased = '$date, 由 $actor 删除。' . "\n"; +$lang->action->desc->undeleted = '$date, 由 $actor 还原。' . "\n"; +$lang->action->desc->commented = '$date, 由 $actor 添加备注。' . "\n"; +$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; +$lang->action->desc->moved = '$date, 由 $actor 移动,之前为 "$extra"' . "\n"; +$lang->action->desc->confirmed = '$date, 由 $actor 确认需求变动,最新版本为#$extra' . "\n"; +$lang->action->desc->bugconfirmed = '$date, 由 $actor 确认Bug' . "\n"; +$lang->action->desc->frombug = '$date, 由 $actor Bug转化而来,Bug编号为 $extra。'; +$lang->action->desc->started = '$date, 由 $actor 启动。' . "\n"; +$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; +$lang->action->desc->svncommited = '$date, 由 $actor 提交代码,版本为#$extra' . "\n"; +$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; +$lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
' . "\n"; +$lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . '
%s
' . "\n"; +$lang->action->desc->diff3 = '将文件名 %s 改为 %s ' . "\n"; + +/* 用来显示动态信息。*/ +$lang->action->label->created = '创建了'; +$lang->action->label->opened = '创建了'; +$lang->action->label->changed = '变更了'; +$lang->action->label->edited = '编辑了'; +$lang->action->label->assigned = '指派了'; +$lang->action->label->closed = '关闭了'; +$lang->action->label->deleted = '删除了'; +$lang->action->label->deletedfile = '删除附件'; +$lang->action->label->editfile = '编辑附件'; +$lang->action->label->erased = '删除了'; +$lang->action->label->undeleted = '还原了'; +$lang->action->label->commented = '评论了'; +$lang->action->label->activated = '激活了'; +$lang->action->label->resolved = '解决了'; +$lang->action->label->reviewed = '评审了'; +$lang->action->label->moved = '移动了'; +$lang->action->label->confirmed = '确认了需求,'; +$lang->action->label->bugconfirmed = '确认了'; +$lang->action->label->tostory = '转需求'; +$lang->action->label->frombug = '转需求'; +$lang->action->label->totask = '转任务'; +$lang->action->label->svncommited = '提交代码'; +$lang->action->label->linked2plan = '关联计划'; +$lang->action->label->unlinkedfromplan = '移除计划'; +$lang->action->label->linked2project = '关联项目'; +$lang->action->label->unlinkedfromproject = '移除项目'; +$lang->action->label->marked = '编辑了'; +$lang->action->label->started = '开始了'; +$lang->action->label->canceled = '取消了'; +$lang->action->label->finished = '完成了'; +$lang->action->label->login = '登录系统'; +$lang->action->label->logout = "退出登录"; + +/* 用来生成相应对象的链接。*/ +$lang->action->label->product = '产品|product|view|productID=%s'; +$lang->action->label->productplan = '计划|productplan|view|productID=%s'; +$lang->action->label->release = '发布|release|view|productID=%s'; +$lang->action->label->story = '需求|story|view|storyID=%s'; +$lang->action->label->project = '项目|project|view|projectID=%s'; +$lang->action->label->task = '任务|task|view|taskID=%s'; +$lang->action->label->build = 'Build|build|view|buildID=%s'; +$lang->action->label->bug = 'Bug|bug|view|bugID=%s'; +$lang->action->label->case = '用例|testcase|view|caseID=%s'; +$lang->action->label->testtask = '测试任务|testtask|view|caseID=%s'; +$lang->action->label->todo = 'todo|todo|view|todoID=%s'; +$lang->action->label->doclib = '文档库|doc|browse|libID=%s'; +$lang->action->label->doc = '文档|doc|view|docID=%s'; +$lang->action->label->user = '用户'; +$lang->action->label->space = ' '; + +/* Object type. */ +$lang->action->search->objectTypeList[''] = ''; +$lang->action->search->objectTypeList['product'] = '产品'; +$lang->action->search->objectTypeList['project'] = '项目'; +$lang->action->search->objectTypeList['bug'] = 'Bug'; +$lang->action->search->objectTypeList['case'] = '用例'; +$lang->action->search->objectTypeList['story'] = '需求'; +$lang->action->search->objectTypeList['task'] = '任务'; +$lang->action->search->objectTypeList['testtask'] = '测试任务'; +$lang->action->search->objectTypeList['user'] = '用户'; +$lang->action->search->objectTypeList['doc'] = '文档'; +$lang->action->search->objectTypeList['doclib'] = '文档库'; +$lang->action->search->objectTypeList['todo'] = 'TODO'; +$lang->action->search->objectTypeList['build'] = 'Build'; +$lang->action->search->objectTypeList['release'] = '发布'; +$lang->action->search->objectTypeList['productplan'] = '计划'; + +/* 用来在动态显示中显示动作 */ +$lang->action->search->label[''] = ''; +$lang->action->search->label['created'] = $lang->action->label->created; +$lang->action->search->label['opened'] = $lang->action->label->opened; +$lang->action->search->label['changed'] = $lang->action->label->changed; +$lang->action->search->label['edited'] = $lang->action->label->edited; +$lang->action->search->label['assigned'] = $lang->action->label->assigned; +$lang->action->search->label['closed'] = $lang->action->label->closed; +$lang->action->search->label['deleted'] = $lang->action->label->deleted; +$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; +$lang->action->search->label['editfile'] = $lang->action->label->editfile; +$lang->action->search->label['erased'] = $lang->action->label->erased; +$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; +$lang->action->search->label['commented'] = $lang->action->label->commented; +$lang->action->search->label['activated'] = $lang->action->label->activated; +$lang->action->search->label['resolved'] = $lang->action->label->resolved; +$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; +$lang->action->search->label['moved'] = $lang->action->label->moved; +$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; +$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; +$lang->action->search->label['tostory'] = $lang->action->label->tostory; +$lang->action->search->label['frombug'] = $lang->action->label->frombug; +$lang->action->search->label['totask'] = $lang->action->label->totask; +$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; +$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; +$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; +$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; +$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; +$lang->action->search->label['marked'] = $lang->action->label->marked; +$lang->action->search->label['started'] = $lang->action->label->started; +$lang->action->search->label['canceled'] = $lang->action->label->canceled; +$lang->action->search->label['finished'] = $lang->action->label->finished; +$lang->action->search->label['login'] = $lang->action->label->login; +$lang->action->search->label['logout'] = $lang->action->label->logout; diff --git a/module/action/lang/zh-tw.php b/module/action/lang/zh-tw.php index 54719a6862..6dae1cd6b6 100644 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -1,181 +1,181 @@ - - * @package action - * @version $Id: zh-tw.php 2528 2012-01-04 00:33:25Z wwccss $ - * @link http://www.zentao.net - */ -$lang->action->common = '系統日誌'; -$lang->action->trash = '資源回收筒'; -$lang->action->undelete = '還原'; - -$lang->action->product = '產品'; -$lang->action->project = '項目'; -$lang->action->objectType = '對象類型'; -$lang->action->objectID = '對象ID'; -$lang->action->objectName = '對象名稱'; -$lang->action->actor = '操作者'; -$lang->action->action = '動作'; -$lang->action->actionID = '記錄ID'; -$lang->action->date = '日期'; -$lang->action->trashTips = '提示:為了保證系統的完整性,禪道系統的刪除都是標記刪除。'; - -$lang->action->dynamic->today = '今天'; -$lang->action->dynamic->yesterday = '昨天'; -$lang->action->dynamic->twoDaysAgo = '前天'; -$lang->action->dynamic->thisWeek = '本週'; -$lang->action->dynamic->lastWeek = '上周'; -$lang->action->dynamic->thisMonth = '本月'; -$lang->action->dynamic->lastMonth = '上月'; -$lang->action->dynamic->all = '所有'; -$lang->action->dynamic->search = '搜索'; - -$lang->action->objectTypes['product'] = '產品'; -$lang->action->objectTypes['story'] = '需求'; -$lang->action->objectTypes['productplan'] = '產品計劃'; -$lang->action->objectTypes['release'] = '發佈'; -$lang->action->objectTypes['project'] = '項目'; -$lang->action->objectTypes['task'] = '任務'; -$lang->action->objectTypes['build'] = 'Build'; -$lang->action->objectTypes['bug'] = 'Bug'; -$lang->action->objectTypes['case'] = '用例'; -$lang->action->objectTypes['testtask'] = '測試任務'; -$lang->action->objectTypes['user'] = '用戶'; -$lang->action->objectTypes['doc'] = '文檔'; -$lang->action->objectTypes['doclib'] = '文檔庫'; -$lang->action->objectTypes['todo'] = 'TODO'; - -/* 用來描述操作歷史記錄。*/ -$lang->action->desc->common = '$date, $action by $actor' . "\n"; -$lang->action->desc->extra = '$date, $action as $extra by $actor' . "\n"; -$lang->action->desc->opened = '$date, 由 $actor 創建。' . "\n"; -$lang->action->desc->created = '$date, 由 $actor 創建。' . "\n"; -$lang->action->desc->changed = '$date, 由 $actor 變更。' . "\n"; -$lang->action->desc->edited = '$date, 由 $actor 編輯。' . "\n"; -$lang->action->desc->assigned = '$date, 由 $actor 指派給 $extra' . "\n"; -$lang->action->desc->closed = '$date, 由 $actor 關閉。' . "\n"; -$lang->action->desc->deleted = '$date, 由 $actor 刪除。' . "\n"; -$lang->action->desc->deletedfile = '$date, 由 $actor 刪除了附件:$extra' . "\n"; -$lang->action->desc->editfile = '$date, 由 $actor 編輯了附件:$extra' . "\n"; -$lang->action->desc->erased = '$date, 由 $actor 刪除。' . "\n"; -$lang->action->desc->undeleted = '$date, 由 $actor 還原。' . "\n"; -$lang->action->desc->commented = '$date, 由 $actor 添加備註。' . "\n"; -$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; -$lang->action->desc->moved = '$date, 由 $actor 移動,之前為 "$extra"' . "\n"; -$lang->action->desc->confirmed = '$date, 由 $actor 確認需求變動,最新版本為#$extra' . "\n"; -$lang->action->desc->bugconfirmed = '$date, 由 $actor 確認Bug' . "\n"; -$lang->action->desc->frombug = '$date, 由 $actor Bug轉化而來,Bug編號為 $extra。'; -$lang->action->desc->started = '$date, 由 $actor 啟動。' . "\n"; -$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; -$lang->action->desc->svncommited = '$date, 由 $actor 提交代碼,版本為#$extra' . "\n"; -$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; -$lang->action->desc->diff1 = '修改了 %s,舊值為 "%s",新值為 "%s"。
' . "\n"; -$lang->action->desc->diff2 = '修改了 %s,區別為:' . "\n" . '
%s
' . "\n"; -$lang->action->desc->diff3 = '將檔案名 %s 改為 %s ' . "\n"; - -/* 用來顯示動態信息。*/ -$lang->action->label->created = '創建了'; -$lang->action->label->opened = '創建了'; -$lang->action->label->changed = '變更了'; -$lang->action->label->edited = '編輯了'; -$lang->action->label->assigned = '指派了'; -$lang->action->label->closed = '關閉了'; -$lang->action->label->deleted = '刪除了'; -$lang->action->label->deletedfile = '刪除附件'; -$lang->action->label->editfile = '編輯附件'; -$lang->action->label->erased = '刪除了'; -$lang->action->label->undeleted = '還原了'; -$lang->action->label->commented = '評論了'; -$lang->action->label->activated = '激活了'; -$lang->action->label->resolved = '解決了'; -$lang->action->label->reviewed = '評審了'; -$lang->action->label->moved = '移動了'; -$lang->action->label->confirmed = '確認了需求,'; -$lang->action->label->bugconfirmed = '確認了'; -$lang->action->label->tostory = '轉需求'; -$lang->action->label->frombug = '轉需求'; -$lang->action->label->totask = '轉任務'; -$lang->action->label->svncommited = '提交代碼'; -$lang->action->label->linked2plan = '關聯計劃'; -$lang->action->label->unlinkedfromplan = '移除計劃'; -$lang->action->label->linked2project = '關聯項目'; -$lang->action->label->unlinkedfromproject = '移除項目'; -$lang->action->label->marked = '編輯了'; -$lang->action->label->started = '開始了'; -$lang->action->label->canceled = '取消了'; -$lang->action->label->finished = '完成了'; -$lang->action->label->login = '登錄系統'; -$lang->action->label->logout = "退出登錄"; - -/* 用來生成相應對象的連結。*/ -$lang->action->label->product = '產品|product|view|productID=%s'; -$lang->action->label->productplan = '計劃|productplan|view|productID=%s'; -$lang->action->label->release = '發佈|release|view|productID=%s'; -$lang->action->label->story = '需求|story|view|storyID=%s'; -$lang->action->label->project = '項目|project|view|projectID=%s'; -$lang->action->label->task = '任務|task|view|taskID=%s'; -$lang->action->label->build = 'Build|build|view|buildID=%s'; -$lang->action->label->bug = 'Bug|bug|view|bugID=%s'; -$lang->action->label->case = '用例|testcase|view|caseID=%s'; -$lang->action->label->testtask = '測試任務|testtask|view|caseID=%s'; -$lang->action->label->todo = 'todo|todo|view|todoID=%s'; -$lang->action->label->doclib = '文檔庫|doc|browse|libID=%s'; -$lang->action->label->doc = '文檔|doc|view|docID=%s'; -$lang->action->label->user = '用戶'; -$lang->action->label->space = ' '; - -/* Object type. */ -$lang->action->search->objectTypeList[''] = ''; -$lang->action->search->objectTypeList['product'] = '產品'; -$lang->action->search->objectTypeList['project'] = '項目'; -$lang->action->search->objectTypeList['bug'] = 'Bug'; -$lang->action->search->objectTypeList['case'] = '用例'; -$lang->action->search->objectTypeList['story'] = '需求'; -$lang->action->search->objectTypeList['task'] = '任務'; -$lang->action->search->objectTypeList['testtask'] = '測試任務'; -$lang->action->search->objectTypeList['user'] = '用戶'; -$lang->action->search->objectTypeList['doc'] = '文檔'; -$lang->action->search->objectTypeList['doclib'] = '文檔庫'; -$lang->action->search->objectTypeList['todo'] = 'TODO'; -$lang->action->search->objectTypeList['build'] = 'Build'; -$lang->action->search->objectTypeList['release'] = '發佈'; -$lang->action->search->objectTypeList['productplan'] = '計劃'; - -/* 用來在動態顯示中顯示動作 */ -$lang->action->search->label[''] = ''; -$lang->action->search->label['created'] = $lang->action->label->created; -$lang->action->search->label['opened'] = $lang->action->label->opened; -$lang->action->search->label['changed'] = $lang->action->label->changed; -$lang->action->search->label['edited'] = $lang->action->label->edited; -$lang->action->search->label['assigned'] = $lang->action->label->assigned; -$lang->action->search->label['closed'] = $lang->action->label->closed; -$lang->action->search->label['deleted'] = $lang->action->label->deleted; -$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; -$lang->action->search->label['editfile'] = $lang->action->label->editfile; -$lang->action->search->label['erased'] = $lang->action->label->erased; -$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; -$lang->action->search->label['commented'] = $lang->action->label->commented; -$lang->action->search->label['activated'] = $lang->action->label->activated; -$lang->action->search->label['resolved'] = $lang->action->label->resolved; -$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; -$lang->action->search->label['moved'] = $lang->action->label->moved; -$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; -$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; -$lang->action->search->label['tostory'] = $lang->action->label->tostory; -$lang->action->search->label['frombug'] = $lang->action->label->frombug; -$lang->action->search->label['totask'] = $lang->action->label->totask; -$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; -$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; -$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; -$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; -$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; -$lang->action->search->label['marked'] = $lang->action->label->marked; -$lang->action->search->label['started'] = $lang->action->label->started; -$lang->action->search->label['canceled'] = $lang->action->label->canceled; -$lang->action->search->label['finished'] = $lang->action->label->finished; -$lang->action->search->label['login'] = $lang->action->label->login; -$lang->action->search->label['logout'] = $lang->action->label->logout; + + * @package action + * @version $Id: zh-tw.php 2528 2012-01-04 00:33:25Z wwccss $ + * @link http://www.zentao.net + */ +$lang->action->common = '系統日誌'; +$lang->action->trash = '資源回收筒'; +$lang->action->undelete = '還原'; + +$lang->action->product = '產品'; +$lang->action->project = '項目'; +$lang->action->objectType = '對象類型'; +$lang->action->objectID = '對象ID'; +$lang->action->objectName = '對象名稱'; +$lang->action->actor = '操作者'; +$lang->action->action = '動作'; +$lang->action->actionID = '記錄ID'; +$lang->action->date = '日期'; +$lang->action->trashTips = '提示:為了保證系統的完整性,禪道系統的刪除都是標記刪除。'; + +$lang->action->dynamic->today = '今天'; +$lang->action->dynamic->yesterday = '昨天'; +$lang->action->dynamic->twoDaysAgo = '前天'; +$lang->action->dynamic->thisWeek = '本週'; +$lang->action->dynamic->lastWeek = '上周'; +$lang->action->dynamic->thisMonth = '本月'; +$lang->action->dynamic->lastMonth = '上月'; +$lang->action->dynamic->all = '所有'; +$lang->action->dynamic->search = '搜索'; + +$lang->action->objectTypes['product'] = '產品'; +$lang->action->objectTypes['story'] = '需求'; +$lang->action->objectTypes['productplan'] = '產品計劃'; +$lang->action->objectTypes['release'] = '發佈'; +$lang->action->objectTypes['project'] = '項目'; +$lang->action->objectTypes['task'] = '任務'; +$lang->action->objectTypes['build'] = 'Build'; +$lang->action->objectTypes['bug'] = 'Bug'; +$lang->action->objectTypes['case'] = '用例'; +$lang->action->objectTypes['testtask'] = '測試任務'; +$lang->action->objectTypes['user'] = '用戶'; +$lang->action->objectTypes['doc'] = '文檔'; +$lang->action->objectTypes['doclib'] = '文檔庫'; +$lang->action->objectTypes['todo'] = 'TODO'; + +/* 用來描述操作歷史記錄。*/ +$lang->action->desc->common = '$date, $action by $actor' . "\n"; +$lang->action->desc->extra = '$date, $action as $extra by $actor' . "\n"; +$lang->action->desc->opened = '$date, 由 $actor 創建。' . "\n"; +$lang->action->desc->created = '$date, 由 $actor 創建。' . "\n"; +$lang->action->desc->changed = '$date, 由 $actor 變更。' . "\n"; +$lang->action->desc->edited = '$date, 由 $actor 編輯。' . "\n"; +$lang->action->desc->assigned = '$date, 由 $actor 指派給 $extra' . "\n"; +$lang->action->desc->closed = '$date, 由 $actor 關閉。' . "\n"; +$lang->action->desc->deleted = '$date, 由 $actor 刪除。' . "\n"; +$lang->action->desc->deletedfile = '$date, 由 $actor 刪除了附件:$extra' . "\n"; +$lang->action->desc->editfile = '$date, 由 $actor 編輯了附件:$extra' . "\n"; +$lang->action->desc->erased = '$date, 由 $actor 刪除。' . "\n"; +$lang->action->desc->undeleted = '$date, 由 $actor 還原。' . "\n"; +$lang->action->desc->commented = '$date, 由 $actor 添加備註。' . "\n"; +$lang->action->desc->activated = '$date, 由 $actor 激活。' . "\n"; +$lang->action->desc->moved = '$date, 由 $actor 移動,之前為 "$extra"' . "\n"; +$lang->action->desc->confirmed = '$date, 由 $actor 確認需求變動,最新版本為#$extra' . "\n"; +$lang->action->desc->bugconfirmed = '$date, 由 $actor 確認Bug' . "\n"; +$lang->action->desc->frombug = '$date, 由 $actor Bug轉化而來,Bug編號為 $extra。'; +$lang->action->desc->started = '$date, 由 $actor 啟動。' . "\n"; +$lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; +$lang->action->desc->svncommited = '$date, 由 $actor 提交代碼,版本為#$extra' . "\n"; +$lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; +$lang->action->desc->diff1 = '修改了 %s,舊值為 "%s",新值為 "%s"。
' . "\n"; +$lang->action->desc->diff2 = '修改了 %s,區別為:' . "\n" . '
%s
' . "\n"; +$lang->action->desc->diff3 = '將檔案名 %s 改為 %s ' . "\n"; + +/* 用來顯示動態信息。*/ +$lang->action->label->created = '創建了'; +$lang->action->label->opened = '創建了'; +$lang->action->label->changed = '變更了'; +$lang->action->label->edited = '編輯了'; +$lang->action->label->assigned = '指派了'; +$lang->action->label->closed = '關閉了'; +$lang->action->label->deleted = '刪除了'; +$lang->action->label->deletedfile = '刪除附件'; +$lang->action->label->editfile = '編輯附件'; +$lang->action->label->erased = '刪除了'; +$lang->action->label->undeleted = '還原了'; +$lang->action->label->commented = '評論了'; +$lang->action->label->activated = '激活了'; +$lang->action->label->resolved = '解決了'; +$lang->action->label->reviewed = '評審了'; +$lang->action->label->moved = '移動了'; +$lang->action->label->confirmed = '確認了需求,'; +$lang->action->label->bugconfirmed = '確認了'; +$lang->action->label->tostory = '轉需求'; +$lang->action->label->frombug = '轉需求'; +$lang->action->label->totask = '轉任務'; +$lang->action->label->svncommited = '提交代碼'; +$lang->action->label->linked2plan = '關聯計劃'; +$lang->action->label->unlinkedfromplan = '移除計劃'; +$lang->action->label->linked2project = '關聯項目'; +$lang->action->label->unlinkedfromproject = '移除項目'; +$lang->action->label->marked = '編輯了'; +$lang->action->label->started = '開始了'; +$lang->action->label->canceled = '取消了'; +$lang->action->label->finished = '完成了'; +$lang->action->label->login = '登錄系統'; +$lang->action->label->logout = "退出登錄"; + +/* 用來生成相應對象的連結。*/ +$lang->action->label->product = '產品|product|view|productID=%s'; +$lang->action->label->productplan = '計劃|productplan|view|productID=%s'; +$lang->action->label->release = '發佈|release|view|productID=%s'; +$lang->action->label->story = '需求|story|view|storyID=%s'; +$lang->action->label->project = '項目|project|view|projectID=%s'; +$lang->action->label->task = '任務|task|view|taskID=%s'; +$lang->action->label->build = 'Build|build|view|buildID=%s'; +$lang->action->label->bug = 'Bug|bug|view|bugID=%s'; +$lang->action->label->case = '用例|testcase|view|caseID=%s'; +$lang->action->label->testtask = '測試任務|testtask|view|caseID=%s'; +$lang->action->label->todo = 'todo|todo|view|todoID=%s'; +$lang->action->label->doclib = '文檔庫|doc|browse|libID=%s'; +$lang->action->label->doc = '文檔|doc|view|docID=%s'; +$lang->action->label->user = '用戶'; +$lang->action->label->space = ' '; + +/* Object type. */ +$lang->action->search->objectTypeList[''] = ''; +$lang->action->search->objectTypeList['product'] = '產品'; +$lang->action->search->objectTypeList['project'] = '項目'; +$lang->action->search->objectTypeList['bug'] = 'Bug'; +$lang->action->search->objectTypeList['case'] = '用例'; +$lang->action->search->objectTypeList['story'] = '需求'; +$lang->action->search->objectTypeList['task'] = '任務'; +$lang->action->search->objectTypeList['testtask'] = '測試任務'; +$lang->action->search->objectTypeList['user'] = '用戶'; +$lang->action->search->objectTypeList['doc'] = '文檔'; +$lang->action->search->objectTypeList['doclib'] = '文檔庫'; +$lang->action->search->objectTypeList['todo'] = 'TODO'; +$lang->action->search->objectTypeList['build'] = 'Build'; +$lang->action->search->objectTypeList['release'] = '發佈'; +$lang->action->search->objectTypeList['productplan'] = '計劃'; + +/* 用來在動態顯示中顯示動作 */ +$lang->action->search->label[''] = ''; +$lang->action->search->label['created'] = $lang->action->label->created; +$lang->action->search->label['opened'] = $lang->action->label->opened; +$lang->action->search->label['changed'] = $lang->action->label->changed; +$lang->action->search->label['edited'] = $lang->action->label->edited; +$lang->action->search->label['assigned'] = $lang->action->label->assigned; +$lang->action->search->label['closed'] = $lang->action->label->closed; +$lang->action->search->label['deleted'] = $lang->action->label->deleted; +$lang->action->search->label['deletedfile'] = $lang->action->label->deletedfile; +$lang->action->search->label['editfile'] = $lang->action->label->editfile; +$lang->action->search->label['erased'] = $lang->action->label->erased; +$lang->action->search->label['undeleted'] = $lang->action->label->undeleted; +$lang->action->search->label['commented'] = $lang->action->label->commented; +$lang->action->search->label['activated'] = $lang->action->label->activated; +$lang->action->search->label['resolved'] = $lang->action->label->resolved; +$lang->action->search->label['reviewed'] = $lang->action->label->reviewed; +$lang->action->search->label['moved'] = $lang->action->label->moved; +$lang->action->search->label['confirmed'] = $lang->action->label->confirmed; +$lang->action->search->label['bugconfirmed'] = $lang->action->label->bugconfirmed; +$lang->action->search->label['tostory'] = $lang->action->label->tostory; +$lang->action->search->label['frombug'] = $lang->action->label->frombug; +$lang->action->search->label['totask'] = $lang->action->label->totask; +$lang->action->search->label['svncommited'] = $lang->action->label->svncommited; +$lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; +$lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; +$lang->action->search->label['linked2project'] = $lang->action->label->linked2project; +$lang->action->search->label['unlinkedfromproject'] = $lang->action->label->unlinkedfromproject; +$lang->action->search->label['marked'] = $lang->action->label->marked; +$lang->action->search->label['started'] = $lang->action->label->started; +$lang->action->search->label['canceled'] = $lang->action->label->canceled; +$lang->action->search->label['finished'] = $lang->action->label->finished; +$lang->action->search->label['login'] = $lang->action->label->login; +$lang->action->search->label['logout'] = $lang->action->label->logout; diff --git a/module/action/model.php b/module/action/model.php index ed317c404c..16ce9ea1ce 100644 --- a/module/action/model.php +++ b/module/action/model.php @@ -1,528 +1,528 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -?> -objectType = strtolower($objectType); - $action->objectID = $objectID; - $action->actor = $this->app->user->account; - $action->action = strtolower($actionType); - $action->date = helper::now(); - $action->comment = htmlspecialchars($comment); - $action->extra = $extra; - - /* Get product and project for this object. */ - $productAndProject = $this->getProductAndProject($objectType, $objectID); - $action->product = $productAndProject['product']; - $action->project = $productAndProject['project']; - - $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); - return $this->dbh->lastInsertID(); - } - - /** - * Get product and project of an object. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getProductAndProject($objectType, $objectID) - { - $objectType = strtolower($objectType); - $emptyRecord = array('product' => 0, 'project' => 0); - - /* If objectType is product or project, return the objectID. */ - if($objectType == 'product') return array('product' => $objectID, 'project' => 0); - if($objectType == 'project') return array('project' => $objectID, 'product' => 0); - - /* Only process these object types. */ - if(strpos('story, productplan, release, task, build. bug, case, testtask, doc', $objectType) !== false) - { - if(!isset($this->config->action->objectTables[$objectType])) return $emptyRecord; - - /* Set fields to fetch. */ - if(strpos('story, productplan, case', $objectType) !== false) $fields = 'product'; - if(strpos('build, bug, testtask, doc', $objectType) !== false) $fields = 'product, project'; - if($objectType == 'release') $fields = 'product, build'; - if($objectType == 'task') $fields = 'project, story'; - - $record = $this->dao->select($fields)->from($this->config->action->objectTables[$objectType])->where('id')->eq($objectID)->fetch(); - - /* Process story, release and task. */ - if($objectType == 'story') $record->project = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->fetch('project'); - if($objectType == 'release') $record->project = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($record->build)->fetch('project'); - if($objectType == 'task') $record->product = $this->dao->select('product')->from(TABLE_STORY)->where('id')->eq($record->story)->fetch('product'); - - if($record) - { - $record = (array)$record; - if(!isset($record['product'])) $record['product'] = 0; - if(!isset($record['project'])) $record['project'] = 0; - return $record; - } - - return $emptyRecord; - } - return $emptyRecord; - } - - /** - * Get actions of an object. - * - * @param int $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getList($objectType, $objectID) - { - $commiters = $this->loadModel('user')->getCommiters(); - $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where('objectType')->eq($objectType) - ->andWhere('objectID')->eq($objectID) - ->orderBy('date, id')->fetchAll('id'); - $histories = $this->getHistory(array_keys($actions)); - foreach($actions as $actionID => $action) - { - if(strtolower($action->action) == 'svncommited' and isset($commiters[$action->actor])) $action->actor = $commiters[$action->actor]; - $action->history = isset($histories[$actionID]) ? $histories[$actionID] : array(); - $actions[$actionID] = $action; - } - return $actions; - } - - /** - * Get an action record. - * - * @param int $actionID - * @access public - * @return object - */ - public function getById($actionID) - { - return $this->dao->findById((int)$actionID)->from(TABLE_ACTION)->fetch(); - } - - /** - * Get deleted objects. - * - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getTrashes($orderBy, $pager) - { - $trashes = $this->dao->select('*')->from(TABLE_ACTION) - ->where('action')->eq('deleted') - ->andWhere('extra')->eq(self::CAN_UNDELETED) - ->orderBy($orderBy)->page($pager)->fetchAll(); - if(!$trashes) return array(); - - /* Group trashes by objectType, and get there name field. */ - foreach($trashes as $object) - { - $object->objectType = str_replace('`', '', $object->objectType); - $typeTrashes[$object->objectType][] = $object->objectID; - } - foreach($typeTrashes as $objectType => $objectIds) - { - $objectIds = array_unique($objectIds); - $table = $this->config->action->objectTables[$objectType]; - $field = $this->config->action->objectNameFields[$objectType]; - $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); - } - - /* Add name field to the trashes. */ - foreach($trashes as $trash) $trash->objectName = $objectNames[$trash->objectType][$trash->objectID]; - return $trashes; - } - - /** - * Get histories of an action. - * - * @param int $actionID - * @access public - * @return array - */ - public function getHistory($actionID) - { - return $this->dao->select()->from(TABLE_HISTORY)->where('action')->in($actionID)->orderBy('id')->fetchGroup('action'); - } - - /** - * Log histories for an action. - * - * @param int $actionID - * @param array $changes - * @access public - * @return void - */ - public function logHistory($actionID, $changes) - { - foreach($changes as $change) - { - $change['action'] = $actionID; - $this->dao->insert(TABLE_HISTORY)->data($change)->exec(); - } - } - - /** - * Print actions of an object. - * - * @param array $action - * @access public - * @return void - */ - public function printAction($action) - { - $objectType = $action->objectType; - $actionType = strtolower($action->action); - - /** - * Set the desc string of this action. - * - * 1. If the module of this action has defined desc of this actionType, use it. - * 2. If no defined in the module language, search the common action define. - * 3. If not found in the lang->action->desc, use the $lang->action->desc->common or $lang->action->desc->extra as the default. - */ - if(isset($this->lang->$objectType->action->$actionType)) - { - $desc = $this->lang->$objectType->action->$actionType; - } - elseif(isset($this->lang->action->desc->$actionType)) - { - $desc = $this->lang->action->desc->$actionType; - } - else - { - $desc = $action->extra ? $this->lang->action->desc->extra : $this->lang->action->desc->common; - } - - /* Cycle actions, replace vars. */ - foreach($action as $key => $value) - { - if($key == 'history') continue; - - /* Desc can be an array or string. */ - if(is_array($desc)) - { - if($key == 'extra') continue; - $desc['main'] = str_replace('$' . $key, $value, $desc['main']); - } - else - { - $desc = str_replace('$' . $key, $value, $desc); - } - } - - /* If the desc is an array, process extra. Please bug/lang. */ - if(is_array($desc)) - { - $extra = strtolower($action->extra); - if(isset($desc['extra'][$extra])) - { - echo str_replace('$extra', $desc['extra'][$extra], $desc['main']); - } - else - { - echo str_replace('$extra', $action->extra, $desc['main']); - } - } - else - { - echo $desc; - } - } - - /** - * Get actions as dynamic. - * - * @param string $objectType - * @param string $count - * @param string $period - * @param string $orderBy - * @param object $pager - * @param string|int $productID all|int(like 123)|notzero all => include zeror, notzero, great than 0 - * @param string|int $projectID same as productID - * @access public - * @return array - */ - public function getDynamic($account = 'all', $period = 'all', $orderBy = 'date_desc', $pager = null, $productID = 'all', $projectID = 'all') - { - /* Computer the begin and end date of a period. */ - $period = $this->computeBeginAndEnd($period); - extract($period); - - /* Get actions. */ - $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where('date')->gt($begin) - ->andWhere('date')->lt($end) - ->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi() - ->beginIF(is_numeric($productID))->andWhere('product')->eq($productID)->fi() - ->beginIF(is_numeric($projectID))->andWhere('project')->eq($projectID)->fi() - ->beginIF($productID == 'notzero')->andWhere('product')->gt(0)->fi() - ->beginIF($projectID == 'notzero')->andWhere('project')->gt(0)->fi() - ->orderBy($orderBy)->page($pager)->fetchAll(); - - if(!$actions) return array(); - return $this->transformActions($actions); - } - - /** - * Get dynamic by search. - * - * @param array $products - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getDynamicBySearch($products, $projects, $queryID, $orderBy = 'date_desc', $pager) - { - $query = $queryID ? $this->loadModel('search')->getQuery($queryID) : ''; - - /* Get the sql and form status from the query. */ - if($query) - { - $this->session->set('actionQuery', $query->sql); - $this->session->set('actionForm', $query->form); - } - if($this->session->actionQuery == false) $this->session->set('actionQuery', ' 1 = 1'); - - $allProduct = "`product` = 'all'"; - $allProject = "`project` = 'all'"; - $actionQuery = $this->session->actionQuery; - - /* If the sql not include 'product', add check purview for product. */ - if(strpos($actionQuery, $allProduct) === false) - { - $actionQuery = $actionQuery . 'AND `product`' . helper::dbIN(array_keys($products)); - } - else - { - $actionQuery = str_replace($allProduct, '1', $actionQuery); - } - - /* If the sql not include 'project', add check purview for project. */ - if(strpos($actionQuery, $allProject) === false) - { - $actionQuery = $actionQuery . 'AND `project`' . helper::dbIN(array_keys($projects)); - } - else - { - $actionQuery = str_replace($allProduct, '1', $actionQuery); - } - - $actions = $this->getBySQL($actionQuery, $orderBy, $pager); - if(!$actions) return array(); - return $this->transformActions($actions); - } - - /** - * Get actions by SQL. - * - * @param string $sql - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getBySQL($sql, $orderBy, $pager = null) - { - return $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where($sql) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * Transform the actions for display. - * - * @param int $actions - * @access public - * @return void - */ - public function transformActions($actions) - { - /* Get commiters. */ - $commiters = $this->loadModel('user')->getCommiters(); - - /* Group actions by objectType, and get there name field. */ - foreach($actions as $object) $objectTypes[$object->objectType][] = $object->objectID; - foreach($objectTypes as $objectType => $objectIds) - { - if(!isset($this->config->action->objectTables[$objectType])) continue; // If no defination for this type, omit it. - - $objectIds = array_unique($objectIds); - $table = $this->config->action->objectTables[$objectType]; - $field = $this->config->action->objectNameFields[$objectType]; - if($table != '`zt_todo`') - { - $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); - } - else - { - $todos = $this->dao->select("id, $field AS name, account, private")->from($table)->where('id')->in($objectIds)->fetchAll('id'); - foreach($todos as $id => $todo) - { - if($todo->private == 1 and $todo->account != $this->app->user->account) - { - $objectNames[$objectType][$id] = $this->lang->todo->thisIsPrivate; - } - else - { - $objectNames[$objectType][$id] = $todo->name; - } - } - } - } - $objectNames['user'][0] = 'guest'; // Add guest account. - - foreach($actions as $action) - { - /* Add name field to the actions. */ - $action->objectName = isset($objectNames[$action->objectType][$action->objectID]) ? $objectNames[$action->objectType][$action->objectID] : ''; - - $actionType = strtolower($action->action); - $objectType = strtolower($action->objectType); - $action->date = date(DT_MONTHTIME2, strtotime($action->date)); - $action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : $action->action; - $action->objectLabel = isset($this->lang->action->label->$objectType) ? $this->lang->action->label->$objectType : $objectType; - - /* If action type is login or logout, needn't link. */ - if($actionType == 'login' or $actionType == 'logout') - { - $action->objectLink = ''; - $action->objectLabel = ''; - continue; - } - elseif($actionType == 'svncommited') - { - $action->actor = isset($commiters[$action->actor]) ? $commiters[$action->actor] : $action->actor; - } - - /* Other actions, create a link. */ - if(strpos($action->objectLabel, '|') !== false) - { - list($objectLabel, $moduleName, $methodName, $vars) = explode('|', $action->objectLabel); - $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID)); - $action->objectLabel = $objectLabel; - } - else - { - $action->objectLink = ''; - } - } - return $actions; - } - - /** - * Compute the begin date and end date of a period. - * - * @param string $period - * @access private - * @return array - */ - private function computeBeginAndEnd($period) - { - $this->loadModel('todo'); - - $today = $this->todo->today(); - $tomorrow = $this->todo->tomorrow(); - $yesterday = $this->todo->yesterday(); - $twoDaysAgo = $this->todo->twoDaysAgo(); - - if($period == 'all') return array('begin' => '1970-1-1', 'end' => '2109-1-1'); - if($period == 'today') return array('begin' => $today, 'end' => $tomorrow); - if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today); - if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday); - - /* If the period is by week, add the end time to the end date. */ - if($period == 'thisweek' or $period == 'lastweek') - { - $func = "get$period"; - extract($this->todo->$func()); - return array('begin' => $begin, 'end' => $end . ' 23:59:59'); - } - - if($period == 'thismonth') return $this->todo->getThisMonth(); - if($period == 'lastmonth') return $this->todo->getLastMonth(); - } - - /** - * Print changes of every action. - * - * @param string $objectType - * @param array $histories - * @access public - * @return void - */ - public function printChanges($objectType, $histories) - { - if(empty($histories)) return; - - $maxLength = 0; // The max length of fields names. - $historiesWithDiff = array(); // To save histories without diff info. - $historiesWithoutDiff = array(); // To save histories with diff info. - - /* Diff histories by hasing diff info or not. Thus we can to make sure the field with diff show at last. */ - foreach($histories as $history) - { - $fieldName = $history->field; - $history->fieldLabel = isset($this->lang->$objectType->$fieldName) ? $this->lang->$objectType->$fieldName : $fieldName; - if(($length = strlen($history->fieldLabel)) > $maxLength) $maxLength = $length; - $history->diff ? $historiesWithDiff[] = $history : $historiesWithoutDiff[] = $history; - } - $histories = array_merge($historiesWithoutDiff, $historiesWithDiff); - - foreach($histories as $history) - { - $history->fieldLabel = str_pad($history->fieldLabel, $maxLength, $this->lang->action->label->space); - if($history->diff != '') - { - $history->diff = str_replace(array('', '', '', ''), array('[ins]', '[/ins]', '[del]', '[/del]'), $history->diff); - $history->diff = $history->field != 'subversion' ? htmlspecialchars($history->diff) : $history->diff; // Keep the diff link. - $history->diff = str_replace(array('[ins]', '[/ins]', '[del]', '[/del]'), array('', '', '', ''), $history->diff); - $history->diff = nl2br($history->diff); - printf($this->lang->action->desc->diff2, $history->fieldLabel, $history->diff); - } - else - { - printf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); - } - } - } -} + + * @package action + * @version $Id$ + * @link http://www.zentao.net + */ +?> +objectType = strtolower($objectType); + $action->objectID = $objectID; + $action->actor = $this->app->user->account; + $action->action = strtolower($actionType); + $action->date = helper::now(); + $action->comment = htmlspecialchars($comment); + $action->extra = $extra; + + /* Get product and project for this object. */ + $productAndProject = $this->getProductAndProject($objectType, $objectID); + $action->product = $productAndProject['product']; + $action->project = $productAndProject['project']; + + $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); + return $this->dbh->lastInsertID(); + } + + /** + * Get product and project of an object. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getProductAndProject($objectType, $objectID) + { + $objectType = strtolower($objectType); + $emptyRecord = array('product' => 0, 'project' => 0); + + /* If objectType is product or project, return the objectID. */ + if($objectType == 'product') return array('product' => $objectID, 'project' => 0); + if($objectType == 'project') return array('project' => $objectID, 'product' => 0); + + /* Only process these object types. */ + if(strpos('story, productplan, release, task, build. bug, case, testtask, doc', $objectType) !== false) + { + if(!isset($this->config->action->objectTables[$objectType])) return $emptyRecord; + + /* Set fields to fetch. */ + if(strpos('story, productplan, case', $objectType) !== false) $fields = 'product'; + if(strpos('build, bug, testtask, doc', $objectType) !== false) $fields = 'product, project'; + if($objectType == 'release') $fields = 'product, build'; + if($objectType == 'task') $fields = 'project, story'; + + $record = $this->dao->select($fields)->from($this->config->action->objectTables[$objectType])->where('id')->eq($objectID)->fetch(); + + /* Process story, release and task. */ + if($objectType == 'story') $record->project = $this->dao->select('project')->from(TABLE_PROJECTSTORY)->where('story')->eq($objectID)->fetch('project'); + if($objectType == 'release') $record->project = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($record->build)->fetch('project'); + if($objectType == 'task') $record->product = $this->dao->select('product')->from(TABLE_STORY)->where('id')->eq($record->story)->fetch('product'); + + if($record) + { + $record = (array)$record; + if(!isset($record['product'])) $record['product'] = 0; + if(!isset($record['project'])) $record['project'] = 0; + return $record; + } + + return $emptyRecord; + } + return $emptyRecord; + } + + /** + * Get actions of an object. + * + * @param int $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getList($objectType, $objectID) + { + $commiters = $this->loadModel('user')->getCommiters(); + $actions = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectType')->eq($objectType) + ->andWhere('objectID')->eq($objectID) + ->orderBy('date, id')->fetchAll('id'); + $histories = $this->getHistory(array_keys($actions)); + foreach($actions as $actionID => $action) + { + if(strtolower($action->action) == 'svncommited' and isset($commiters[$action->actor])) $action->actor = $commiters[$action->actor]; + $action->history = isset($histories[$actionID]) ? $histories[$actionID] : array(); + $actions[$actionID] = $action; + } + return $actions; + } + + /** + * Get an action record. + * + * @param int $actionID + * @access public + * @return object + */ + public function getById($actionID) + { + return $this->dao->findById((int)$actionID)->from(TABLE_ACTION)->fetch(); + } + + /** + * Get deleted objects. + * + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getTrashes($orderBy, $pager) + { + $trashes = $this->dao->select('*')->from(TABLE_ACTION) + ->where('action')->eq('deleted') + ->andWhere('extra')->eq(self::CAN_UNDELETED) + ->orderBy($orderBy)->page($pager)->fetchAll(); + if(!$trashes) return array(); + + /* Group trashes by objectType, and get there name field. */ + foreach($trashes as $object) + { + $object->objectType = str_replace('`', '', $object->objectType); + $typeTrashes[$object->objectType][] = $object->objectID; + } + foreach($typeTrashes as $objectType => $objectIds) + { + $objectIds = array_unique($objectIds); + $table = $this->config->action->objectTables[$objectType]; + $field = $this->config->action->objectNameFields[$objectType]; + $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); + } + + /* Add name field to the trashes. */ + foreach($trashes as $trash) $trash->objectName = $objectNames[$trash->objectType][$trash->objectID]; + return $trashes; + } + + /** + * Get histories of an action. + * + * @param int $actionID + * @access public + * @return array + */ + public function getHistory($actionID) + { + return $this->dao->select()->from(TABLE_HISTORY)->where('action')->in($actionID)->orderBy('id')->fetchGroup('action'); + } + + /** + * Log histories for an action. + * + * @param int $actionID + * @param array $changes + * @access public + * @return void + */ + public function logHistory($actionID, $changes) + { + foreach($changes as $change) + { + $change['action'] = $actionID; + $this->dao->insert(TABLE_HISTORY)->data($change)->exec(); + } + } + + /** + * Print actions of an object. + * + * @param array $action + * @access public + * @return void + */ + public function printAction($action) + { + $objectType = $action->objectType; + $actionType = strtolower($action->action); + + /** + * Set the desc string of this action. + * + * 1. If the module of this action has defined desc of this actionType, use it. + * 2. If no defined in the module language, search the common action define. + * 3. If not found in the lang->action->desc, use the $lang->action->desc->common or $lang->action->desc->extra as the default. + */ + if(isset($this->lang->$objectType->action->$actionType)) + { + $desc = $this->lang->$objectType->action->$actionType; + } + elseif(isset($this->lang->action->desc->$actionType)) + { + $desc = $this->lang->action->desc->$actionType; + } + else + { + $desc = $action->extra ? $this->lang->action->desc->extra : $this->lang->action->desc->common; + } + + /* Cycle actions, replace vars. */ + foreach($action as $key => $value) + { + if($key == 'history') continue; + + /* Desc can be an array or string. */ + if(is_array($desc)) + { + if($key == 'extra') continue; + $desc['main'] = str_replace('$' . $key, $value, $desc['main']); + } + else + { + $desc = str_replace('$' . $key, $value, $desc); + } + } + + /* If the desc is an array, process extra. Please bug/lang. */ + if(is_array($desc)) + { + $extra = strtolower($action->extra); + if(isset($desc['extra'][$extra])) + { + echo str_replace('$extra', $desc['extra'][$extra], $desc['main']); + } + else + { + echo str_replace('$extra', $action->extra, $desc['main']); + } + } + else + { + echo $desc; + } + } + + /** + * Get actions as dynamic. + * + * @param string $objectType + * @param string $count + * @param string $period + * @param string $orderBy + * @param object $pager + * @param string|int $productID all|int(like 123)|notzero all => include zeror, notzero, great than 0 + * @param string|int $projectID same as productID + * @access public + * @return array + */ + public function getDynamic($account = 'all', $period = 'all', $orderBy = 'date_desc', $pager = null, $productID = 'all', $projectID = 'all') + { + /* Computer the begin and end date of a period. */ + $period = $this->computeBeginAndEnd($period); + extract($period); + + /* Get actions. */ + $actions = $this->dao->select('*')->from(TABLE_ACTION) + ->where('date')->gt($begin) + ->andWhere('date')->lt($end) + ->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi() + ->beginIF(is_numeric($productID))->andWhere('product')->eq($productID)->fi() + ->beginIF(is_numeric($projectID))->andWhere('project')->eq($projectID)->fi() + ->beginIF($productID == 'notzero')->andWhere('product')->gt(0)->fi() + ->beginIF($projectID == 'notzero')->andWhere('project')->gt(0)->fi() + ->orderBy($orderBy)->page($pager)->fetchAll(); + + if(!$actions) return array(); + return $this->transformActions($actions); + } + + /** + * Get dynamic by search. + * + * @param array $products + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getDynamicBySearch($products, $projects, $queryID, $orderBy = 'date_desc', $pager) + { + $query = $queryID ? $this->loadModel('search')->getQuery($queryID) : ''; + + /* Get the sql and form status from the query. */ + if($query) + { + $this->session->set('actionQuery', $query->sql); + $this->session->set('actionForm', $query->form); + } + if($this->session->actionQuery == false) $this->session->set('actionQuery', ' 1 = 1'); + + $allProduct = "`product` = 'all'"; + $allProject = "`project` = 'all'"; + $actionQuery = $this->session->actionQuery; + + /* If the sql not include 'product', add check purview for product. */ + if(strpos($actionQuery, $allProduct) === false) + { + $actionQuery = $actionQuery . 'AND `product`' . helper::dbIN(array_keys($products)); + } + else + { + $actionQuery = str_replace($allProduct, '1', $actionQuery); + } + + /* If the sql not include 'project', add check purview for project. */ + if(strpos($actionQuery, $allProject) === false) + { + $actionQuery = $actionQuery . 'AND `project`' . helper::dbIN(array_keys($projects)); + } + else + { + $actionQuery = str_replace($allProduct, '1', $actionQuery); + } + + $actions = $this->getBySQL($actionQuery, $orderBy, $pager); + if(!$actions) return array(); + return $this->transformActions($actions); + } + + /** + * Get actions by SQL. + * + * @param string $sql + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getBySQL($sql, $orderBy, $pager = null) + { + return $actions = $this->dao->select('*')->from(TABLE_ACTION) + ->where($sql) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * Transform the actions for display. + * + * @param int $actions + * @access public + * @return void + */ + public function transformActions($actions) + { + /* Get commiters. */ + $commiters = $this->loadModel('user')->getCommiters(); + + /* Group actions by objectType, and get there name field. */ + foreach($actions as $object) $objectTypes[$object->objectType][] = $object->objectID; + foreach($objectTypes as $objectType => $objectIds) + { + if(!isset($this->config->action->objectTables[$objectType])) continue; // If no defination for this type, omit it. + + $objectIds = array_unique($objectIds); + $table = $this->config->action->objectTables[$objectType]; + $field = $this->config->action->objectNameFields[$objectType]; + if($table != '`zt_todo`') + { + $objectNames[$objectType] = $this->dao->select("id, $field AS name")->from($table)->where('id')->in($objectIds)->fetchPairs(); + } + else + { + $todos = $this->dao->select("id, $field AS name, account, private")->from($table)->where('id')->in($objectIds)->fetchAll('id'); + foreach($todos as $id => $todo) + { + if($todo->private == 1 and $todo->account != $this->app->user->account) + { + $objectNames[$objectType][$id] = $this->lang->todo->thisIsPrivate; + } + else + { + $objectNames[$objectType][$id] = $todo->name; + } + } + } + } + $objectNames['user'][0] = 'guest'; // Add guest account. + + foreach($actions as $action) + { + /* Add name field to the actions. */ + $action->objectName = isset($objectNames[$action->objectType][$action->objectID]) ? $objectNames[$action->objectType][$action->objectID] : ''; + + $actionType = strtolower($action->action); + $objectType = strtolower($action->objectType); + $action->date = date(DT_MONTHTIME2, strtotime($action->date)); + $action->actionLabel = isset($this->lang->action->label->$actionType) ? $this->lang->action->label->$actionType : $action->action; + $action->objectLabel = isset($this->lang->action->label->$objectType) ? $this->lang->action->label->$objectType : $objectType; + + /* If action type is login or logout, needn't link. */ + if($actionType == 'login' or $actionType == 'logout') + { + $action->objectLink = ''; + $action->objectLabel = ''; + continue; + } + elseif($actionType == 'svncommited') + { + $action->actor = isset($commiters[$action->actor]) ? $commiters[$action->actor] : $action->actor; + } + + /* Other actions, create a link. */ + if(strpos($action->objectLabel, '|') !== false) + { + list($objectLabel, $moduleName, $methodName, $vars) = explode('|', $action->objectLabel); + $action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID)); + $action->objectLabel = $objectLabel; + } + else + { + $action->objectLink = ''; + } + } + return $actions; + } + + /** + * Compute the begin date and end date of a period. + * + * @param string $period + * @access private + * @return array + */ + private function computeBeginAndEnd($period) + { + $this->loadModel('todo'); + + $today = $this->todo->today(); + $tomorrow = $this->todo->tomorrow(); + $yesterday = $this->todo->yesterday(); + $twoDaysAgo = $this->todo->twoDaysAgo(); + + if($period == 'all') return array('begin' => '1970-1-1', 'end' => '2109-1-1'); + if($period == 'today') return array('begin' => $today, 'end' => $tomorrow); + if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today); + if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday); + + /* If the period is by week, add the end time to the end date. */ + if($period == 'thisweek' or $period == 'lastweek') + { + $func = "get$period"; + extract($this->todo->$func()); + return array('begin' => $begin, 'end' => $end . ' 23:59:59'); + } + + if($period == 'thismonth') return $this->todo->getThisMonth(); + if($period == 'lastmonth') return $this->todo->getLastMonth(); + } + + /** + * Print changes of every action. + * + * @param string $objectType + * @param array $histories + * @access public + * @return void + */ + public function printChanges($objectType, $histories) + { + if(empty($histories)) return; + + $maxLength = 0; // The max length of fields names. + $historiesWithDiff = array(); // To save histories without diff info. + $historiesWithoutDiff = array(); // To save histories with diff info. + + /* Diff histories by hasing diff info or not. Thus we can to make sure the field with diff show at last. */ + foreach($histories as $history) + { + $fieldName = $history->field; + $history->fieldLabel = isset($this->lang->$objectType->$fieldName) ? $this->lang->$objectType->$fieldName : $fieldName; + if(($length = strlen($history->fieldLabel)) > $maxLength) $maxLength = $length; + $history->diff ? $historiesWithDiff[] = $history : $historiesWithoutDiff[] = $history; + } + $histories = array_merge($historiesWithoutDiff, $historiesWithDiff); + + foreach($histories as $history) + { + $history->fieldLabel = str_pad($history->fieldLabel, $maxLength, $this->lang->action->label->space); + if($history->diff != '') + { + $history->diff = str_replace(array('', '', '', ''), array('[ins]', '[/ins]', '[del]', '[/del]'), $history->diff); + $history->diff = $history->field != 'subversion' ? htmlspecialchars($history->diff) : $history->diff; // Keep the diff link. + $history->diff = str_replace(array('[ins]', '[/ins]', '[del]', '[/del]'), array('', '', '', ''), $history->diff); + $history->diff = nl2br($history->diff); + printf($this->lang->action->desc->diff2, $history->fieldLabel, $history->diff); + } + else + { + printf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); + } + } + } +} diff --git a/module/action/view/trash.html.php b/module/action/view/trash.html.php index 39062d7c56..6c83be7bb2 100644 --- a/module/action/view/trash.html.php +++ b/module/action/view/trash.html.php @@ -1,49 +1,49 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - - - - -
action->objectType);?> idAB);?>action->objectName;?>action->actor);?>action->date);?>actions;?>
action->objectTypes[$action->objectType];?>objectID;?>createLink($module, 'view', "id=$action->objectID"), $action->objectName);?>actor];?>date;?>id", $lang->action->undelete, 'hiddenwin');?> -
-
action->trashTips;?>
-
show();?>
-
- + + * @package action + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + + + + +
action->objectType);?> idAB);?>action->objectName;?>action->actor);?>action->date);?>actions;?>
action->objectTypes[$action->objectType];?>objectID;?>createLink($module, 'view', "id=$action->objectID"), $action->objectName);?>actor];?>date;?>id", $lang->action->undelete, 'hiddenwin');?> +
+
action->trashTips;?>
+
show();?>
+
+ diff --git a/module/admin/control.php b/module/admin/control.php index bb10409ffe..d4529055df 100644 --- a/module/admin/control.php +++ b/module/admin/control.php @@ -1,24 +1,24 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -class admin extends control -{ - /** - * Index page of admin module. Locate to action's trash page. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('extension', 'browse')); - } -} + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +class admin extends control +{ + /** + * Index page of admin module. Locate to action's trash page. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('extension', 'browse')); + } +} diff --git a/module/admin/lang/en.php b/module/admin/lang/en.php index cc8c107ef8..c7f856321e 100644 --- a/module/admin/lang/en.php +++ b/module/admin/lang/en.php @@ -1,19 +1,19 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->admin->common = 'Admin'; -$lang->admin->index = 'Index'; -$lang->admin->company = 'Company'; -$lang->admin->user = 'User'; -$lang->admin->group = 'Group'; -$lang->admin->welcome = 'Welcome to ZenTaoPMS.'; - -$lang->admin->browseCompany = 'Browse Company'; + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->admin->common = 'Admin'; +$lang->admin->index = 'Index'; +$lang->admin->company = 'Company'; +$lang->admin->user = 'User'; +$lang->admin->group = 'Group'; +$lang->admin->welcome = 'Welcome to ZenTaoPMS.'; + +$lang->admin->browseCompany = 'Browse Company'; diff --git a/module/admin/lang/zh-cn.php b/module/admin/lang/zh-cn.php index 0301a165b7..8553ce8ff5 100644 --- a/module/admin/lang/zh-cn.php +++ b/module/admin/lang/zh-cn.php @@ -1,19 +1,19 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->admin->common = '后台管理'; -$lang->admin->index = '后台管理首页'; -$lang->admin->company = '公司管理'; -$lang->admin->user = '用户管理'; -$lang->admin->group = '分组管理'; -$lang->admin->welcome = '欢迎使用禅道管理软件后台管理系统'; - -$lang->admin->browseCompany = '浏览公司'; + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->admin->common = '后台管理'; +$lang->admin->index = '后台管理首页'; +$lang->admin->company = '公司管理'; +$lang->admin->user = '用户管理'; +$lang->admin->group = '分组管理'; +$lang->admin->welcome = '欢迎使用禅道管理软件后台管理系统'; + +$lang->admin->browseCompany = '浏览公司'; diff --git a/module/admin/lang/zh-tw.php b/module/admin/lang/zh-tw.php index fed35d4632..2ce9241b36 100644 --- a/module/admin/lang/zh-tw.php +++ b/module/admin/lang/zh-tw.php @@ -1,19 +1,19 @@ - - * @package admin - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->admin->common = '後台管理'; -$lang->admin->index = '後台管理首頁'; -$lang->admin->company = '公司管理'; -$lang->admin->user = '用戶管理'; -$lang->admin->group = '分組管理'; -$lang->admin->welcome = '歡迎使用禪道管理軟件後台管理系統'; - -$lang->admin->browseCompany = '瀏覽公司'; + + * @package admin + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->admin->common = '後台管理'; +$lang->admin->index = '後台管理首頁'; +$lang->admin->company = '公司管理'; +$lang->admin->user = '用戶管理'; +$lang->admin->group = '分組管理'; +$lang->admin->welcome = '歡迎使用禪道管理軟件後台管理系統'; + +$lang->admin->browseCompany = '瀏覽公司'; diff --git a/module/admin/model.php b/module/admin/model.php index a5e964baf5..330118119f 100644 --- a/module/admin/model.php +++ b/module/admin/model.php @@ -1,48 +1,48 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dbh->query($sql)->fetchALL(); - } - - /** - * Get state of company. - * - * @param int $companyID - * @access public - * @return void - */ - public function getStatOfCompany($companyID) - { - } - - /** - * Get system info. - * - * @access public - * @return void - */ - public function getStatOfSys() - { - } -} + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dbh->query($sql)->fetchALL(); + } + + /** + * Get state of company. + * + * @param int $companyID + * @access public + * @return void + */ + public function getStatOfCompany($companyID) + { + } + + /** + * Get system info. + * + * @access public + * @return void + */ + public function getStatOfSys() + { + } +} diff --git a/module/admin/view/browsecompany.html.php b/module/admin/view/browsecompany.html.php index f2c7d40182..1e41fc2eea 100644 --- a/module/admin/view/browsecompany.html.php +++ b/module/admin/view/browsecompany.html.php @@ -1,47 +1,47 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
company->id;?>company->name;?>company->phone;?>company->fax;?>company->address;?>company->zipcode;?>company->website;?>company->backyard;?>company->pms;?>company->guest;?>actions;?>
id;?>name;?>phone;?>fax;?>address;?>zipcode;?>website, $company->website, '_blank');?>backyard,$company->backyard, '_blank');?>pms, $company->pms, '_blank');?>company->guestList[(int)$company->guest];?> - createLink('company', 'edit', "companyID=$company->id"), $this->lang->company->edit);?> - createLink('company', 'delete', "companyID=$company->id"), $this->lang->company->delete, "hiddenwin");?> -
- + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
company->id;?>company->name;?>company->phone;?>company->fax;?>company->address;?>company->zipcode;?>company->website;?>company->backyard;?>company->pms;?>company->guest;?>actions;?>
id;?>name;?>phone;?>fax;?>address;?>zipcode;?>website, $company->website, '_blank');?>backyard,$company->backyard, '_blank');?>pms, $company->pms, '_blank');?>company->guestList[(int)$company->guest];?> + createLink('company', 'edit', "companyID=$company->id"), $this->lang->company->edit);?> + createLink('company', 'delete', "companyID=$company->id"), $this->lang->company->delete, "hiddenwin");?> +
+ diff --git a/module/api/control.php b/module/api/control.php index 5508c6dbc2..278278693a 100644 --- a/module/api/control.php +++ b/module/api/control.php @@ -1,50 +1,50 @@ - - * @package api - * @version $Id$ - * @link http://www.zentao.net - */ -class api extends control -{ - /** - * Return session to the client. - * - * @access public - * @return void - */ - public function getSessionID() - { - $this->session->set('rand', mt_rand(0, 10000)); - $this->view->sessionName = session_name(); - $this->view->sessionID = session_id(); - $this->view->rand = $this->session->rand; - $this->display(); - } - - /** - * Execute a module's model's method, return the result. - * - * @param string $moduleName - * @param string $methodName - * @param string $params param1=value1,param2=value2, don't use & to join them. - * @access public - * @return string - */ - public function getModel($moduleName, $methodName, $params = '') - { - parse_str(str_replace(',', '&', $params), $params); - $module = $this->loadModel($moduleName); - $result = call_user_func_array(array(&$module, $methodName), $params); - if(dao::isError()) die(json_encode(dao::getError())); - $output['status'] = $result ? 'success' : 'fail'; - $output['data'] = json_encode($result); - $output['md5'] = md5($output['data']); - $this->output = json_encode($output); - die($this->output); - } -} + + * @package api + * @version $Id$ + * @link http://www.zentao.net + */ +class api extends control +{ + /** + * Return session to the client. + * + * @access public + * @return void + */ + public function getSessionID() + { + $this->session->set('rand', mt_rand(0, 10000)); + $this->view->sessionName = session_name(); + $this->view->sessionID = session_id(); + $this->view->rand = $this->session->rand; + $this->display(); + } + + /** + * Execute a module's model's method, return the result. + * + * @param string $moduleName + * @param string $methodName + * @param string $params param1=value1,param2=value2, don't use & to join them. + * @access public + * @return string + */ + public function getModel($moduleName, $methodName, $params = '') + { + parse_str(str_replace(',', '&', $params), $params); + $module = $this->loadModel($moduleName); + $result = call_user_func_array(array(&$module, $methodName), $params); + if(dao::isError()) die(json_encode(dao::getError())); + $output['status'] = $result ? 'success' : 'fail'; + $output['data'] = json_encode($result); + $output['md5'] = md5($output['data']); + $this->output = json_encode($output); + die($this->output); + } +} diff --git a/module/api/lang/en.php b/module/api/lang/en.php index 99ee0d7991..59555de28f 100644 --- a/module/api/lang/en.php +++ b/module/api/lang/en.php @@ -1,13 +1,13 @@ - - * @package api - * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -$lang->api->common = 'API'; -$lang->api->getModel = 'Super Model API'; + + * @package api + * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $ + * @link http://www.zentao.net + */ +$lang->api->common = 'API'; +$lang->api->getModel = 'Super Model API'; diff --git a/module/api/lang/zh-cn.php b/module/api/lang/zh-cn.php index c7446f2e6a..e18a454d8d 100644 --- a/module/api/lang/zh-cn.php +++ b/module/api/lang/zh-cn.php @@ -1,13 +1,13 @@ - - * @package api - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->api->common = 'API接口'; -$lang->api->getModel = '超级model调用接口'; + + * @package api + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->api->common = 'API接口'; +$lang->api->getModel = '超级model调用接口'; diff --git a/module/api/lang/zh-tw.php b/module/api/lang/zh-tw.php index 2a290d4d74..b75d8dae48 100644 --- a/module/api/lang/zh-tw.php +++ b/module/api/lang/zh-tw.php @@ -1,13 +1,13 @@ - - * @package api - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->api->common = 'API介面'; -$lang->api->getModel = '超級model調用介面'; + + * @package api + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->api->common = 'API介面'; +$lang->api->getModel = '超級model調用介面'; diff --git a/module/api/model.php b/module/api/model.php index 3d8da69a82..6b6ff00676 100644 --- a/module/api/model.php +++ b/module/api/model.php @@ -1,15 +1,15 @@ - - * @package api - * @version $Id$ - * @link http://www.zentao.net - */ -class apiModel extends model -{ -} - + + * @package api + * @version $Id$ + * @link http://www.zentao.net + */ +class apiModel extends model +{ +} + diff --git a/module/bug/control.php b/module/bug/control.php index 04b431bbde..c806429ee8 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1,947 +1,947 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -class bug extends control -{ - private $products = array(); - - /** - * Construct function, load some modules auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('product'); - $this->loadModel('tree'); - $this->loadModel('user'); - $this->loadModel('action'); - $this->loadModel('story'); - $this->loadModel('task'); - $this->products = $this->product->getPairs(); - if(empty($this->products)) - { - echo js::alert($this->lang->product->errorNoProduct); - die(js::locate($this->createLink('product', 'create'))); - } - $this->view->products = $this->products; - } - - /** - * The index page, locate to browse. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('bug', 'browse')); - } - - /** - * Browse bugs. - * - * @param int $productID - * @param string $browseType - * @param int $param - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Set browseType, productID, moduleID and queryID. */ - $browseType = strtolower($browseType); - $productID = $this->product->saveState($productID, $this->products); - $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Set menu and save session. */ - $this->bug->setMenu($this->products, $productID); - $this->session->set('bugList', $this->app->getURI(true)); - - /* Process the order by field. */ - if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc'; - setcookie('qaBugOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - $projects = $this->loadModel('project')->getPairs(); - $projects[0] = ''; - - /* Get bugs. */ - $bugs = array(); - if($browseType == 'all') $bugs = $this->bug->getAllBugs($productID, $projects, $orderBy, $pager); - elseif($browseType == "bymodule") - { - $childModuleIds = $this->tree->getAllChildId($moduleID); - $bugs = $this->bug->getModuleBugs($productID, $childModuleIds, $projects, $orderBy, $pager); - } - elseif($browseType == 'assigntome') $bugs = $this->bug->getByAssigntome($productID, $projects, $orderBy, $pager); - elseif($browseType == 'openedbyme') $bugs = $this->bug->getByOpenedbyme($productID, $projects, $orderBy, $pager); - elseif($browseType == 'resolvedbyme') $bugs = $this->bug->getByResolvedbyme($productID, $projects, $orderBy, $pager); - elseif($browseType == 'assigntonull') $bugs = $this->bug->getByAssigntonull($productID, $projects, $orderBy, $pager); - elseif($browseType == 'unresolved') $bugs = $this->bug->getByStatus($productID, $projects, 'unresolved', $orderBy, $pager); - elseif($browseType == 'unclosed') $bugs = $this->bug->getByStatus($productID, $projects, 'unclosed', $orderBy, $pager); - elseif($browseType == 'longlifebugs') $bugs = $this->bug->getByLonglifebugs($productID, $projects, $orderBy, $pager); - elseif($browseType == 'postponedbugs') $bugs = $this->bug->getByPostponedbugs($productID, $projects, $orderBy, $pager); - elseif($browseType == 'needconfirm') $bugs = $this->bug->getByNeedconfirm($productID, $projects, $orderBy, $pager); - elseif($browseType == 'bysearch') $bugs = $this->bug->getBySearch($productID, $projects, $queryID, $orderBy, $pager); - - /* Process the sql, get the conditon partion, save it to session. Thus the report page can use the same condition. */ - if($browseType != 'needconfirm') - { - $sql = explode('WHERE', $this->dao->get()); - $sql = explode('ORDER', $sql[1]); - $this->session->set('bugReportCondition', $sql[0]); - } - - /* Get custom fields. */ - $customFields = $this->cookie->bugFields != false ? $this->cookie->bugFields : $this->config->bug->list->defaultFields; - $customed = !($customFields == $this->config->bug->list->defaultFields); - - /* If customed, get related name or titles. */ - if($customed) $bugs = $this->bug->formCustomedBugs($bugs); - - /* Build the search form. */ - $this->config->bug->search['actionURL'] = $this->createLink('bug', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); - $this->config->bug->search['queryID'] = $queryID; - $this->config->bug->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->bug->allProduct); - $this->config->bug->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); - $this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID); - $this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID); - $this->config->bug->search['params']['resolvedBuild']['values'] = $this->build->getProductBuildPairs($productID); - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->bug->search); - - $users = $this->user->getPairs('noletter'); - - $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common; - $position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $position[] = $this->lang->bug->common; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink')); - $this->view->browseType = $browseType; - $this->view->bugs = $bugs; - $this->view->users = $users; - $this->view->pager = $pager; - $this->view->param = $param; - $this->view->orderBy = $orderBy; - $this->view->moduleID = $moduleID; - $this->view->customed = $customed; - $this->view->customFields= explode(',', str_replace(' ', '', trim($customFields))); - $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; - - $this->display(); - } - - /** - * The report page. - * - * @param int $productID - * @param string $browseType - * @param int $moduleID - * @access public - * @return void - */ - public function report($productID, $browseType, $moduleID) - { - $this->loadModel('report'); - $this->view->charts = array(); - $this->view->renderJS = ''; - - if(!empty($_POST)) - { - foreach($this->post->charts as $chart) - { - $chartFunc = 'getDataOf' . $chart; - $chartData = $this->bug->$chartFunc(); - $chartOption = $this->lang->bug->report->$chart; - $this->bug->mergeChartOption($chart); - - $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); - $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); - $this->view->datas[$chart] = $this->report->computePercent($chartData); - } - $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); - } - - $this->bug->setMenu($this->products, $productID); - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common; - $this->view->productID = $productID; - $this->view->browseType = $browseType; - $this->view->moduleID = $moduleID; - $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; - $this->display(); - } - - /** - * Create a bug. - * - * @param int $productID - * @param string $extras others params, forexample, projectID=10,moduleID=10 - * @access public - * @return void - */ - public function create($productID, $extras = '') - { - $this->view->users = $this->user->getPairs('nodeleted'); - if(empty($this->products)) $this->locate($this->createLink('product', 'create')); - - if(!empty($_POST)) - { - $bugID = $this->bug->create(); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'Opened'); - $this->sendmail($bugID, $actionID); - die(js::locate($this->createLink('bug', 'browse', "productID={$this->post->product}&type=byModule¶m={$this->post->module}"), 'parent')); - } - - /* Get product, then set menu. */ - $productID = $this->product->saveState($productID, $this->products); - $this->bug->setMenu($this->products, $productID); - - /* Remove the unused types. */ - unset($this->lang->bug->typeList['designchange']); - unset($this->lang->bug->typeList['newfeature']); - unset($this->lang->bug->typeList['trackthings']); - - /* Init vars. */ - $moduleID = 0; - $projectID = 0; - $taskID = 0; - $storyID = 0; - $buildID = 0; - $caseID = 0; - $runID = 0; - $title = ''; - $steps = $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect; - $os = ''; - $browser = ''; - $assignedTo = ''; - $mailto = ''; - $keywords = ''; - $severity = 3; - $type = 'codeerror'; - - /* Parse the extras. */ - $extras = str_replace(array(',', ' '), array('&', ''), $extras); - parse_str($extras); - - /* If set runID, get the last result info as the template. */ - if($runID > 0) $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->limit(1)->fetch('id'); - if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID)); - - /* If set caseID and runID='', get the last result info as the template. */ - if($caseID > 0 && $runID == '') - { - $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('date desc')->limit(1)->fetch('id'); - if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID, $caseID, $version)); - } - - /* If bugID setted, use this bug as template. */ - if(isset($bugID)) - { - $bug = $this->bug->getById($bugID); - extract((array)$bug); - $projectID = $bug->project; - $moduleID = $bug->module; - $taskID = $bug->task; - $storyID = $bug->story; - $buildID = $bug->openedBuild; - $severity = $bug->severity; - $type = $bug->type; - } - - /* If projectID is setted, get builds and stories of this project. */ - if($projectID) - { - $builds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty'); - $stories = $this->story->getProjectStoryPairs($projectID); - } - else - { - $builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); - $stories = $this->story->getProductStoryPairs($productID); - } - - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->create; - - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); - $this->view->stories = $stories; - $this->view->projects = $this->product->getProjectPairs($productID, $params = 'nodeleted'); - $this->view->builds = $builds; - $this->view->tasks = $this->loadModel('task')->getProjectTaskPairs($projectID); - $this->view->moduleID = $moduleID; - $this->view->projectID = $projectID; - $this->view->taskID = $taskID; - $this->view->storyID = $storyID; - $this->view->buildID = $buildID; - $this->view->caseID = $caseID; - $this->view->title = $title; - $this->view->steps = htmlspecialchars($steps); - $this->view->os = $os; - $this->view->browser = $browser; - $this->view->assignedTo = $assignedTo; - $this->view->mailto = $mailto; - $this->view->keywords = $keywords; - $this->view->severity = $severity; - $this->view->type = $type; - - $this->display(); - } - - /** - * View a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function view($bugID) - { - /* Judge bug exits or not. */ - $bug = $this->bug->getById($bugID); - if(!$bug) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Set menu. */ - $this->bug->setMenu($this->products, $bug->product); - - /* Get product info. */ - $productID = $bug->product; - $productName = $this->products[$productID]; - - /* Header and positon. */ - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->view; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $productName); - $this->view->position[] = $this->lang->bug->view; - - /* Assign. */ - $this->view->productID = $productID; - $this->view->productName = $productName; - $this->view->modulePath = $this->tree->getParents($bug->module); - $this->view->bug = $bug; - $this->view->users = $this->user->getPairs('noletter'); - $this->view->actions = $this->action->getList('bug', $bugID); - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); - - $this->display(); - } - - /** - * Edit a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function edit($bugID, $comment = false) - { - if(!empty($_POST)) - { - $changes = array(); - $files = array(); - if($comment == false) - { - $changes = $this->bug->update($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('bug', $bugID); - } - if($this->post->comment != '' or !empty($changes) or !empty($files)) - { - $action = !empty($changes) ? 'Edited' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; - $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($bugID, $actionID); - } - - $bug = $this->bug->getById($bugID); - if($bug->toTask != 0) - { - foreach($changes as $change) - { - if($change['field'] == 'status') - { - $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask"); - $cancelURL = $this->server->HTTP_REFERER; - die(js::confirm(sprintf($this->lang->task->remindTask, $bug->Task), $confirmURL, $cancelURL, 'parent', 'parent')); - } - } - } - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - /* Get the info of bug, current product and modue. */ - $bug = $this->bug->getById($bugID); - $productID = $bug->product; - $projectID = $bug->project; - $currentModuleID = $bug->module; - - /** - * Remove designchange, newfeature, trackings from the typeList, because should be tracked in story or task. - * These thress types if upgrade from bugfree2.x. - */ - if($bug->type != 'designchange') unset($this->lang->bug->typeList['designchange']); - if($bug->type != 'newfeature') unset($this->lang->bug->typeList['newfeature']); - if($bug->type != 'trackthings') unset($this->lang->bug->typeList['trackthings']); - - /* Set the menu. */ - $this->bug->setMenu($this->products, $productID); - - /* Set header and position. */ - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->edit; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->edit; - - /* Assign. */ - if($projectID) - { - $this->view->openedBuilds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty'); - } - else - { - $this->view->openedBuilds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); - } - $this->view->bug = $bug; - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); - $this->view->currentModuleID = $currentModuleID; - $this->view->projects = $this->product->getProjectPairs($bug->product); - $this->view->stories = $bug->project ? $this->story->getProjectStoryPairs($bug->project) : $this->story->getProductStoryPairs($bug->product); - $this->view->tasks = $this->task->getProjectTaskPairs($bug->project); - $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy"); - $this->view->resolvedBuilds = array('' => '') + $this->view->openedBuilds; - $this->view->actions = $this->action->getList('bug', $bugID); - $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account); - - $this->display(); - } - - /** - * confirm a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function confirmBug($bugID) - { - if(!empty($_POST)) - { - $this->bug->confirm($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'bugConfirmed', $this->post->comment); - $this->sendmail($bugID, $actionID); - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - $bug = $this->bug->getById($bugID); - $productID = $bug->product; - $this->bug->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->confirmBug; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->confirmBug; - - $this->view->bug = $bug; - $this->view->actions = $this->action->getList('bug', $bugID); - $this->display(); - } - - /** - * Resolve a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function resolve($bugID) - { - $this->view->users = $this->user->getPairs('nodeleted'); - - if(!empty($_POST)) - { - $this->bug->resolve($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'Resolved', $this->post->comment, $this->post->resolution); - $this->sendmail($bugID, $actionID); - - $bug = $this->bug->getById($bugID); - if($bug->toTask != 0) - { - $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask"); - $cancelURL = $this->createLink('bug', 'view', "bugID=$bugID"); - die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent')); - } - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - $bug = $this->bug->getById($bugID); - $productID = $bug->product; - $this->bug->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->resolve; - - $this->view->bug = $bug; - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); - $this->view->actions = $this->action->getList('bug', $bugID); - $this->display(); - } - - /** - * Activate a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function activate($bugID) - { - $this->view->users = $this->user->getPairs('nodeleted'); - - if(!empty($_POST)) - { - $this->bug->activate($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('bug', $bugID); - $actionID = $this->action->create('bug', $bugID, 'Activated', $this->post->comment); - $this->sendmail($bugID, $actionID); - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - $bug = $this->bug->getById($bugID); - $productID = $bug->product; - $this->bug->setMenu($this->products, $productID); - - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->activate; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->activate; - - $this->view->bug = $bug; - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); - $this->view->actions = $this->action->getList('bug', $bugID); - - $this->display(); - } - - /** - * Close a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function close($bugID) - { - $this->view->users = $this->user->getPairs('noletter'); - if(!empty($_POST)) - { - $this->bug->close($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment); - $this->sendmail($bugID, $actionID); - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - $bug = $this->bug->getById($bugID); - $productID = $bug->product; - $this->bug->setMenu($this->products, $productID); - - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->close; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->close; - - $this->view->bug = $bug; - $this->view->actions = $this->action->getList('bug', $bugID); - $this->display(); - } - - /** - * Confirm story change. - * - * @param int $bugID - * @access public - * @return void - */ - public function confirmStoryChange($bugID) - { - $bug = $this->bug->getById($bugID); - $this->dao->update(TABLE_BUG)->set('storyVersion')->eq($bug->latestStoryVersion)->where('id')->eq($bugID)->exec(); - $this->loadModel('action')->create('bug', $bugID, 'confirmed', '', $bug->latestStoryVersion); - die(js::reload('parent')); - } - - /** - * Delete a bug. - * - * @param int $bugID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($bugID, $confirm = 'no') - { - $bug = $this->bug->getById($bugID); - if($confirm == 'no') - { - die(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes"))); - } - else - { - $this->bug->delete(TABLE_BUG, $bugID); - if($bug->toTask != 0) echo js::alert($this->lang->bug->remindTask . $bug->toTask); - die(js::locate($this->session->bugList, 'parent')); - } - } - - /** - * Save current template. - * - * @access public - * @return string - */ - public function saveTemplate() - { - $this->bug->saveUserBugTemplate(); - if(dao::isError()) die(js::error(dao::getError())); - die($this->fetch('bug', 'buildTemplates')); - } - - /** - * Build the user templates selection code. - * - * @access public - * @return void - */ - public function buildTemplates() - { - $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account); - $this->display('bug', 'buildTemplates'); - } - - /** - * Delete a user template. - * - * @param int $templateID - * @access public - * @return void - */ - public function deleteTemplate($templateID) - { - $this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)->andWhere('account')->eq($this->app->user->account)->exec(); - die(); - } - - /** - * Custom fields. - * - * @access public - * @return void - */ - public function customFields() - { - if($_POST) - { - $customFields = $this->post->customFields; - $customFields = join(',', $customFields); - setcookie('bugFields', $customFields, $this->config->cookieLife, $this->config->webRoot); - die(js::reload('parent')); - } - - $customFields = $this->cookie->bugFields ? $this->cookie->bugFields : $this->config->bug->list->defaultFields; - - $this->view->allFields = $this->bug->getFieldPairs($this->config->bug->list->allFields); - $this->view->customFields = $this->bug->getFieldPairs($customFields); - $this->view->defaultFields = $this->bug->getFieldPairs($this->config->bug->list->defaultFields); - die($this->display()); - } - - /** - * AJAX: get bugs of a user in html select. - * - * @param string $account - * @access public - * @return string - */ - public function ajaxGetUserBugs($account = '') - { - if($account == '') $account = $this->app->user->account; - $bugs = $this->bug->getUserBugPairs($account); - die(html::select('bug', $bugs, '', 'class=select-1')); - } - - /** - * AJAX: Get bug owner of a module. - * - * @param int $moduleID - * @param int $productID - * @access public - * @return string - */ - public function ajaxGetModuleOwner($moduleID, $productID = 0) - { - $owner = ''; - if($moduleID) $owner = $this->dao->findByID($moduleID)->from(TABLE_MODULE)->fetch('owner'); - if(!$owner) $owner = $this->dao->findByID($productID)->from(TABLE_PRODUCT)->fetch('QM'); - die($owner); - } - - /** - * Send email. - * - * @param int $bugID - * @param int $actionID - * @access private - * @return void - */ - private function sendmail($bugID, $actionID) - { - /* Set toList and ccList. */ - $bug = $this->bug->getByID($bugID); - $productName = $this->products[$bug->product]; - $toList = $bug->assignedTo; - $ccList = trim($bug->mailto, ','); - if($toList == '') - { - if($ccList == '') return; - if(strpos($ccList, ',') === false) - { - $toList = $ccList; - $ccList = ''; - } - else - { - $commaPos = strpos($ccList, ','); - $toList = substr($ccList, 0, $commaPos); - $ccList = substr($ccList, $commaPos + 1); - } - } - elseif(strtolower($toList) == 'closed') - { - $toList = $bug->resolvedBy; - } - - /* Get action info. */ - $action = $this->action->getById($actionID); - $history = $this->action->getHistory($actionID); - $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); - if(strtolower($action->action) == 'opened') $action->comment = $bug->steps; - - /* Create the mail content. */ - $this->view->bug = $bug; - $this->view->action = $action; - $mailContent = $this->parse($this->moduleName, 'sendmail'); - - /* Send it. */ - $this->loadModel('mail')->send($toList, $productName . ':' . 'BUG #'. $bug->id . $this->lang->colon . $bug->title, $mailContent, $ccList); - if($this->mail->isError()) echo js::error($this->mail->getError()); - } - - /** - * Get data to export - * - * @param string $productID - * @param string $orderBy - * @access public - * @return void - */ - public function export($productID, $orderBy) - { - if($_POST) - { - $bugLang = $this->lang->bug; - $bugConfig = $this->config->bug; - - /* Create field lists. */ - $fields = explode(',', $bugConfig->list->exportFields); - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($bugLang->$fieldName) ? $bugLang->$fieldName : $fieldName; - unset($fields[$key]); - } - - /* Get bugs. */ - $bugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugReportCondition)->orderBy($orderBy)->fetchAll('id'); - - /* Get users, products and projects. */ - $users = $this->loadModel('user')->getPairs('noletter'); - $products = $this->loadModel('product')->getPairs(); - $projects = $this->loadModel('project')->getPairs('all'); - - /* Get related objects id lists. */ - $relatedModuleIdList = array(); - $relatedStoryIdList = array(); - $relatedTaskIdList = array(); - $relatedBugIdList = array(); - $relatedCaseIdList = array(); - $relatedBuildIdList = array(); - - foreach($bugs as $bug) - { - $relatedModuleIdList[$bug->module] = $bug->module; - $relatedStoryIdList[$bug->story] = $bug->story; - $relatedTaskIdList[$bug->task] = $bug->task; - $relatedCaseIdList[$bug->case] = $bug->case; - $relatedBugIdList[$bug->duplicateBug] = $bug->duplicateBug; - - /* Process link bugs. */ - $linkBugs = explode(',', $bug->linkBug); - foreach($linkBugs as $linkBugID) - { - if($linkBugID) $relatedBugIdList[$linkBugID] = trim($linkBugID); - } - - /* Process builds. */ - $builds = $bug->openedBuild . ',' . $bug->resolvedBuild; - $builds = explode(',', $builds); - foreach($builds as $buildID) - { - if($buildID) $relatedBuildIdList[$buildID] = trim($buildID); - } - } - - /* Get related objects title or names. */ - $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); - $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); - $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs(); - $relatedBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('id')->in($relatedBugIdList)->fetchPairs(); - $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); - $relatedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($relatedBuildIdList)->fetchPairs(); - $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('bug')->andWhere('objectID')->in(@array_keys($bugs))->fetchGroup('objectID'); - - foreach($bugs as $bug) - { - if($this->post->fileType == 'csv') - { - $bug->steps = htmlspecialchars_decode($bug->steps); - $bug->steps = str_replace("
", "\n", $bug->steps); - $bug->steps = str_replace('"', '""', $bug->steps); - $bug->steps = str_replace(' ', ' ', $bug->steps); - $bug->steps = strip_tags($bug->steps); - } - - /* fill some field with useful value. */ - if(isset($products[$bug->product])) $bug->product = $products[$bug->product]; - if(isset($projects[$bug->project])) $bug->project = $projects[$bug->project]; - if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module]; - if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story]; - if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task]; - if(isset($relatedBugs[$bug->duplicateBug])) $bug->duplicateBug = $relatedBugs[$bug->duplicateBug]; - if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case]; - - if(isset($bugLang->priList[$bug->pri])) $bug->pri = $bugLang->priList[$bug->pri]; - if(isset($bugLang->typeList[$bug->type])) $bug->type = $bugLang->typeList[$bug->type]; - if(isset($bugLang->statusList[$bug->status])) $bug->status = $bugLang->statusList[$bug->status]; - if(isset($bugLang->confirmedList[$bug->confirmed])) $bug->confirmed = $bugLang->confirmedList[$bug->confirmed]; - if(isset($bugLang->resolutionList[$bug->resolution])) $bug->resolution = $bugLang->resolutionList[$bug->resolution]; - - if(isset($users[$bug->openedBy])) $bug->openedBy = $users[$bug->openedBy]; - if(isset($users[$bug->assignedTo])) $bug->assignedTo = $users[$bug->assignedTo]; - if(isset($users[$bug->resolvedBy])) $bug->resolvedBy = $users[$bug->resolvedBy]; - if(isset($users[$bug->lastEditedBy])) $bug->lastEditedBy = $users[$bug->lastEditedBy]; - if(isset($users[$bug->closedBy])) $bug->closedBy = $users[$bug->closedBy]; - - $bug->openedDate = substr($bug->openedDate, 0, 10); - $bug->assignedDate = substr($bug->assignedDate, 0, 10); - $bug->closedDate = substr($bug->closedDate, 0, 10); - $bug->resolvedDate = substr($bug->resolvedDate, 0, 10); - $bug->lastEditedDate = substr($bug->lastEditedDate, 0, 10); - - if($bug->linkBug) - { - $tmpLinkBugs = array(); - $linkBugIdList = explode(',', $bug->linkBug); - foreach($linkBugIdList as $linkBugID) - { - $linkBugID = trim($linkBugID); - $tmpLinkBugs[] = isset($relatedBugs[$linkBugID]) ? $relatedBugs[$linkBugID] : $linkBugID; - } - $bug->linkBug = join("; \n", $tmpLinkBugs); - } - - if($bug->openedBuild) - { - $tmpOpenedBuilds = array(); - $tmpResolvedBuilds = array(); - $buildIdList = explode(',', $bug->openedBuild); - foreach($buildIdList as $buildID) - { - $buildID = trim($buildID); - $tmpOpenedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID; - } - $bug->openedBuild = join("; \n", $tmpOpenedBuilds); - } - - if($bug->resolvedBuild) - { - $buildIdList = explode(',', $bug->resolvedBuild); - foreach($buildIdList as $buildID) - { - $buildID = trim($buildID); - $tmpResolvedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID; - } - $bug->resolvedBuild = join("; \n", $tmpResolvedBuilds); - } - - /* Set related files. */ - if(isset($relatedFiles[$bug->id])) - { - foreach($relatedFiles[$bug->id] as $file) - { - $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$bug->company/" . $file->pathname; - $bug->files .= html::a($fileURL, $file->title, '_blank') . '
'; - } - } - - $bug->mailto = trim(trim($bug->mailto), ','); - $mailtos = explode(',', $bug->mailto); - $bug->mailto = ''; - foreach($mailtos as $mailto) - { - $mailto = trim($mailto); - if(isset($users[$mailto])) $bug->mailto .= $users[$mailto] . ','; - } - - /* drop some field that is not needed. */ - unset($bug->company); - unset($bug->caseVersion); - unset($bug->result); - unset($bug->deleted); - } - - $this->post->set('fields', $fields); - $this->post->set('rows', $bugs); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +class bug extends control +{ + private $products = array(); + + /** + * Construct function, load some modules auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('product'); + $this->loadModel('tree'); + $this->loadModel('user'); + $this->loadModel('action'); + $this->loadModel('story'); + $this->loadModel('task'); + $this->products = $this->product->getPairs(); + if(empty($this->products)) + { + echo js::alert($this->lang->product->errorNoProduct); + die(js::locate($this->createLink('product', 'create'))); + } + $this->view->products = $this->products; + } + + /** + * The index page, locate to browse. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('bug', 'browse')); + } + + /** + * Browse bugs. + * + * @param int $productID + * @param string $browseType + * @param int $param + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Set browseType, productID, moduleID and queryID. */ + $browseType = strtolower($browseType); + $productID = $this->product->saveState($productID, $this->products); + $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Set menu and save session. */ + $this->bug->setMenu($this->products, $productID); + $this->session->set('bugList', $this->app->getURI(true)); + + /* Process the order by field. */ + if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc'; + setcookie('qaBugOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + $projects = $this->loadModel('project')->getPairs(); + $projects[0] = ''; + + /* Get bugs. */ + $bugs = array(); + if($browseType == 'all') $bugs = $this->bug->getAllBugs($productID, $projects, $orderBy, $pager); + elseif($browseType == "bymodule") + { + $childModuleIds = $this->tree->getAllChildId($moduleID); + $bugs = $this->bug->getModuleBugs($productID, $childModuleIds, $projects, $orderBy, $pager); + } + elseif($browseType == 'assigntome') $bugs = $this->bug->getByAssigntome($productID, $projects, $orderBy, $pager); + elseif($browseType == 'openedbyme') $bugs = $this->bug->getByOpenedbyme($productID, $projects, $orderBy, $pager); + elseif($browseType == 'resolvedbyme') $bugs = $this->bug->getByResolvedbyme($productID, $projects, $orderBy, $pager); + elseif($browseType == 'assigntonull') $bugs = $this->bug->getByAssigntonull($productID, $projects, $orderBy, $pager); + elseif($browseType == 'unresolved') $bugs = $this->bug->getByStatus($productID, $projects, 'unresolved', $orderBy, $pager); + elseif($browseType == 'unclosed') $bugs = $this->bug->getByStatus($productID, $projects, 'unclosed', $orderBy, $pager); + elseif($browseType == 'longlifebugs') $bugs = $this->bug->getByLonglifebugs($productID, $projects, $orderBy, $pager); + elseif($browseType == 'postponedbugs') $bugs = $this->bug->getByPostponedbugs($productID, $projects, $orderBy, $pager); + elseif($browseType == 'needconfirm') $bugs = $this->bug->getByNeedconfirm($productID, $projects, $orderBy, $pager); + elseif($browseType == 'bysearch') $bugs = $this->bug->getBySearch($productID, $projects, $queryID, $orderBy, $pager); + + /* Process the sql, get the conditon partion, save it to session. Thus the report page can use the same condition. */ + if($browseType != 'needconfirm') + { + $sql = explode('WHERE', $this->dao->get()); + $sql = explode('ORDER', $sql[1]); + $this->session->set('bugReportCondition', $sql[0]); + } + + /* Get custom fields. */ + $customFields = $this->cookie->bugFields != false ? $this->cookie->bugFields : $this->config->bug->list->defaultFields; + $customed = !($customFields == $this->config->bug->list->defaultFields); + + /* If customed, get related name or titles. */ + if($customed) $bugs = $this->bug->formCustomedBugs($bugs); + + /* Build the search form. */ + $this->config->bug->search['actionURL'] = $this->createLink('bug', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); + $this->config->bug->search['queryID'] = $queryID; + $this->config->bug->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->bug->allProduct); + $this->config->bug->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); + $this->config->bug->search['params']['project']['values'] = $this->product->getProjectPairs($productID); + $this->config->bug->search['params']['openedBuild']['values'] = $this->loadModel('build')->getProductBuildPairs($productID); + $this->config->bug->search['params']['resolvedBuild']['values'] = $this->build->getProductBuildPairs($productID); + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->bug->search); + + $users = $this->user->getPairs('noletter'); + + $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common; + $position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $position[] = $this->lang->bug->common; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'bug', $startModuleID = 0, array('treeModel', 'createBugLink')); + $this->view->browseType = $browseType; + $this->view->bugs = $bugs; + $this->view->users = $users; + $this->view->pager = $pager; + $this->view->param = $param; + $this->view->orderBy = $orderBy; + $this->view->moduleID = $moduleID; + $this->view->customed = $customed; + $this->view->customFields= explode(',', str_replace(' ', '', trim($customFields))); + $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; + + $this->display(); + } + + /** + * The report page. + * + * @param int $productID + * @param string $browseType + * @param int $moduleID + * @access public + * @return void + */ + public function report($productID, $browseType, $moduleID) + { + $this->loadModel('report'); + $this->view->charts = array(); + $this->view->renderJS = ''; + + if(!empty($_POST)) + { + foreach($this->post->charts as $chart) + { + $chartFunc = 'getDataOf' . $chart; + $chartData = $this->bug->$chartFunc(); + $chartOption = $this->lang->bug->report->$chart; + $this->bug->mergeChartOption($chart); + + $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); + $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); + $this->view->datas[$chart] = $this->report->computePercent($chartData); + } + $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); + } + + $this->bug->setMenu($this->products, $productID); + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->common; + $this->view->productID = $productID; + $this->view->browseType = $browseType; + $this->view->moduleID = $moduleID; + $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; + $this->display(); + } + + /** + * Create a bug. + * + * @param int $productID + * @param string $extras others params, forexample, projectID=10,moduleID=10 + * @access public + * @return void + */ + public function create($productID, $extras = '') + { + $this->view->users = $this->user->getPairs('nodeleted'); + if(empty($this->products)) $this->locate($this->createLink('product', 'create')); + + if(!empty($_POST)) + { + $bugID = $this->bug->create(); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('bug', $bugID, 'Opened'); + $this->sendmail($bugID, $actionID); + die(js::locate($this->createLink('bug', 'browse', "productID={$this->post->product}&type=byModule¶m={$this->post->module}"), 'parent')); + } + + /* Get product, then set menu. */ + $productID = $this->product->saveState($productID, $this->products); + $this->bug->setMenu($this->products, $productID); + + /* Remove the unused types. */ + unset($this->lang->bug->typeList['designchange']); + unset($this->lang->bug->typeList['newfeature']); + unset($this->lang->bug->typeList['trackthings']); + + /* Init vars. */ + $moduleID = 0; + $projectID = 0; + $taskID = 0; + $storyID = 0; + $buildID = 0; + $caseID = 0; + $runID = 0; + $title = ''; + $steps = $this->lang->bug->tplStep . $this->lang->bug->tplResult . $this->lang->bug->tplExpect; + $os = ''; + $browser = ''; + $assignedTo = ''; + $mailto = ''; + $keywords = ''; + $severity = 3; + $type = 'codeerror'; + + /* Parse the extras. */ + $extras = str_replace(array(',', ' '), array('&', ''), $extras); + parse_str($extras); + + /* If set runID, get the last result info as the template. */ + if($runID > 0) $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->limit(1)->fetch('id'); + if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID)); + + /* If set caseID and runID='', get the last result info as the template. */ + if($caseID > 0 && $runID == '') + { + $resultID = $this->dao->select('id')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('date desc')->limit(1)->fetch('id'); + if(isset($resultID) and $resultID > 0) extract($this->bug->getBugInfoFromResult($resultID, $caseID, $version)); + } + + /* If bugID setted, use this bug as template. */ + if(isset($bugID)) + { + $bug = $this->bug->getById($bugID); + extract((array)$bug); + $projectID = $bug->project; + $moduleID = $bug->module; + $taskID = $bug->task; + $storyID = $bug->story; + $buildID = $bug->openedBuild; + $severity = $bug->severity; + $type = $bug->type; + } + + /* If projectID is setted, get builds and stories of this project. */ + if($projectID) + { + $builds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty'); + $stories = $this->story->getProjectStoryPairs($projectID); + } + else + { + $builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); + $stories = $this->story->getProductStoryPairs($productID); + } + + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->create; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->create; + + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); + $this->view->stories = $stories; + $this->view->projects = $this->product->getProjectPairs($productID, $params = 'nodeleted'); + $this->view->builds = $builds; + $this->view->tasks = $this->loadModel('task')->getProjectTaskPairs($projectID); + $this->view->moduleID = $moduleID; + $this->view->projectID = $projectID; + $this->view->taskID = $taskID; + $this->view->storyID = $storyID; + $this->view->buildID = $buildID; + $this->view->caseID = $caseID; + $this->view->title = $title; + $this->view->steps = htmlspecialchars($steps); + $this->view->os = $os; + $this->view->browser = $browser; + $this->view->assignedTo = $assignedTo; + $this->view->mailto = $mailto; + $this->view->keywords = $keywords; + $this->view->severity = $severity; + $this->view->type = $type; + + $this->display(); + } + + /** + * View a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function view($bugID) + { + /* Judge bug exits or not. */ + $bug = $this->bug->getById($bugID); + if(!$bug) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Set menu. */ + $this->bug->setMenu($this->products, $bug->product); + + /* Get product info. */ + $productID = $bug->product; + $productName = $this->products[$productID]; + + /* Header and positon. */ + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->view; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $productName); + $this->view->position[] = $this->lang->bug->view; + + /* Assign. */ + $this->view->productID = $productID; + $this->view->productName = $productName; + $this->view->modulePath = $this->tree->getParents($bug->module); + $this->view->bug = $bug; + $this->view->users = $this->user->getPairs('noletter'); + $this->view->actions = $this->action->getList('bug', $bugID); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); + + $this->display(); + } + + /** + * Edit a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function edit($bugID, $comment = false) + { + if(!empty($_POST)) + { + $changes = array(); + $files = array(); + if($comment == false) + { + $changes = $this->bug->update($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $files = $this->loadModel('file')->saveUpload('bug', $bugID); + } + if($this->post->comment != '' or !empty($changes) or !empty($files)) + { + $action = !empty($changes) ? 'Edited' : 'Commented'; + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; + $actionID = $this->action->create('bug', $bugID, $action, $fileAction . $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($bugID, $actionID); + } + + $bug = $this->bug->getById($bugID); + if($bug->toTask != 0) + { + foreach($changes as $change) + { + if($change['field'] == 'status') + { + $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask"); + $cancelURL = $this->server->HTTP_REFERER; + die(js::confirm(sprintf($this->lang->task->remindTask, $bug->Task), $confirmURL, $cancelURL, 'parent', 'parent')); + } + } + } + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + /* Get the info of bug, current product and modue. */ + $bug = $this->bug->getById($bugID); + $productID = $bug->product; + $projectID = $bug->project; + $currentModuleID = $bug->module; + + /** + * Remove designchange, newfeature, trackings from the typeList, because should be tracked in story or task. + * These thress types if upgrade from bugfree2.x. + */ + if($bug->type != 'designchange') unset($this->lang->bug->typeList['designchange']); + if($bug->type != 'newfeature') unset($this->lang->bug->typeList['newfeature']); + if($bug->type != 'trackthings') unset($this->lang->bug->typeList['trackthings']); + + /* Set the menu. */ + $this->bug->setMenu($this->products, $productID); + + /* Set header and position. */ + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->edit; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->edit; + + /* Assign. */ + if($projectID) + { + $this->view->openedBuilds = $this->loadModel('build')->getProjectBuildPairs($projectID, $productID, 'noempty'); + } + else + { + $this->view->openedBuilds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); + } + $this->view->bug = $bug; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'bug', $startModuleID = 0); + $this->view->currentModuleID = $currentModuleID; + $this->view->projects = $this->product->getProjectPairs($bug->product); + $this->view->stories = $bug->project ? $this->story->getProjectStoryPairs($bug->project) : $this->story->getProductStoryPairs($bug->product); + $this->view->tasks = $this->task->getProjectTaskPairs($bug->project); + $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), "$bug->assignedTo,$bug->resolvedBy,$bug->closedBy"); + $this->view->resolvedBuilds = array('' => '') + $this->view->openedBuilds; + $this->view->actions = $this->action->getList('bug', $bugID); + $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account); + + $this->display(); + } + + /** + * confirm a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function confirmBug($bugID) + { + if(!empty($_POST)) + { + $this->bug->confirm($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('bug', $bugID, 'bugConfirmed', $this->post->comment); + $this->sendmail($bugID, $actionID); + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + $bug = $this->bug->getById($bugID); + $productID = $bug->product; + $this->bug->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->confirmBug; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->confirmBug; + + $this->view->bug = $bug; + $this->view->actions = $this->action->getList('bug', $bugID); + $this->display(); + } + + /** + * Resolve a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function resolve($bugID) + { + $this->view->users = $this->user->getPairs('nodeleted'); + + if(!empty($_POST)) + { + $this->bug->resolve($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('bug', $bugID, 'Resolved', $this->post->comment, $this->post->resolution); + $this->sendmail($bugID, $actionID); + + $bug = $this->bug->getById($bugID); + if($bug->toTask != 0) + { + $confirmURL = $this->createLink('task', 'view', "taskID=$bug->toTask"); + $cancelURL = $this->createLink('bug', 'view', "bugID=$bugID"); + die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent')); + } + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + $bug = $this->bug->getById($bugID); + $productID = $bug->product; + $this->bug->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->resolve; + + $this->view->bug = $bug; + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); + $this->view->actions = $this->action->getList('bug', $bugID); + $this->display(); + } + + /** + * Activate a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function activate($bugID) + { + $this->view->users = $this->user->getPairs('nodeleted'); + + if(!empty($_POST)) + { + $this->bug->activate($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $files = $this->loadModel('file')->saveUpload('bug', $bugID); + $actionID = $this->action->create('bug', $bugID, 'Activated', $this->post->comment); + $this->sendmail($bugID, $actionID); + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + $bug = $this->bug->getById($bugID); + $productID = $bug->product; + $this->bug->setMenu($this->products, $productID); + + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->activate; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->activate; + + $this->view->bug = $bug; + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID, 'noempty'); + $this->view->actions = $this->action->getList('bug', $bugID); + + $this->display(); + } + + /** + * Close a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function close($bugID) + { + $this->view->users = $this->user->getPairs('noletter'); + if(!empty($_POST)) + { + $this->bug->close($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('bug', $bugID, 'Closed', $this->post->comment); + $this->sendmail($bugID, $actionID); + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + $bug = $this->bug->getById($bugID); + $productID = $bug->product; + $this->bug->setMenu($this->products, $productID); + + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->close; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->close; + + $this->view->bug = $bug; + $this->view->actions = $this->action->getList('bug', $bugID); + $this->display(); + } + + /** + * Confirm story change. + * + * @param int $bugID + * @access public + * @return void + */ + public function confirmStoryChange($bugID) + { + $bug = $this->bug->getById($bugID); + $this->dao->update(TABLE_BUG)->set('storyVersion')->eq($bug->latestStoryVersion)->where('id')->eq($bugID)->exec(); + $this->loadModel('action')->create('bug', $bugID, 'confirmed', '', $bug->latestStoryVersion); + die(js::reload('parent')); + } + + /** + * Delete a bug. + * + * @param int $bugID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($bugID, $confirm = 'no') + { + $bug = $this->bug->getById($bugID); + if($confirm == 'no') + { + die(js::confirm($this->lang->bug->confirmDelete, inlink('delete', "bugID=$bugID&confirm=yes"))); + } + else + { + $this->bug->delete(TABLE_BUG, $bugID); + if($bug->toTask != 0) echo js::alert($this->lang->bug->remindTask . $bug->toTask); + die(js::locate($this->session->bugList, 'parent')); + } + } + + /** + * Save current template. + * + * @access public + * @return string + */ + public function saveTemplate() + { + $this->bug->saveUserBugTemplate(); + if(dao::isError()) die(js::error(dao::getError())); + die($this->fetch('bug', 'buildTemplates')); + } + + /** + * Build the user templates selection code. + * + * @access public + * @return void + */ + public function buildTemplates() + { + $this->view->templates = $this->bug->getUserBugTemplates($this->app->user->account); + $this->display('bug', 'buildTemplates'); + } + + /** + * Delete a user template. + * + * @param int $templateID + * @access public + * @return void + */ + public function deleteTemplate($templateID) + { + $this->dao->delete()->from(TABLE_USERTPL)->where('id')->eq($templateID)->andWhere('account')->eq($this->app->user->account)->exec(); + die(); + } + + /** + * Custom fields. + * + * @access public + * @return void + */ + public function customFields() + { + if($_POST) + { + $customFields = $this->post->customFields; + $customFields = join(',', $customFields); + setcookie('bugFields', $customFields, $this->config->cookieLife, $this->config->webRoot); + die(js::reload('parent')); + } + + $customFields = $this->cookie->bugFields ? $this->cookie->bugFields : $this->config->bug->list->defaultFields; + + $this->view->allFields = $this->bug->getFieldPairs($this->config->bug->list->allFields); + $this->view->customFields = $this->bug->getFieldPairs($customFields); + $this->view->defaultFields = $this->bug->getFieldPairs($this->config->bug->list->defaultFields); + die($this->display()); + } + + /** + * AJAX: get bugs of a user in html select. + * + * @param string $account + * @access public + * @return string + */ + public function ajaxGetUserBugs($account = '') + { + if($account == '') $account = $this->app->user->account; + $bugs = $this->bug->getUserBugPairs($account); + die(html::select('bug', $bugs, '', 'class=select-1')); + } + + /** + * AJAX: Get bug owner of a module. + * + * @param int $moduleID + * @param int $productID + * @access public + * @return string + */ + public function ajaxGetModuleOwner($moduleID, $productID = 0) + { + $owner = ''; + if($moduleID) $owner = $this->dao->findByID($moduleID)->from(TABLE_MODULE)->fetch('owner'); + if(!$owner) $owner = $this->dao->findByID($productID)->from(TABLE_PRODUCT)->fetch('QM'); + die($owner); + } + + /** + * Send email. + * + * @param int $bugID + * @param int $actionID + * @access private + * @return void + */ + private function sendmail($bugID, $actionID) + { + /* Set toList and ccList. */ + $bug = $this->bug->getByID($bugID); + $productName = $this->products[$bug->product]; + $toList = $bug->assignedTo; + $ccList = trim($bug->mailto, ','); + if($toList == '') + { + if($ccList == '') return; + if(strpos($ccList, ',') === false) + { + $toList = $ccList; + $ccList = ''; + } + else + { + $commaPos = strpos($ccList, ','); + $toList = substr($ccList, 0, $commaPos); + $ccList = substr($ccList, $commaPos + 1); + } + } + elseif(strtolower($toList) == 'closed') + { + $toList = $bug->resolvedBy; + } + + /* Get action info. */ + $action = $this->action->getById($actionID); + $history = $this->action->getHistory($actionID); + $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); + if(strtolower($action->action) == 'opened') $action->comment = $bug->steps; + + /* Create the mail content. */ + $this->view->bug = $bug; + $this->view->action = $action; + $mailContent = $this->parse($this->moduleName, 'sendmail'); + + /* Send it. */ + $this->loadModel('mail')->send($toList, $productName . ':' . 'BUG #'. $bug->id . $this->lang->colon . $bug->title, $mailContent, $ccList); + if($this->mail->isError()) echo js::error($this->mail->getError()); + } + + /** + * Get data to export + * + * @param string $productID + * @param string $orderBy + * @access public + * @return void + */ + public function export($productID, $orderBy) + { + if($_POST) + { + $bugLang = $this->lang->bug; + $bugConfig = $this->config->bug; + + /* Create field lists. */ + $fields = explode(',', $bugConfig->list->exportFields); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($bugLang->$fieldName) ? $bugLang->$fieldName : $fieldName; + unset($fields[$key]); + } + + /* Get bugs. */ + $bugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugReportCondition)->orderBy($orderBy)->fetchAll('id'); + + /* Get users, products and projects. */ + $users = $this->loadModel('user')->getPairs('noletter'); + $products = $this->loadModel('product')->getPairs(); + $projects = $this->loadModel('project')->getPairs('all'); + + /* Get related objects id lists. */ + $relatedModuleIdList = array(); + $relatedStoryIdList = array(); + $relatedTaskIdList = array(); + $relatedBugIdList = array(); + $relatedCaseIdList = array(); + $relatedBuildIdList = array(); + + foreach($bugs as $bug) + { + $relatedModuleIdList[$bug->module] = $bug->module; + $relatedStoryIdList[$bug->story] = $bug->story; + $relatedTaskIdList[$bug->task] = $bug->task; + $relatedCaseIdList[$bug->case] = $bug->case; + $relatedBugIdList[$bug->duplicateBug] = $bug->duplicateBug; + + /* Process link bugs. */ + $linkBugs = explode(',', $bug->linkBug); + foreach($linkBugs as $linkBugID) + { + if($linkBugID) $relatedBugIdList[$linkBugID] = trim($linkBugID); + } + + /* Process builds. */ + $builds = $bug->openedBuild . ',' . $bug->resolvedBuild; + $builds = explode(',', $builds); + foreach($builds as $buildID) + { + if($buildID) $relatedBuildIdList[$buildID] = trim($buildID); + } + } + + /* Get related objects title or names. */ + $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); + $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); + $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs(); + $relatedBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('id')->in($relatedBugIdList)->fetchPairs(); + $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); + $relatedBuilds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->in($relatedBuildIdList)->fetchPairs(); + $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('bug')->andWhere('objectID')->in(@array_keys($bugs))->fetchGroup('objectID'); + + foreach($bugs as $bug) + { + if($this->post->fileType == 'csv') + { + $bug->steps = htmlspecialchars_decode($bug->steps); + $bug->steps = str_replace("
", "\n", $bug->steps); + $bug->steps = str_replace('"', '""', $bug->steps); + $bug->steps = str_replace(' ', ' ', $bug->steps); + $bug->steps = strip_tags($bug->steps); + } + + /* fill some field with useful value. */ + if(isset($products[$bug->product])) $bug->product = $products[$bug->product]; + if(isset($projects[$bug->project])) $bug->project = $projects[$bug->project]; + if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module]; + if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story]; + if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task]; + if(isset($relatedBugs[$bug->duplicateBug])) $bug->duplicateBug = $relatedBugs[$bug->duplicateBug]; + if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case]; + + if(isset($bugLang->priList[$bug->pri])) $bug->pri = $bugLang->priList[$bug->pri]; + if(isset($bugLang->typeList[$bug->type])) $bug->type = $bugLang->typeList[$bug->type]; + if(isset($bugLang->statusList[$bug->status])) $bug->status = $bugLang->statusList[$bug->status]; + if(isset($bugLang->confirmedList[$bug->confirmed])) $bug->confirmed = $bugLang->confirmedList[$bug->confirmed]; + if(isset($bugLang->resolutionList[$bug->resolution])) $bug->resolution = $bugLang->resolutionList[$bug->resolution]; + + if(isset($users[$bug->openedBy])) $bug->openedBy = $users[$bug->openedBy]; + if(isset($users[$bug->assignedTo])) $bug->assignedTo = $users[$bug->assignedTo]; + if(isset($users[$bug->resolvedBy])) $bug->resolvedBy = $users[$bug->resolvedBy]; + if(isset($users[$bug->lastEditedBy])) $bug->lastEditedBy = $users[$bug->lastEditedBy]; + if(isset($users[$bug->closedBy])) $bug->closedBy = $users[$bug->closedBy]; + + $bug->openedDate = substr($bug->openedDate, 0, 10); + $bug->assignedDate = substr($bug->assignedDate, 0, 10); + $bug->closedDate = substr($bug->closedDate, 0, 10); + $bug->resolvedDate = substr($bug->resolvedDate, 0, 10); + $bug->lastEditedDate = substr($bug->lastEditedDate, 0, 10); + + if($bug->linkBug) + { + $tmpLinkBugs = array(); + $linkBugIdList = explode(',', $bug->linkBug); + foreach($linkBugIdList as $linkBugID) + { + $linkBugID = trim($linkBugID); + $tmpLinkBugs[] = isset($relatedBugs[$linkBugID]) ? $relatedBugs[$linkBugID] : $linkBugID; + } + $bug->linkBug = join("; \n", $tmpLinkBugs); + } + + if($bug->openedBuild) + { + $tmpOpenedBuilds = array(); + $tmpResolvedBuilds = array(); + $buildIdList = explode(',', $bug->openedBuild); + foreach($buildIdList as $buildID) + { + $buildID = trim($buildID); + $tmpOpenedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID; + } + $bug->openedBuild = join("; \n", $tmpOpenedBuilds); + } + + if($bug->resolvedBuild) + { + $buildIdList = explode(',', $bug->resolvedBuild); + foreach($buildIdList as $buildID) + { + $buildID = trim($buildID); + $tmpResolvedBuilds[] = isset($relatedBuilds[$buildID]) ? $relatedBuilds[$buildID] : $buildID; + } + $bug->resolvedBuild = join("; \n", $tmpResolvedBuilds); + } + + /* Set related files. */ + if(isset($relatedFiles[$bug->id])) + { + foreach($relatedFiles[$bug->id] as $file) + { + $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$bug->company/" . $file->pathname; + $bug->files .= html::a($fileURL, $file->title, '_blank') . '
'; + } + } + + $bug->mailto = trim(trim($bug->mailto), ','); + $mailtos = explode(',', $bug->mailto); + $bug->mailto = ''; + foreach($mailtos as $mailto) + { + $mailto = trim($mailto); + if(isset($users[$mailto])) $bug->mailto .= $users[$mailto] . ','; + } + + /* drop some field that is not needed. */ + unset($bug->company); + unset($bug->caseVersion); + unset($bug->result); + unset($bug->deleted); + } + + $this->post->set('fields', $fields); + $this->post->set('rows', $bugs); + $this->fetch('file', 'export2' . $this->post->fileType, $_POST); + } + + $this->display(); + } +} diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php index 09db614e9a..23e577b833 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -1,312 +1,312 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -/* Fieldlist. */ -$lang->bug->common = 'Bug'; -$lang->bug->id = 'ID'; -$lang->bug->product = 'Product'; -$lang->bug->module = 'Module'; -$lang->bug->path = 'Path'; -$lang->bug->project = 'Project'; -$lang->bug->story = 'Story'; -$lang->bug->storyVersion = 'Story Version'; -$lang->bug->task = 'Task'; -$lang->bug->title = 'Title'; -$lang->bug->severity = 'Severity'; -$lang->bug->severityAB = 'S'; -$lang->bug->pri = 'Priority'; -$lang->bug->type = 'Type'; -$lang->bug->os = 'OS'; -$lang->bug->hardware = 'Hardware'; -$lang->bug->browser = 'Browser'; -$lang->bug->machine = 'Machine'; -$lang->bug->found = 'How found'; -$lang->bug->steps = 'Steps'; -$lang->bug->status = 'Status'; -$lang->bug->statusAB = 'Status'; -$lang->bug->activatedCount = 'Activated count'; -$lang->bug->activatedCountAB = 'Activated count'; -$lang->bug->confirmed = 'Confirmed'; -$lang->bug->toTask = 'To task'; -$lang->bug->toStory = 'To story'; -$lang->bug->mailto = 'Mailto'; -$lang->bug->openedBy = 'Opened By'; -$lang->bug->openedByAB = 'Opened'; -$lang->bug->openedDate = 'Opened date'; -$lang->bug->openedDateAB = 'Date'; -$lang->bug->openedBuild = 'Opened Build'; -$lang->bug->assignedTo = 'Assigned'; -$lang->bug->assignedDate = 'Assigned Date'; -$lang->bug->resolvedBy = 'Resolved By'; -$lang->bug->resolvedByAB = 'Resolve'; -$lang->bug->resolution = 'Resolution'; -$lang->bug->resolutionAB = 'Resolution'; -$lang->bug->resolvedBuild = 'Resolved Build'; -$lang->bug->resolvedDate = 'Resolved Date'; -$lang->bug->resolvedDateAB = 'Date'; -$lang->bug->closedBy = 'Closed By'; -$lang->bug->closedDate = 'Closed Date'; -$lang->bug->duplicateBug = 'Duplicate'; -$lang->bug->lastEditedBy = 'Last Edited By'; -$lang->bug->lastEditedDate = 'Last Edited Date'; -$lang->bug->linkBug = 'Related'; -$lang->bug->case = 'Case'; -$lang->bug->files = 'Files'; -$lang->bug->keywords = 'Keywords'; -$lang->bug->lastEditedByAB = 'Edited'; -$lang->bug->lastEditedDateAB = 'Edited Date'; - -/* Actions. */ -$lang->bug->index = 'Index'; -$lang->bug->create = 'Create Bug'; -$lang->bug->confirmBug = 'Confirm Bug'; -$lang->bug->edit = 'Edit Bug'; -$lang->bug->browse = 'Browse Bug'; -$lang->bug->view = 'Bug Info'; -$lang->bug->resolve = 'Resolve Bug'; -$lang->bug->close = 'Close Bug'; -$lang->bug->activate = 'Activate Bug'; -$lang->bug->reportChart = 'Report'; -$lang->bug->export = 'Export data'; -$lang->bug->delete = 'Delete Bug'; -$lang->bug->saveTemplate = 'Save template'; -$lang->bug->deleteTemplate = 'Delete template'; -$lang->bug->customFields = 'Custom'; -$lang->bug->restoreDefault = 'Default'; -$lang->bug->ajaxGetUserBugs = 'API: My Bugs'; -$lang->bug->ajaxGetModuleOwner = 'API: Get module default owner'; -$lang->bug->confirmStoryChange = 'Confirm Story Change'; - -/* Browse tabs. */ -$lang->bug->selectProduct = 'Select product'; -$lang->bug->byModule = 'ByModule'; -$lang->bug->assignToMe = 'MyBugs'; -$lang->bug->openedByMe = 'MyOpen'; -$lang->bug->resolvedByMe = 'MyResolve'; -$lang->bug->closedByMe = 'MyClose'; -$lang->bug->assignToNull = 'Unassigned'; -$lang->bug->unResolved = 'Unresolved'; -$lang->bug->unclosed = 'Unclosed'; -$lang->bug->longLifeBugs = 'Longlife'; -$lang->bug->postponedBugs = 'Postponed'; -$lang->bug->allBugs = 'Allbug'; -$lang->bug->moduleBugs = 'ByModule'; -$lang->bug->byQuery = 'Search'; -$lang->bug->needConfirm = 'StoryChanged'; -$lang->bug->allProduct = 'All products'; - -/* Labels. */ -$lang->bug->lblProductAndModule = 'Product&Module'; -$lang->bug->lblProjectAndTask = 'Project&Task'; -$lang->bug->lblStory = 'Story'; -$lang->bug->lblTypeAndSeverity = 'Type&Severity'; -$lang->bug->lblSystemBrowserAndHardware = 'OS&Browser'; -$lang->bug->lblAssignedTo = 'Assigned to'; -$lang->bug->lblMailto = 'Mailto'; -$lang->bug->lblLastEdited = 'Last edited'; -$lang->bug->lblResolved = 'Resolved'; -$lang->bug->lblAllFields = 'All Fields'; -$lang->bug->lblCustomFields = 'Custom Fields'; - -/* Legends. */ -$lang->bug->legendBasicInfo = 'Basic info'; -$lang->bug->legendMailto = 'Mailto'; -$lang->bug->legendAttatch = 'Files'; -$lang->bug->legendLinkBugs = 'Related bug'; -$lang->bug->legendPrjStoryTask = 'Project, story & task'; -$lang->bug->legendCases = 'Related case'; -$lang->bug->legendSteps = 'Steps'; -$lang->bug->legendAction = 'Action'; -$lang->bug->legendHistory = 'History'; -$lang->bug->legendComment = 'Comment'; -$lang->bug->legendLife = 'Lifetime'; -$lang->bug->legendMisc = 'Misc'; - -/* Action buttons. */ -$lang->bug->buttonConfirm = 'Confirm'; -$lang->bug->buttonCopy = 'Copy'; -$lang->bug->buttonEdit = 'Edit'; -$lang->bug->buttonActivate = 'Activate'; -$lang->bug->buttonResolve = 'Resolve'; -$lang->bug->buttonClose = 'Close'; -$lang->bug->buttonToList = 'Back'; -$lang->bug->buttonCreateTestcase = 'Create case'; - -/* Confirm messags. */ -$lang->bug->confirmChangeProduct = 'Change product will change project, task and story also, are you sure?'; -$lang->bug->confirmDelete = 'Are you sure to delete this bug?'; -$lang->bug->setTemplateTitle = 'Please input the template title:'; -$lang->bug->remindTask = 'This bug has been to be a task, update the task:%s or not?'; - -/* Templates. */ -$lang->bug->tplStep = "

[Steps]

"; -$lang->bug->tplResult = "

[Result]

"; -$lang->bug->tplExpect = "

[Expect]

"; - -/* Field options lists. */ -$lang->bug->severityList[3] = '3'; -$lang->bug->severityList[1] = '1'; -$lang->bug->severityList[2] = '2'; -$lang->bug->severityList[4] = '4'; - -$lang->bug->priList[0] = ''; -$lang->bug->priList[3] = '3'; -$lang->bug->priList[1] = '1'; -$lang->bug->priList[2] = '2'; -$lang->bug->priList[4] = '4'; - -$lang->bug->osList[''] = ''; -$lang->bug->osList['all'] = 'All'; -$lang->bug->osList['windows'] = 'Windows'; -$lang->bug->osList['winxp'] = 'Windows XP'; -$lang->bug->osList['win7'] = 'Windows 7'; -$lang->bug->osList['vista'] = 'Windows Vista'; -$lang->bug->osList['win2000'] = 'Windows 2000'; -$lang->bug->osList['win2003'] = 'Windows 2003'; -$lang->bug->osList['win2008'] = 'Windows 2008'; -$lang->bug->osList['winnt'] = 'Windows NT'; -$lang->bug->osList['win98'] = 'Windows 98'; -$lang->bug->osList['andriod'] = 'Andriod'; -$lang->bug->osList['ios'] = 'IOS'; -$lang->bug->osList['wp7'] = 'WP7'; -$lang->bug->osList['symbian'] = 'Symbian'; -$lang->bug->osList['linux'] = 'Linux'; -$lang->bug->osList['freebsd'] = 'FreeBSD'; -$lang->bug->osList['mac'] = 'Mac OS'; -$lang->bug->osList['unix'] = 'Unix'; -$lang->bug->osList['others'] = 'Others'; - -$lang->bug->browserList[''] = ''; -$lang->bug->browserList['all'] = 'All'; -$lang->bug->browserList['ie'] = 'IE'; -$lang->bug->browserList['ie8'] = 'IE8'; -$lang->bug->browserList['ie9'] = 'IE9'; -$lang->bug->browserList['ie6'] = 'IE6'; -$lang->bug->browserList['ie7'] = 'IE7'; -$lang->bug->browserList['chrome'] = 'chrome'; -$lang->bug->browserList['firefox'] = 'Firefox'; -$lang->bug->browserList['firefox2'] = 'Firefox2'; -$lang->bug->browserList['firefox3'] = 'Firefox3'; -$lang->bug->browserList['firefox4'] = 'Firefox4'; -$lang->bug->browserList['opera'] = 'opera'; -$lang->bug->browserList['opera9'] = 'opera9'; -$lang->bug->browserList['oprea10'] = 'opera10'; -$lang->bug->browserList['oprea11'] = 'opera11'; -$lang->bug->browserList['safari'] = 'safari'; -$lang->bug->browserList['maxthon'] = '傲游'; -$lang->bug->browserList['uc'] = 'UC'; -$lang->bug->browserList['other'] = 'Others'; - -$lang->bug->typeList[''] = ''; -$lang->bug->typeList['codeerror'] = 'Code error'; -$lang->bug->typeList['interface'] = 'Interface'; -$lang->bug->typeList['designchange'] = 'Design change'; -$lang->bug->typeList['newfeature'] = 'New feature'; -$lang->bug->typeList['designdefect'] = 'Design defect'; -$lang->bug->typeList['config'] = 'Config'; -$lang->bug->typeList['install'] = 'Install'; -$lang->bug->typeList['security'] = 'Security'; -$lang->bug->typeList['performance'] = 'Performance'; -$lang->bug->typeList['standard'] = 'Standard'; -$lang->bug->typeList['automation'] = 'Automation'; -$lang->bug->typeList['trackthings'] = 'Tracking'; -$lang->bug->typeList['others'] = 'Others'; - -$lang->bug->statusList[''] = ''; -$lang->bug->statusList['active'] = 'Active'; -$lang->bug->statusList['resolved'] = 'Resolved'; -$lang->bug->statusList['closed'] = 'Closed'; - -$lang->bug->confirmedList[1] = 'Confirmed'; -$lang->bug->confirmedList[0] = 'Unconfirmed'; - -$lang->bug->resolutionList[''] = ''; -$lang->bug->resolutionList['bydesign'] = 'By design'; -$lang->bug->resolutionList['duplicate'] = 'Duplicate'; -$lang->bug->resolutionList['external'] = 'External'; -$lang->bug->resolutionList['fixed'] = 'Fixed'; -$lang->bug->resolutionList['notrepro'] = 'Not reproduce'; -$lang->bug->resolutionList['postponed'] = 'Postponed'; -$lang->bug->resolutionList['willnotfix'] = "Won't fix"; -$lang->bug->resolutionList['tostory'] = 'To story'; - -/* Report. */ -$lang->bug->report->common = 'Report'; -$lang->bug->report->select = 'Select'; -$lang->bug->report->create = 'Create'; -$lang->bug->report->selectAll = 'All'; -$lang->bug->report->selectReverse = 'Reverse'; - -$lang->bug->report->charts['bugsPerProject'] = 'Project bugs'; -$lang->bug->report->charts['bugsPerModule'] = 'Module bugs'; -$lang->bug->report->charts['openedBugsPerDay'] = 'Opened bugs per day'; -$lang->bug->report->charts['resolvedBugsPerDay'] = 'Resolved bugs per day'; -$lang->bug->report->charts['closedBugsPerDay'] = 'Closed bugs per day'; -$lang->bug->report->charts['openedBugsPerUser'] = 'Opened bugs per user'; -$lang->bug->report->charts['resolvedBugsPerUser'] = 'Resolved bugs per user'; -$lang->bug->report->charts['closedBugsPerUser'] = 'Closed bugs per user'; -$lang->bug->report->charts['bugsPerSeverity'] = 'Severity'; -$lang->bug->report->charts['bugsPerResolution'] = 'Resolution'; -$lang->bug->report->charts['bugsPerStatus'] = 'Status'; -$lang->bug->report->charts['bugsPerActivatedCount'] = 'Activated count'; -$lang->bug->report->charts['bugsPerType'] = 'Type'; -$lang->bug->report->charts['bugsPerAssignedTo'] = 'AssignedTo'; -//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计'; -//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计'; - -$lang->bug->report->options->swf = 'pie2d'; -$lang->bug->report->options->width = 'auto'; -$lang->bug->report->options->height = 300; -$lang->bug->report->options->graph->baseFontSize = 12; -$lang->bug->report->options->graph->showNames = 1; -$lang->bug->report->options->graph->formatNumber = 1; -$lang->bug->report->options->graph->decimalPrecision = 0; -$lang->bug->report->options->graph->animation = 0; -$lang->bug->report->options->graph->rotateNames = 0; -$lang->bug->report->options->graph->yAxisName = 'COUNT'; -$lang->bug->report->options->graph->pieRadius = 100; -$lang->bug->report->options->graph->showColumnShadow = 0; - -$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project'; -$lang->bug->report->bugsPerModule->graph->xAxisName = 'Module'; - -$lang->bug->report->openedBugsPerDay->swf = 'column2d'; -$lang->bug->report->openedBugsPerDay->height = 400; -$lang->bug->report->openedBugsPerDay->graph->xAxisName = 'Date'; -$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; -$lang->bug->report->resolvedBugsPerDay->height = 400; -$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = 'Date'; -$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->closedBugsPerDay->swf = 'column2d'; -$lang->bug->report->closedBugsPerDay->height = 400; -$lang->bug->report->closedBugsPerDay->graph->xAxisName = 'Date'; -$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->openedBugsPerUser->graph->xAxisName = 'User'; -$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= 'User'; -$lang->bug->report->closedBugsPerUser->graph->xAxisName = 'User'; - -$lang->bug->report->bugsPerSeverity->graph->xAxisName = 'Severity'; -$lang->bug->report->bugsPerResolution->graph->xAxisName = 'Resolution'; -$lang->bug->report->bugsPerStatus->graph->xAxisName = 'Status'; -$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = 'Activated count'; -$lang->bug->report->bugsPerType->graph->xAxisName = 'Type'; -$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = 'AssignedTo'; -$lang->bug->report->bugLiveDays->graph->xAxisName = 'Live days'; -$lang->bug->report->bugHistories->graph->xAxisName = 'Histories'; - -/* 操作记录。*/ -$lang->bug->action->resolved = array('main' => '$date, Resolved by $actor, resolution is $extra.', 'extra' => $lang->bug->resolutionList); -$lang->bug->action->tostory = array('main' => '$date, To story by $actor, ID is $extra.'); -$lang->bug->action->totask = array('main' => '$date, To task by $actor, ID is $extra.'); + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +/* Fieldlist. */ +$lang->bug->common = 'Bug'; +$lang->bug->id = 'ID'; +$lang->bug->product = 'Product'; +$lang->bug->module = 'Module'; +$lang->bug->path = 'Path'; +$lang->bug->project = 'Project'; +$lang->bug->story = 'Story'; +$lang->bug->storyVersion = 'Story Version'; +$lang->bug->task = 'Task'; +$lang->bug->title = 'Title'; +$lang->bug->severity = 'Severity'; +$lang->bug->severityAB = 'S'; +$lang->bug->pri = 'Priority'; +$lang->bug->type = 'Type'; +$lang->bug->os = 'OS'; +$lang->bug->hardware = 'Hardware'; +$lang->bug->browser = 'Browser'; +$lang->bug->machine = 'Machine'; +$lang->bug->found = 'How found'; +$lang->bug->steps = 'Steps'; +$lang->bug->status = 'Status'; +$lang->bug->statusAB = 'Status'; +$lang->bug->activatedCount = 'Activated count'; +$lang->bug->activatedCountAB = 'Activated count'; +$lang->bug->confirmed = 'Confirmed'; +$lang->bug->toTask = 'To task'; +$lang->bug->toStory = 'To story'; +$lang->bug->mailto = 'Mailto'; +$lang->bug->openedBy = 'Opened By'; +$lang->bug->openedByAB = 'Opened'; +$lang->bug->openedDate = 'Opened date'; +$lang->bug->openedDateAB = 'Date'; +$lang->bug->openedBuild = 'Opened Build'; +$lang->bug->assignedTo = 'Assigned'; +$lang->bug->assignedDate = 'Assigned Date'; +$lang->bug->resolvedBy = 'Resolved By'; +$lang->bug->resolvedByAB = 'Resolve'; +$lang->bug->resolution = 'Resolution'; +$lang->bug->resolutionAB = 'Resolution'; +$lang->bug->resolvedBuild = 'Resolved Build'; +$lang->bug->resolvedDate = 'Resolved Date'; +$lang->bug->resolvedDateAB = 'Date'; +$lang->bug->closedBy = 'Closed By'; +$lang->bug->closedDate = 'Closed Date'; +$lang->bug->duplicateBug = 'Duplicate'; +$lang->bug->lastEditedBy = 'Last Edited By'; +$lang->bug->lastEditedDate = 'Last Edited Date'; +$lang->bug->linkBug = 'Related'; +$lang->bug->case = 'Case'; +$lang->bug->files = 'Files'; +$lang->bug->keywords = 'Keywords'; +$lang->bug->lastEditedByAB = 'Edited'; +$lang->bug->lastEditedDateAB = 'Edited Date'; + +/* Actions. */ +$lang->bug->index = 'Index'; +$lang->bug->create = 'Create Bug'; +$lang->bug->confirmBug = 'Confirm Bug'; +$lang->bug->edit = 'Edit Bug'; +$lang->bug->browse = 'Browse Bug'; +$lang->bug->view = 'Bug Info'; +$lang->bug->resolve = 'Resolve Bug'; +$lang->bug->close = 'Close Bug'; +$lang->bug->activate = 'Activate Bug'; +$lang->bug->reportChart = 'Report'; +$lang->bug->export = 'Export data'; +$lang->bug->delete = 'Delete Bug'; +$lang->bug->saveTemplate = 'Save template'; +$lang->bug->deleteTemplate = 'Delete template'; +$lang->bug->customFields = 'Custom'; +$lang->bug->restoreDefault = 'Default'; +$lang->bug->ajaxGetUserBugs = 'API: My Bugs'; +$lang->bug->ajaxGetModuleOwner = 'API: Get module default owner'; +$lang->bug->confirmStoryChange = 'Confirm Story Change'; + +/* Browse tabs. */ +$lang->bug->selectProduct = 'Select product'; +$lang->bug->byModule = 'ByModule'; +$lang->bug->assignToMe = 'MyBugs'; +$lang->bug->openedByMe = 'MyOpen'; +$lang->bug->resolvedByMe = 'MyResolve'; +$lang->bug->closedByMe = 'MyClose'; +$lang->bug->assignToNull = 'Unassigned'; +$lang->bug->unResolved = 'Unresolved'; +$lang->bug->unclosed = 'Unclosed'; +$lang->bug->longLifeBugs = 'Longlife'; +$lang->bug->postponedBugs = 'Postponed'; +$lang->bug->allBugs = 'Allbug'; +$lang->bug->moduleBugs = 'ByModule'; +$lang->bug->byQuery = 'Search'; +$lang->bug->needConfirm = 'StoryChanged'; +$lang->bug->allProduct = 'All products'; + +/* Labels. */ +$lang->bug->lblProductAndModule = 'Product&Module'; +$lang->bug->lblProjectAndTask = 'Project&Task'; +$lang->bug->lblStory = 'Story'; +$lang->bug->lblTypeAndSeverity = 'Type&Severity'; +$lang->bug->lblSystemBrowserAndHardware = 'OS&Browser'; +$lang->bug->lblAssignedTo = 'Assigned to'; +$lang->bug->lblMailto = 'Mailto'; +$lang->bug->lblLastEdited = 'Last edited'; +$lang->bug->lblResolved = 'Resolved'; +$lang->bug->lblAllFields = 'All Fields'; +$lang->bug->lblCustomFields = 'Custom Fields'; + +/* Legends. */ +$lang->bug->legendBasicInfo = 'Basic info'; +$lang->bug->legendMailto = 'Mailto'; +$lang->bug->legendAttatch = 'Files'; +$lang->bug->legendLinkBugs = 'Related bug'; +$lang->bug->legendPrjStoryTask = 'Project, story & task'; +$lang->bug->legendCases = 'Related case'; +$lang->bug->legendSteps = 'Steps'; +$lang->bug->legendAction = 'Action'; +$lang->bug->legendHistory = 'History'; +$lang->bug->legendComment = 'Comment'; +$lang->bug->legendLife = 'Lifetime'; +$lang->bug->legendMisc = 'Misc'; + +/* Action buttons. */ +$lang->bug->buttonConfirm = 'Confirm'; +$lang->bug->buttonCopy = 'Copy'; +$lang->bug->buttonEdit = 'Edit'; +$lang->bug->buttonActivate = 'Activate'; +$lang->bug->buttonResolve = 'Resolve'; +$lang->bug->buttonClose = 'Close'; +$lang->bug->buttonToList = 'Back'; +$lang->bug->buttonCreateTestcase = 'Create case'; + +/* Confirm messags. */ +$lang->bug->confirmChangeProduct = 'Change product will change project, task and story also, are you sure?'; +$lang->bug->confirmDelete = 'Are you sure to delete this bug?'; +$lang->bug->setTemplateTitle = 'Please input the template title:'; +$lang->bug->remindTask = 'This bug has been to be a task, update the task:%s or not?'; + +/* Templates. */ +$lang->bug->tplStep = "

[Steps]

"; +$lang->bug->tplResult = "

[Result]

"; +$lang->bug->tplExpect = "

[Expect]

"; + +/* Field options lists. */ +$lang->bug->severityList[3] = '3'; +$lang->bug->severityList[1] = '1'; +$lang->bug->severityList[2] = '2'; +$lang->bug->severityList[4] = '4'; + +$lang->bug->priList[0] = ''; +$lang->bug->priList[3] = '3'; +$lang->bug->priList[1] = '1'; +$lang->bug->priList[2] = '2'; +$lang->bug->priList[4] = '4'; + +$lang->bug->osList[''] = ''; +$lang->bug->osList['all'] = 'All'; +$lang->bug->osList['windows'] = 'Windows'; +$lang->bug->osList['winxp'] = 'Windows XP'; +$lang->bug->osList['win7'] = 'Windows 7'; +$lang->bug->osList['vista'] = 'Windows Vista'; +$lang->bug->osList['win2000'] = 'Windows 2000'; +$lang->bug->osList['win2003'] = 'Windows 2003'; +$lang->bug->osList['win2008'] = 'Windows 2008'; +$lang->bug->osList['winnt'] = 'Windows NT'; +$lang->bug->osList['win98'] = 'Windows 98'; +$lang->bug->osList['andriod'] = 'Andriod'; +$lang->bug->osList['ios'] = 'IOS'; +$lang->bug->osList['wp7'] = 'WP7'; +$lang->bug->osList['symbian'] = 'Symbian'; +$lang->bug->osList['linux'] = 'Linux'; +$lang->bug->osList['freebsd'] = 'FreeBSD'; +$lang->bug->osList['mac'] = 'Mac OS'; +$lang->bug->osList['unix'] = 'Unix'; +$lang->bug->osList['others'] = 'Others'; + +$lang->bug->browserList[''] = ''; +$lang->bug->browserList['all'] = 'All'; +$lang->bug->browserList['ie'] = 'IE'; +$lang->bug->browserList['ie8'] = 'IE8'; +$lang->bug->browserList['ie9'] = 'IE9'; +$lang->bug->browserList['ie6'] = 'IE6'; +$lang->bug->browserList['ie7'] = 'IE7'; +$lang->bug->browserList['chrome'] = 'chrome'; +$lang->bug->browserList['firefox'] = 'Firefox'; +$lang->bug->browserList['firefox2'] = 'Firefox2'; +$lang->bug->browserList['firefox3'] = 'Firefox3'; +$lang->bug->browserList['firefox4'] = 'Firefox4'; +$lang->bug->browserList['opera'] = 'opera'; +$lang->bug->browserList['opera9'] = 'opera9'; +$lang->bug->browserList['oprea10'] = 'opera10'; +$lang->bug->browserList['oprea11'] = 'opera11'; +$lang->bug->browserList['safari'] = 'safari'; +$lang->bug->browserList['maxthon'] = '傲游'; +$lang->bug->browserList['uc'] = 'UC'; +$lang->bug->browserList['other'] = 'Others'; + +$lang->bug->typeList[''] = ''; +$lang->bug->typeList['codeerror'] = 'Code error'; +$lang->bug->typeList['interface'] = 'Interface'; +$lang->bug->typeList['designchange'] = 'Design change'; +$lang->bug->typeList['newfeature'] = 'New feature'; +$lang->bug->typeList['designdefect'] = 'Design defect'; +$lang->bug->typeList['config'] = 'Config'; +$lang->bug->typeList['install'] = 'Install'; +$lang->bug->typeList['security'] = 'Security'; +$lang->bug->typeList['performance'] = 'Performance'; +$lang->bug->typeList['standard'] = 'Standard'; +$lang->bug->typeList['automation'] = 'Automation'; +$lang->bug->typeList['trackthings'] = 'Tracking'; +$lang->bug->typeList['others'] = 'Others'; + +$lang->bug->statusList[''] = ''; +$lang->bug->statusList['active'] = 'Active'; +$lang->bug->statusList['resolved'] = 'Resolved'; +$lang->bug->statusList['closed'] = 'Closed'; + +$lang->bug->confirmedList[1] = 'Confirmed'; +$lang->bug->confirmedList[0] = 'Unconfirmed'; + +$lang->bug->resolutionList[''] = ''; +$lang->bug->resolutionList['bydesign'] = 'By design'; +$lang->bug->resolutionList['duplicate'] = 'Duplicate'; +$lang->bug->resolutionList['external'] = 'External'; +$lang->bug->resolutionList['fixed'] = 'Fixed'; +$lang->bug->resolutionList['notrepro'] = 'Not reproduce'; +$lang->bug->resolutionList['postponed'] = 'Postponed'; +$lang->bug->resolutionList['willnotfix'] = "Won't fix"; +$lang->bug->resolutionList['tostory'] = 'To story'; + +/* Report. */ +$lang->bug->report->common = 'Report'; +$lang->bug->report->select = 'Select'; +$lang->bug->report->create = 'Create'; +$lang->bug->report->selectAll = 'All'; +$lang->bug->report->selectReverse = 'Reverse'; + +$lang->bug->report->charts['bugsPerProject'] = 'Project bugs'; +$lang->bug->report->charts['bugsPerModule'] = 'Module bugs'; +$lang->bug->report->charts['openedBugsPerDay'] = 'Opened bugs per day'; +$lang->bug->report->charts['resolvedBugsPerDay'] = 'Resolved bugs per day'; +$lang->bug->report->charts['closedBugsPerDay'] = 'Closed bugs per day'; +$lang->bug->report->charts['openedBugsPerUser'] = 'Opened bugs per user'; +$lang->bug->report->charts['resolvedBugsPerUser'] = 'Resolved bugs per user'; +$lang->bug->report->charts['closedBugsPerUser'] = 'Closed bugs per user'; +$lang->bug->report->charts['bugsPerSeverity'] = 'Severity'; +$lang->bug->report->charts['bugsPerResolution'] = 'Resolution'; +$lang->bug->report->charts['bugsPerStatus'] = 'Status'; +$lang->bug->report->charts['bugsPerActivatedCount'] = 'Activated count'; +$lang->bug->report->charts['bugsPerType'] = 'Type'; +$lang->bug->report->charts['bugsPerAssignedTo'] = 'AssignedTo'; +//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计'; +//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计'; + +$lang->bug->report->options->swf = 'pie2d'; +$lang->bug->report->options->width = 'auto'; +$lang->bug->report->options->height = 300; +$lang->bug->report->options->graph->baseFontSize = 12; +$lang->bug->report->options->graph->showNames = 1; +$lang->bug->report->options->graph->formatNumber = 1; +$lang->bug->report->options->graph->decimalPrecision = 0; +$lang->bug->report->options->graph->animation = 0; +$lang->bug->report->options->graph->rotateNames = 0; +$lang->bug->report->options->graph->yAxisName = 'COUNT'; +$lang->bug->report->options->graph->pieRadius = 100; +$lang->bug->report->options->graph->showColumnShadow = 0; + +$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project'; +$lang->bug->report->bugsPerModule->graph->xAxisName = 'Module'; + +$lang->bug->report->openedBugsPerDay->swf = 'column2d'; +$lang->bug->report->openedBugsPerDay->height = 400; +$lang->bug->report->openedBugsPerDay->graph->xAxisName = 'Date'; +$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; +$lang->bug->report->resolvedBugsPerDay->height = 400; +$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = 'Date'; +$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->closedBugsPerDay->swf = 'column2d'; +$lang->bug->report->closedBugsPerDay->height = 400; +$lang->bug->report->closedBugsPerDay->graph->xAxisName = 'Date'; +$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->openedBugsPerUser->graph->xAxisName = 'User'; +$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= 'User'; +$lang->bug->report->closedBugsPerUser->graph->xAxisName = 'User'; + +$lang->bug->report->bugsPerSeverity->graph->xAxisName = 'Severity'; +$lang->bug->report->bugsPerResolution->graph->xAxisName = 'Resolution'; +$lang->bug->report->bugsPerStatus->graph->xAxisName = 'Status'; +$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = 'Activated count'; +$lang->bug->report->bugsPerType->graph->xAxisName = 'Type'; +$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = 'AssignedTo'; +$lang->bug->report->bugLiveDays->graph->xAxisName = 'Live days'; +$lang->bug->report->bugHistories->graph->xAxisName = 'Histories'; + +/* 操作记录。*/ +$lang->bug->action->resolved = array('main' => '$date, Resolved by $actor, resolution is $extra.', 'extra' => $lang->bug->resolutionList); +$lang->bug->action->tostory = array('main' => '$date, To story by $actor, ID is $extra.'); +$lang->bug->action->totask = array('main' => '$date, To task by $actor, ID is $extra.'); diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index 286e550364..fd5f8ab6d2 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -1,312 +1,312 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -/* 字段列表。*/ -$lang->bug->common = '缺陷管理'; -$lang->bug->id = 'Bug编号'; -$lang->bug->product = '所属产品'; -$lang->bug->module = '所属模块'; -$lang->bug->path = '模块路径'; -$lang->bug->project = '所属项目'; -$lang->bug->story = '相关需求'; -$lang->bug->storyVersion = '需求版本'; -$lang->bug->task = '相关任务'; -$lang->bug->title = 'Bug标题'; -$lang->bug->severity = '严重程度'; -$lang->bug->severityAB = '级别'; -$lang->bug->pri = '优先级'; -$lang->bug->type = 'Bug类型'; -$lang->bug->os = '操作系统'; -$lang->bug->hardware = '硬件平台'; -$lang->bug->browser = '浏览器'; -$lang->bug->machine = '机器硬件'; -$lang->bug->found = '如何发现'; -$lang->bug->steps = '重现步骤'; -$lang->bug->status = 'Bug状态'; -$lang->bug->statusAB = '状态'; -$lang->bug->activatedCount = '激活次数'; -$lang->bug->activatedCountAB = '激活次数'; -$lang->bug->confirmed = '是否确认'; -$lang->bug->toTask = '转任务'; -$lang->bug->toStory = '转需求'; -$lang->bug->mailto = '抄送给'; -$lang->bug->openedBy = '由谁创建'; -$lang->bug->openedByAB = '创建'; -$lang->bug->openedDate = '创建日期'; -$lang->bug->openedDateAB = '创建日期'; -$lang->bug->openedBuild = '影响版本'; -$lang->bug->assignedTo = '指派给'; -$lang->bug->assignedDate = '指派日期'; -$lang->bug->resolvedBy = '解决者'; -$lang->bug->resolvedByAB = '解决'; -$lang->bug->resolution = '解决方案'; -$lang->bug->resolutionAB = '方案'; -$lang->bug->resolvedBuild = '解决版本'; -$lang->bug->resolvedDate = '解决日期'; -$lang->bug->resolvedDateAB = '解决日期'; -$lang->bug->closedBy = '由谁关闭'; -$lang->bug->closedDate = '关闭日期'; -$lang->bug->duplicateBug = '重复Bug'; -$lang->bug->lastEditedBy = '最后修改者'; -$lang->bug->lastEditedDate = '最后修改日期'; -$lang->bug->linkBug = '相关Bug'; -$lang->bug->case = '相关用例'; -$lang->bug->files = '附件'; -$lang->bug->keywords = '关键词'; -$lang->bug->lastEditedByAB = '修改者'; -$lang->bug->lastEditedDateAB = '修改日期'; - -/* 方法列表。*/ -$lang->bug->index = '首页'; -$lang->bug->create = '创建Bug'; -$lang->bug->confirmBug = '确认'; -$lang->bug->edit = '编辑Bug'; -$lang->bug->browse = 'Bug列表'; -$lang->bug->view = 'Bug详情'; -$lang->bug->resolve = '解决Bug'; -$lang->bug->close = '关闭Bug'; -$lang->bug->activate = '激活Bug'; -$lang->bug->reportChart = '报表统计'; -$lang->bug->export = '导出数据'; -$lang->bug->delete = '删除Bug'; -$lang->bug->saveTemplate = '保存模板'; -$lang->bug->deleteTemplate = '删除模板'; -$lang->bug->customFields = '自定义字段'; -$lang->bug->restoreDefault = '恢复默认'; -$lang->bug->ajaxGetUserBugs = '接口:我的Bug'; -$lang->bug->ajaxGetModuleOwner = '接口:获得模块的默认指派人'; -$lang->bug->confirmStoryChange = '确认需求变动'; - -/* 查询条件列表。*/ -$lang->bug->selectProduct = '请选择产品'; -$lang->bug->byModule = '按模块'; -$lang->bug->assignToMe = '指派给我'; -$lang->bug->openedByMe = '由我创建'; -$lang->bug->resolvedByMe = '由我解决'; -$lang->bug->closedByMe = '由我关闭'; -$lang->bug->assignToNull = '未指派'; -$lang->bug->unResolved = '未解决'; -$lang->bug->unclosed = '未关闭'; -$lang->bug->longLifeBugs = '久未处理'; -$lang->bug->postponedBugs = '被延期'; -$lang->bug->allBugs = '所有Bug'; -$lang->bug->moduleBugs = '按模块浏览'; -$lang->bug->byQuery = '搜索'; -$lang->bug->needConfirm = '需求变动'; -$lang->bug->allProduct = '所有产品'; - -/* 页面标签。*/ -$lang->bug->lblProductAndModule = '产品模块'; -$lang->bug->lblProjectAndTask = '项目任务'; -$lang->bug->lblStory = '相关需求'; -$lang->bug->lblTypeAndSeverity = '类型/严重程度'; -$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器'; -$lang->bug->lblAssignedTo = '当前指派'; -$lang->bug->lblMailto = '抄送给'; -$lang->bug->lblLastEdited = '最后修改'; -$lang->bug->lblResolved = '由谁解决'; -$lang->bug->lblAllFields = '所有字段'; -$lang->bug->lblCustomFields = '自定义字段'; - -/* legend列表。*/ -$lang->bug->legendBasicInfo = '基本信息'; -$lang->bug->legendMailto = '抄送给'; -$lang->bug->legendAttatch = '附件'; -$lang->bug->legendLinkBugs = '相关Bug'; -$lang->bug->legendPrjStoryTask = '项目/需求/任务'; -$lang->bug->legendCases = '相关用例'; -$lang->bug->legendSteps = '重现步骤'; -$lang->bug->legendAction = '操作'; -$lang->bug->legendHistory = '历史记录'; -$lang->bug->legendComment = '备注'; -$lang->bug->legendLife = 'BUG的一生'; -$lang->bug->legendMisc = '其相关他'; - -/* 功能按钮。*/ -$lang->bug->buttonConfirm = '确认'; -$lang->bug->buttonCopy = '复制'; -$lang->bug->buttonEdit = '编辑'; -$lang->bug->buttonActivate = '激活'; -$lang->bug->buttonResolve = '解决'; -$lang->bug->buttonClose = '关闭'; -$lang->bug->buttonToList = '返回'; -$lang->bug->buttonCreateTestcase = '建用例'; - -/* 交互提示。*/ -$lang->bug->confirmChangeProduct = '修改产品会导致相应的项目、需求和任务发生变化,确定吗?'; -$lang->bug->confirmDelete = '您确认要删除该Bug吗?'; -$lang->bug->setTemplateTitle = '请输入bug模板标题(保存之前请先填写bug重现步骤):'; -$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?'; - -/* 模板。*/ -$lang->bug->tplStep = "

[步骤]

"; -$lang->bug->tplResult = "

[结果]

"; -$lang->bug->tplExpect = "

[期望]

"; - -/* 各个字段取值列表。*/ -$lang->bug->severityList[3] = '3'; -$lang->bug->severityList[1] = '1'; -$lang->bug->severityList[2] = '2'; -$lang->bug->severityList[4] = '4'; - -$lang->bug->priList[0] = ''; -$lang->bug->priList[3] = '3'; -$lang->bug->priList[1] = '1'; -$lang->bug->priList[2] = '2'; -$lang->bug->priList[4] = '4'; - -$lang->bug->osList[''] = ''; -$lang->bug->osList['all'] = '全部'; -$lang->bug->osList['windows'] = 'Windows'; -$lang->bug->osList['winxp'] = 'Windows XP'; -$lang->bug->osList['win7'] = 'Windows 7'; -$lang->bug->osList['vista'] = 'Windows Vista'; -$lang->bug->osList['win2000'] = 'Windows 2000'; -$lang->bug->osList['win2003'] = 'Windows 2003'; -$lang->bug->osList['win2008'] = 'Windows 2008'; -$lang->bug->osList['winnt'] = 'Windows NT'; -$lang->bug->osList['win98'] = 'Windows 98'; -$lang->bug->osList['andriod'] = 'Andriod'; -$lang->bug->osList['ios'] = 'IOS'; -$lang->bug->osList['wp7'] = 'WP7'; -$lang->bug->osList['symbian'] = 'Symbian'; -$lang->bug->osList['linux'] = 'Linux'; -$lang->bug->osList['freebsd'] = 'FreeBSD'; -$lang->bug->osList['mac'] = 'Mac OS'; -$lang->bug->osList['unix'] = 'Unix'; -$lang->bug->osList['others'] = '其他'; - -$lang->bug->browserList[''] = ''; -$lang->bug->browserList['all'] = '全部'; -$lang->bug->browserList['ie'] = 'IE系列'; -$lang->bug->browserList['ie8'] = 'IE8'; -$lang->bug->browserList['ie9'] = 'IE9'; -$lang->bug->browserList['ie6'] = 'IE6'; -$lang->bug->browserList['ie7'] = 'IE7'; -$lang->bug->browserList['chrome'] = 'chrome'; -$lang->bug->browserList['firefox'] = 'firefox系列'; -$lang->bug->browserList['firefox2'] = 'firefox2'; -$lang->bug->browserList['firefox3'] = 'firefox3'; -$lang->bug->browserList['firefox4'] = 'firefox4'; -$lang->bug->browserList['opera'] = 'opera系列'; -$lang->bug->browserList['opera9'] = 'opera9'; -$lang->bug->browserList['oprea10'] = 'opera10'; -$lang->bug->browserList['oprea11'] = 'opera11'; -$lang->bug->browserList['safari'] = 'safari'; -$lang->bug->browserList['maxthon'] = '傲游'; -$lang->bug->browserList['uc'] = 'UC'; -$lang->bug->browserList['other'] = '其他'; - -$lang->bug->typeList[''] = ''; -$lang->bug->typeList['codeerror'] = '代码错误'; -$lang->bug->typeList['interface'] = '界面优化'; -$lang->bug->typeList['designchange'] = '设计变更'; -$lang->bug->typeList['newfeature'] = '新增需求'; -$lang->bug->typeList['designdefect'] = '设计缺陷'; -$lang->bug->typeList['config'] = '配置相关'; -$lang->bug->typeList['install'] = '安装部署'; -$lang->bug->typeList['security'] = '安全相关'; -$lang->bug->typeList['performance'] = '性能问题'; -$lang->bug->typeList['standard'] = '标准规范'; -$lang->bug->typeList['automation'] = '测试脚本'; -$lang->bug->typeList['trackthings'] = '事务跟踪'; -$lang->bug->typeList['others'] = '其他'; - -$lang->bug->statusList[''] = ''; -$lang->bug->statusList['active'] = '激活'; -$lang->bug->statusList['resolved'] = '已解决'; -$lang->bug->statusList['closed'] = '已关闭'; - -$lang->bug->confirmedList[1] = '已确认'; -$lang->bug->confirmedList[0] = '未确认'; - -$lang->bug->resolutionList[''] = ''; -$lang->bug->resolutionList['bydesign'] = '设计如此'; -$lang->bug->resolutionList['duplicate'] = '重复Bug'; -$lang->bug->resolutionList['external'] = '外部原因'; -$lang->bug->resolutionList['fixed'] = '已解决'; -$lang->bug->resolutionList['notrepro'] = '无法重现'; -$lang->bug->resolutionList['postponed'] = '延期处理'; -$lang->bug->resolutionList['willnotfix'] = "不予解决"; -$lang->bug->resolutionList['tostory'] = '转为需求'; - -/* 统计报表。*/ -$lang->bug->report->common = '统计报表'; -$lang->bug->report->select = '请选择报表类型'; -$lang->bug->report->create = '生成报表'; -$lang->bug->report->selectAll = '全选'; -$lang->bug->report->selectReverse = '反选'; - -$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量'; -$lang->bug->report->charts['bugsPerModule'] = '模块Bug数量'; -$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug数'; -$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解决Bug数'; -$lang->bug->report->charts['closedBugsPerDay'] = '每天关闭的Bug数'; -$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug数'; -$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解决的Bug数'; -$lang->bug->report->charts['closedBugsPerUser'] = '每人关闭的Bug数'; -$lang->bug->report->charts['bugsPerSeverity'] = 'Bug严重程度统计'; -$lang->bug->report->charts['bugsPerResolution'] = 'Bug解决方案统计'; -$lang->bug->report->charts['bugsPerStatus'] = 'Bug状态统计'; -$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次数统计'; -$lang->bug->report->charts['bugsPerType'] = 'Bug类型统计'; -$lang->bug->report->charts['bugsPerAssignedTo'] = '指派给统计'; -//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计'; -//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计'; - -$lang->bug->report->options->swf = 'pie2d'; -$lang->bug->report->options->width = 'auto'; -$lang->bug->report->options->height = 300; -$lang->bug->report->options->graph->baseFontSize = 12; -$lang->bug->report->options->graph->showNames = 1; -$lang->bug->report->options->graph->formatNumber = 1; -$lang->bug->report->options->graph->decimalPrecision = 0; -$lang->bug->report->options->graph->animation = 0; -$lang->bug->report->options->graph->rotateNames = 0; -$lang->bug->report->options->graph->yAxisName = 'COUNT'; -$lang->bug->report->options->graph->pieRadius = 100; // 饼图直径。 -$lang->bug->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 - -$lang->bug->report->bugsPerProject->graph->xAxisName = '项目'; -$lang->bug->report->bugsPerModule->graph->xAxisName = '模块'; - -$lang->bug->report->openedBugsPerDay->swf = 'column2d'; -$lang->bug->report->openedBugsPerDay->height = 400; -$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; -$lang->bug->report->resolvedBugsPerDay->height = 400; -$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->closedBugsPerDay->swf = 'column2d'; -$lang->bug->report->closedBugsPerDay->height = 400; -$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用户'; -$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用户'; -$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用户'; - -$lang->bug->report->bugsPerSeverity->graph->xAxisName = '严重程度'; -$lang->bug->report->bugsPerResolution->graph->xAxisName = '解决方案'; -$lang->bug->report->bugsPerStatus->graph->xAxisName = '状态'; -$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次数'; -$lang->bug->report->bugsPerType->graph->xAxisName = '类型'; -$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派给'; -$lang->bug->report->bugLiveDays->graph->xAxisName = '处理时间'; -$lang->bug->report->bugHistories->graph->xAxisName = '处理步骤'; - -/* 操作记录。*/ -$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra。', 'extra' => $lang->bug->resolutionList); -$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求,编号为 $extra。'); -$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务,编号为 $extra。'); + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +/* 字段列表。*/ +$lang->bug->common = '缺陷管理'; +$lang->bug->id = 'Bug编号'; +$lang->bug->product = '所属产品'; +$lang->bug->module = '所属模块'; +$lang->bug->path = '模块路径'; +$lang->bug->project = '所属项目'; +$lang->bug->story = '相关需求'; +$lang->bug->storyVersion = '需求版本'; +$lang->bug->task = '相关任务'; +$lang->bug->title = 'Bug标题'; +$lang->bug->severity = '严重程度'; +$lang->bug->severityAB = '级别'; +$lang->bug->pri = '优先级'; +$lang->bug->type = 'Bug类型'; +$lang->bug->os = '操作系统'; +$lang->bug->hardware = '硬件平台'; +$lang->bug->browser = '浏览器'; +$lang->bug->machine = '机器硬件'; +$lang->bug->found = '如何发现'; +$lang->bug->steps = '重现步骤'; +$lang->bug->status = 'Bug状态'; +$lang->bug->statusAB = '状态'; +$lang->bug->activatedCount = '激活次数'; +$lang->bug->activatedCountAB = '激活次数'; +$lang->bug->confirmed = '是否确认'; +$lang->bug->toTask = '转任务'; +$lang->bug->toStory = '转需求'; +$lang->bug->mailto = '抄送给'; +$lang->bug->openedBy = '由谁创建'; +$lang->bug->openedByAB = '创建'; +$lang->bug->openedDate = '创建日期'; +$lang->bug->openedDateAB = '创建日期'; +$lang->bug->openedBuild = '影响版本'; +$lang->bug->assignedTo = '指派给'; +$lang->bug->assignedDate = '指派日期'; +$lang->bug->resolvedBy = '解决者'; +$lang->bug->resolvedByAB = '解决'; +$lang->bug->resolution = '解决方案'; +$lang->bug->resolutionAB = '方案'; +$lang->bug->resolvedBuild = '解决版本'; +$lang->bug->resolvedDate = '解决日期'; +$lang->bug->resolvedDateAB = '解决日期'; +$lang->bug->closedBy = '由谁关闭'; +$lang->bug->closedDate = '关闭日期'; +$lang->bug->duplicateBug = '重复Bug'; +$lang->bug->lastEditedBy = '最后修改者'; +$lang->bug->lastEditedDate = '最后修改日期'; +$lang->bug->linkBug = '相关Bug'; +$lang->bug->case = '相关用例'; +$lang->bug->files = '附件'; +$lang->bug->keywords = '关键词'; +$lang->bug->lastEditedByAB = '修改者'; +$lang->bug->lastEditedDateAB = '修改日期'; + +/* 方法列表。*/ +$lang->bug->index = '首页'; +$lang->bug->create = '创建Bug'; +$lang->bug->confirmBug = '确认'; +$lang->bug->edit = '编辑Bug'; +$lang->bug->browse = 'Bug列表'; +$lang->bug->view = 'Bug详情'; +$lang->bug->resolve = '解决Bug'; +$lang->bug->close = '关闭Bug'; +$lang->bug->activate = '激活Bug'; +$lang->bug->reportChart = '报表统计'; +$lang->bug->export = '导出数据'; +$lang->bug->delete = '删除Bug'; +$lang->bug->saveTemplate = '保存模板'; +$lang->bug->deleteTemplate = '删除模板'; +$lang->bug->customFields = '自定义字段'; +$lang->bug->restoreDefault = '恢复默认'; +$lang->bug->ajaxGetUserBugs = '接口:我的Bug'; +$lang->bug->ajaxGetModuleOwner = '接口:获得模块的默认指派人'; +$lang->bug->confirmStoryChange = '确认需求变动'; + +/* 查询条件列表。*/ +$lang->bug->selectProduct = '请选择产品'; +$lang->bug->byModule = '按模块'; +$lang->bug->assignToMe = '指派给我'; +$lang->bug->openedByMe = '由我创建'; +$lang->bug->resolvedByMe = '由我解决'; +$lang->bug->closedByMe = '由我关闭'; +$lang->bug->assignToNull = '未指派'; +$lang->bug->unResolved = '未解决'; +$lang->bug->unclosed = '未关闭'; +$lang->bug->longLifeBugs = '久未处理'; +$lang->bug->postponedBugs = '被延期'; +$lang->bug->allBugs = '所有Bug'; +$lang->bug->moduleBugs = '按模块浏览'; +$lang->bug->byQuery = '搜索'; +$lang->bug->needConfirm = '需求变动'; +$lang->bug->allProduct = '所有产品'; + +/* 页面标签。*/ +$lang->bug->lblProductAndModule = '产品模块'; +$lang->bug->lblProjectAndTask = '项目任务'; +$lang->bug->lblStory = '相关需求'; +$lang->bug->lblTypeAndSeverity = '类型/严重程度'; +$lang->bug->lblSystemBrowserAndHardware = '系统/浏览器'; +$lang->bug->lblAssignedTo = '当前指派'; +$lang->bug->lblMailto = '抄送给'; +$lang->bug->lblLastEdited = '最后修改'; +$lang->bug->lblResolved = '由谁解决'; +$lang->bug->lblAllFields = '所有字段'; +$lang->bug->lblCustomFields = '自定义字段'; + +/* legend列表。*/ +$lang->bug->legendBasicInfo = '基本信息'; +$lang->bug->legendMailto = '抄送给'; +$lang->bug->legendAttatch = '附件'; +$lang->bug->legendLinkBugs = '相关Bug'; +$lang->bug->legendPrjStoryTask = '项目/需求/任务'; +$lang->bug->legendCases = '相关用例'; +$lang->bug->legendSteps = '重现步骤'; +$lang->bug->legendAction = '操作'; +$lang->bug->legendHistory = '历史记录'; +$lang->bug->legendComment = '备注'; +$lang->bug->legendLife = 'BUG的一生'; +$lang->bug->legendMisc = '其相关他'; + +/* 功能按钮。*/ +$lang->bug->buttonConfirm = '确认'; +$lang->bug->buttonCopy = '复制'; +$lang->bug->buttonEdit = '编辑'; +$lang->bug->buttonActivate = '激活'; +$lang->bug->buttonResolve = '解决'; +$lang->bug->buttonClose = '关闭'; +$lang->bug->buttonToList = '返回'; +$lang->bug->buttonCreateTestcase = '建用例'; + +/* 交互提示。*/ +$lang->bug->confirmChangeProduct = '修改产品会导致相应的项目、需求和任务发生变化,确定吗?'; +$lang->bug->confirmDelete = '您确认要删除该Bug吗?'; +$lang->bug->setTemplateTitle = '请输入bug模板标题(保存之前请先填写bug重现步骤):'; +$lang->bug->remindTask = '该Bug已经转化为任务,是否更新任务(编号:%s)状态 ?'; + +/* 模板。*/ +$lang->bug->tplStep = "

[步骤]

"; +$lang->bug->tplResult = "

[结果]

"; +$lang->bug->tplExpect = "

[期望]

"; + +/* 各个字段取值列表。*/ +$lang->bug->severityList[3] = '3'; +$lang->bug->severityList[1] = '1'; +$lang->bug->severityList[2] = '2'; +$lang->bug->severityList[4] = '4'; + +$lang->bug->priList[0] = ''; +$lang->bug->priList[3] = '3'; +$lang->bug->priList[1] = '1'; +$lang->bug->priList[2] = '2'; +$lang->bug->priList[4] = '4'; + +$lang->bug->osList[''] = ''; +$lang->bug->osList['all'] = '全部'; +$lang->bug->osList['windows'] = 'Windows'; +$lang->bug->osList['winxp'] = 'Windows XP'; +$lang->bug->osList['win7'] = 'Windows 7'; +$lang->bug->osList['vista'] = 'Windows Vista'; +$lang->bug->osList['win2000'] = 'Windows 2000'; +$lang->bug->osList['win2003'] = 'Windows 2003'; +$lang->bug->osList['win2008'] = 'Windows 2008'; +$lang->bug->osList['winnt'] = 'Windows NT'; +$lang->bug->osList['win98'] = 'Windows 98'; +$lang->bug->osList['andriod'] = 'Andriod'; +$lang->bug->osList['ios'] = 'IOS'; +$lang->bug->osList['wp7'] = 'WP7'; +$lang->bug->osList['symbian'] = 'Symbian'; +$lang->bug->osList['linux'] = 'Linux'; +$lang->bug->osList['freebsd'] = 'FreeBSD'; +$lang->bug->osList['mac'] = 'Mac OS'; +$lang->bug->osList['unix'] = 'Unix'; +$lang->bug->osList['others'] = '其他'; + +$lang->bug->browserList[''] = ''; +$lang->bug->browserList['all'] = '全部'; +$lang->bug->browserList['ie'] = 'IE系列'; +$lang->bug->browserList['ie8'] = 'IE8'; +$lang->bug->browserList['ie9'] = 'IE9'; +$lang->bug->browserList['ie6'] = 'IE6'; +$lang->bug->browserList['ie7'] = 'IE7'; +$lang->bug->browserList['chrome'] = 'chrome'; +$lang->bug->browserList['firefox'] = 'firefox系列'; +$lang->bug->browserList['firefox2'] = 'firefox2'; +$lang->bug->browserList['firefox3'] = 'firefox3'; +$lang->bug->browserList['firefox4'] = 'firefox4'; +$lang->bug->browserList['opera'] = 'opera系列'; +$lang->bug->browserList['opera9'] = 'opera9'; +$lang->bug->browserList['oprea10'] = 'opera10'; +$lang->bug->browserList['oprea11'] = 'opera11'; +$lang->bug->browserList['safari'] = 'safari'; +$lang->bug->browserList['maxthon'] = '傲游'; +$lang->bug->browserList['uc'] = 'UC'; +$lang->bug->browserList['other'] = '其他'; + +$lang->bug->typeList[''] = ''; +$lang->bug->typeList['codeerror'] = '代码错误'; +$lang->bug->typeList['interface'] = '界面优化'; +$lang->bug->typeList['designchange'] = '设计变更'; +$lang->bug->typeList['newfeature'] = '新增需求'; +$lang->bug->typeList['designdefect'] = '设计缺陷'; +$lang->bug->typeList['config'] = '配置相关'; +$lang->bug->typeList['install'] = '安装部署'; +$lang->bug->typeList['security'] = '安全相关'; +$lang->bug->typeList['performance'] = '性能问题'; +$lang->bug->typeList['standard'] = '标准规范'; +$lang->bug->typeList['automation'] = '测试脚本'; +$lang->bug->typeList['trackthings'] = '事务跟踪'; +$lang->bug->typeList['others'] = '其他'; + +$lang->bug->statusList[''] = ''; +$lang->bug->statusList['active'] = '激活'; +$lang->bug->statusList['resolved'] = '已解决'; +$lang->bug->statusList['closed'] = '已关闭'; + +$lang->bug->confirmedList[1] = '已确认'; +$lang->bug->confirmedList[0] = '未确认'; + +$lang->bug->resolutionList[''] = ''; +$lang->bug->resolutionList['bydesign'] = '设计如此'; +$lang->bug->resolutionList['duplicate'] = '重复Bug'; +$lang->bug->resolutionList['external'] = '外部原因'; +$lang->bug->resolutionList['fixed'] = '已解决'; +$lang->bug->resolutionList['notrepro'] = '无法重现'; +$lang->bug->resolutionList['postponed'] = '延期处理'; +$lang->bug->resolutionList['willnotfix'] = "不予解决"; +$lang->bug->resolutionList['tostory'] = '转为需求'; + +/* 统计报表。*/ +$lang->bug->report->common = '统计报表'; +$lang->bug->report->select = '请选择报表类型'; +$lang->bug->report->create = '生成报表'; +$lang->bug->report->selectAll = '全选'; +$lang->bug->report->selectReverse = '反选'; + +$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量'; +$lang->bug->report->charts['bugsPerModule'] = '模块Bug数量'; +$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug数'; +$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解决Bug数'; +$lang->bug->report->charts['closedBugsPerDay'] = '每天关闭的Bug数'; +$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug数'; +$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解决的Bug数'; +$lang->bug->report->charts['closedBugsPerUser'] = '每人关闭的Bug数'; +$lang->bug->report->charts['bugsPerSeverity'] = 'Bug严重程度统计'; +$lang->bug->report->charts['bugsPerResolution'] = 'Bug解决方案统计'; +$lang->bug->report->charts['bugsPerStatus'] = 'Bug状态统计'; +$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次数统计'; +$lang->bug->report->charts['bugsPerType'] = 'Bug类型统计'; +$lang->bug->report->charts['bugsPerAssignedTo'] = '指派给统计'; +//$lang->bug->report->charts['bugLiveDays'] = 'Bug处理时间统计'; +//$lang->bug->report->charts['bugHistories'] = 'Bug处理步骤统计'; + +$lang->bug->report->options->swf = 'pie2d'; +$lang->bug->report->options->width = 'auto'; +$lang->bug->report->options->height = 300; +$lang->bug->report->options->graph->baseFontSize = 12; +$lang->bug->report->options->graph->showNames = 1; +$lang->bug->report->options->graph->formatNumber = 1; +$lang->bug->report->options->graph->decimalPrecision = 0; +$lang->bug->report->options->graph->animation = 0; +$lang->bug->report->options->graph->rotateNames = 0; +$lang->bug->report->options->graph->yAxisName = 'COUNT'; +$lang->bug->report->options->graph->pieRadius = 100; // 饼图直径。 +$lang->bug->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 + +$lang->bug->report->bugsPerProject->graph->xAxisName = '项目'; +$lang->bug->report->bugsPerModule->graph->xAxisName = '模块'; + +$lang->bug->report->openedBugsPerDay->swf = 'column2d'; +$lang->bug->report->openedBugsPerDay->height = 400; +$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; +$lang->bug->report->resolvedBugsPerDay->height = 400; +$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->closedBugsPerDay->swf = 'column2d'; +$lang->bug->report->closedBugsPerDay->height = 400; +$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用户'; +$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用户'; +$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用户'; + +$lang->bug->report->bugsPerSeverity->graph->xAxisName = '严重程度'; +$lang->bug->report->bugsPerResolution->graph->xAxisName = '解决方案'; +$lang->bug->report->bugsPerStatus->graph->xAxisName = '状态'; +$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次数'; +$lang->bug->report->bugsPerType->graph->xAxisName = '类型'; +$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派给'; +$lang->bug->report->bugLiveDays->graph->xAxisName = '处理时间'; +$lang->bug->report->bugHistories->graph->xAxisName = '处理步骤'; + +/* 操作记录。*/ +$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解决,方案为 $extra。', 'extra' => $lang->bug->resolutionList); +$lang->bug->action->tostory = array('main' => '$date, 由 $actor 转为需求,编号为 $extra。'); +$lang->bug->action->totask = array('main' => '$date, 由 $actor 导入为任务,编号为 $extra。'); diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index 0c02335474..c9e9f4e91a 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -1,312 +1,312 @@ - - * @package bug - * @version $Id: zh-tw.php 2484 2011-12-27 08:45:57Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -/* 欄位列表。*/ -$lang->bug->common = '缺陷管理'; -$lang->bug->id = 'Bug編號'; -$lang->bug->product = '所屬產品'; -$lang->bug->module = '所屬模組'; -$lang->bug->path = '模組路徑'; -$lang->bug->project = '所屬項目'; -$lang->bug->story = '相關需求'; -$lang->bug->storyVersion = '需求版本'; -$lang->bug->task = '相關任務'; -$lang->bug->title = 'Bug標題'; -$lang->bug->severity = '嚴重程度'; -$lang->bug->severityAB = '級別'; -$lang->bug->pri = '優先順序'; -$lang->bug->type = 'Bug類型'; -$lang->bug->os = '操作系統'; -$lang->bug->hardware = '硬件平台'; -$lang->bug->browser = '瀏覽器'; -$lang->bug->machine = '機器硬件'; -$lang->bug->found = '如何發現'; -$lang->bug->steps = '重現步驟'; -$lang->bug->status = 'Bug狀態'; -$lang->bug->statusAB = '狀態'; -$lang->bug->activatedCount = '激活次數'; -$lang->bug->activatedCountAB = '激活次數'; -$lang->bug->confirmed = '是否確認'; -$lang->bug->toTask = '轉任務'; -$lang->bug->toStory = '轉需求'; -$lang->bug->mailto = '抄送給'; -$lang->bug->openedBy = '由誰創建'; -$lang->bug->openedByAB = '創建'; -$lang->bug->openedDate = '創建日期'; -$lang->bug->openedDateAB = '創建日期'; -$lang->bug->openedBuild = '影響版本'; -$lang->bug->assignedTo = '指派給'; -$lang->bug->assignedDate = '指派日期'; -$lang->bug->resolvedBy = '解決者'; -$lang->bug->resolvedByAB = '解決'; -$lang->bug->resolution = '解決方案'; -$lang->bug->resolutionAB = '方案'; -$lang->bug->resolvedBuild = '解決版本'; -$lang->bug->resolvedDate = '解決日期'; -$lang->bug->resolvedDateAB = '解決日期'; -$lang->bug->closedBy = '由誰關閉'; -$lang->bug->closedDate = '關閉日期'; -$lang->bug->duplicateBug = '重複Bug'; -$lang->bug->lastEditedBy = '最後修改者'; -$lang->bug->lastEditedDate = '最後修改日期'; -$lang->bug->linkBug = '相關Bug'; -$lang->bug->case = '相關用例'; -$lang->bug->files = '附件'; -$lang->bug->keywords = '關鍵詞'; -$lang->bug->lastEditedByAB = '修改者'; -$lang->bug->lastEditedDateAB = '修改日期'; - -/* 方法列表。*/ -$lang->bug->index = '首頁'; -$lang->bug->create = '創建Bug'; -$lang->bug->confirmBug = '確認'; -$lang->bug->edit = '編輯Bug'; -$lang->bug->browse = 'Bug列表'; -$lang->bug->view = 'Bug詳情'; -$lang->bug->resolve = '解決Bug'; -$lang->bug->close = '關閉Bug'; -$lang->bug->activate = '激活Bug'; -$lang->bug->reportChart = '報表統計'; -$lang->bug->export = '導出數據'; -$lang->bug->delete = '刪除Bug'; -$lang->bug->saveTemplate = '保存模板'; -$lang->bug->deleteTemplate = '刪除模板'; -$lang->bug->customFields = '自定義欄位'; -$lang->bug->restoreDefault = '恢復預設'; -$lang->bug->ajaxGetUserBugs = '介面:我的Bug'; -$lang->bug->ajaxGetModuleOwner = '介面:獲得模組的預設指派人'; -$lang->bug->confirmStoryChange = '確認需求變動'; - -/* 查詢條件列表。*/ -$lang->bug->selectProduct = '請選擇產品'; -$lang->bug->byModule = '按模組'; -$lang->bug->assignToMe = '指派給我'; -$lang->bug->openedByMe = '由我創建'; -$lang->bug->resolvedByMe = '由我解決'; -$lang->bug->closedByMe = '由我關閉'; -$lang->bug->assignToNull = '未指派'; -$lang->bug->unResolved = '未解決'; -$lang->bug->unclosed = '未關閉'; -$lang->bug->longLifeBugs = '久未處理'; -$lang->bug->postponedBugs = '被延期'; -$lang->bug->allBugs = '所有Bug'; -$lang->bug->moduleBugs = '按模組瀏覽'; -$lang->bug->byQuery = '搜索'; -$lang->bug->needConfirm = '需求變動'; -$lang->bug->allProduct = '所有產品'; - -/* 頁面標籤。*/ -$lang->bug->lblProductAndModule = '產品模組'; -$lang->bug->lblProjectAndTask = '項目任務'; -$lang->bug->lblStory = '相關需求'; -$lang->bug->lblTypeAndSeverity = '類型/嚴重程度'; -$lang->bug->lblSystemBrowserAndHardware = '系統/瀏覽器'; -$lang->bug->lblAssignedTo = '當前指派'; -$lang->bug->lblMailto = '抄送給'; -$lang->bug->lblLastEdited = '最後修改'; -$lang->bug->lblResolved = '由誰解決'; -$lang->bug->lblAllFields = '所有欄位'; -$lang->bug->lblCustomFields = '自定義欄位'; - -/* legend列表。*/ -$lang->bug->legendBasicInfo = '基本信息'; -$lang->bug->legendMailto = '抄送給'; -$lang->bug->legendAttatch = '附件'; -$lang->bug->legendLinkBugs = '相關Bug'; -$lang->bug->legendPrjStoryTask = '項目/需求/任務'; -$lang->bug->legendCases = '相關用例'; -$lang->bug->legendSteps = '重現步驟'; -$lang->bug->legendAction = '操作'; -$lang->bug->legendHistory = '歷史記錄'; -$lang->bug->legendComment = '備註'; -$lang->bug->legendLife = 'BUG的一生'; -$lang->bug->legendMisc = '其相關他'; - -/* 功能按鈕。*/ -$lang->bug->buttonConfirm = '確認'; -$lang->bug->buttonCopy = '複製'; -$lang->bug->buttonEdit = '編輯'; -$lang->bug->buttonActivate = '激活'; -$lang->bug->buttonResolve = '解決'; -$lang->bug->buttonClose = '關閉'; -$lang->bug->buttonToList = '返回'; -$lang->bug->buttonCreateTestcase = '建用例'; - -/* 交互提示。*/ -$lang->bug->confirmChangeProduct = '修改產品會導致相應的項目、需求和任務發生變化,確定嗎?'; -$lang->bug->confirmDelete = '您確認要刪除該Bug嗎?'; -$lang->bug->setTemplateTitle = '請輸入bug模板標題(保存之前請先填寫bug重現步驟):'; -$lang->bug->remindTask = '該Bug已經轉化為任務,是否更新任務(編號:%s)狀態 ?'; - -/* 模板。*/ -$lang->bug->tplStep = "

[步驟]

"; -$lang->bug->tplResult = "

[結果]

"; -$lang->bug->tplExpect = "

[期望]

"; - -/* 各個欄位取值列表。*/ -$lang->bug->severityList[3] = '3'; -$lang->bug->severityList[1] = '1'; -$lang->bug->severityList[2] = '2'; -$lang->bug->severityList[4] = '4'; - -$lang->bug->priList[0] = ''; -$lang->bug->priList[3] = '3'; -$lang->bug->priList[1] = '1'; -$lang->bug->priList[2] = '2'; -$lang->bug->priList[4] = '4'; - -$lang->bug->osList[''] = ''; -$lang->bug->osList['all'] = '全部'; -$lang->bug->osList['windows'] = 'Windows'; -$lang->bug->osList['winxp'] = 'Windows XP'; -$lang->bug->osList['win7'] = 'Windows 7'; -$lang->bug->osList['vista'] = 'Windows Vista'; -$lang->bug->osList['win2000'] = 'Windows 2000'; -$lang->bug->osList['win2003'] = 'Windows 2003'; -$lang->bug->osList['win2008'] = 'Windows 2008'; -$lang->bug->osList['winnt'] = 'Windows NT'; -$lang->bug->osList['win98'] = 'Windows 98'; -$lang->bug->osList['andriod'] = 'Andriod'; -$lang->bug->osList['ios'] = 'IOS'; -$lang->bug->osList['wp7'] = 'WP7'; -$lang->bug->osList['symbian'] = 'Symbian'; -$lang->bug->osList['linux'] = 'Linux'; -$lang->bug->osList['freebsd'] = 'FreeBSD'; -$lang->bug->osList['mac'] = 'Mac OS'; -$lang->bug->osList['unix'] = 'Unix'; -$lang->bug->osList['others'] = '其他'; - -$lang->bug->browserList[''] = ''; -$lang->bug->browserList['all'] = '全部'; -$lang->bug->browserList['ie'] = 'IE系列'; -$lang->bug->browserList['ie8'] = 'IE8'; -$lang->bug->browserList['ie9'] = 'IE9'; -$lang->bug->browserList['ie6'] = 'IE6'; -$lang->bug->browserList['ie7'] = 'IE7'; -$lang->bug->browserList['chrome'] = 'chrome'; -$lang->bug->browserList['firefox'] = 'firefox系列'; -$lang->bug->browserList['firefox2'] = 'firefox2'; -$lang->bug->browserList['firefox3'] = 'firefox3'; -$lang->bug->browserList['firefox4'] = 'firefox4'; -$lang->bug->browserList['opera'] = 'opera系列'; -$lang->bug->browserList['opera9'] = 'opera9'; -$lang->bug->browserList['oprea10'] = 'opera10'; -$lang->bug->browserList['oprea11'] = 'opera11'; -$lang->bug->browserList['safari'] = 'safari'; -$lang->bug->browserList['maxthon'] = '傲游'; -$lang->bug->browserList['uc'] = 'UC'; -$lang->bug->browserList['other'] = '其他'; - -$lang->bug->typeList[''] = ''; -$lang->bug->typeList['codeerror'] = '代碼錯誤'; -$lang->bug->typeList['interface'] = '界面優化'; -$lang->bug->typeList['designchange'] = '設計變更'; -$lang->bug->typeList['newfeature'] = '新增需求'; -$lang->bug->typeList['designdefect'] = '設計缺陷'; -$lang->bug->typeList['config'] = '配置相關'; -$lang->bug->typeList['install'] = '安裝部署'; -$lang->bug->typeList['security'] = '安全相關'; -$lang->bug->typeList['performance'] = '性能問題'; -$lang->bug->typeList['standard'] = '標準規範'; -$lang->bug->typeList['automation'] = '測試腳本'; -$lang->bug->typeList['trackthings'] = '事務跟蹤'; -$lang->bug->typeList['others'] = '其他'; - -$lang->bug->statusList[''] = ''; -$lang->bug->statusList['active'] = '激活'; -$lang->bug->statusList['resolved'] = '已解決'; -$lang->bug->statusList['closed'] = '已關閉'; - -$lang->bug->confirmedList[1] = '已確認'; -$lang->bug->confirmedList[0] = '未確認'; - -$lang->bug->resolutionList[''] = ''; -$lang->bug->resolutionList['bydesign'] = '設計如此'; -$lang->bug->resolutionList['duplicate'] = '重複Bug'; -$lang->bug->resolutionList['external'] = '外部原因'; -$lang->bug->resolutionList['fixed'] = '已解決'; -$lang->bug->resolutionList['notrepro'] = '無法重現'; -$lang->bug->resolutionList['postponed'] = '延期處理'; -$lang->bug->resolutionList['willnotfix'] = "不予解決"; -$lang->bug->resolutionList['tostory'] = '轉為需求'; - -/* 統計報表。*/ -$lang->bug->report->common = '統計報表'; -$lang->bug->report->select = '請選擇報表類型'; -$lang->bug->report->create = '生成報表'; -$lang->bug->report->selectAll = '全選'; -$lang->bug->report->selectReverse = '反選'; - -$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量'; -$lang->bug->report->charts['bugsPerModule'] = '模組Bug數量'; -$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug數'; -$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解決Bug數'; -$lang->bug->report->charts['closedBugsPerDay'] = '每天關閉的Bug數'; -$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug數'; -$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解決的Bug數'; -$lang->bug->report->charts['closedBugsPerUser'] = '每人關閉的Bug數'; -$lang->bug->report->charts['bugsPerSeverity'] = 'Bug嚴重程度統計'; -$lang->bug->report->charts['bugsPerResolution'] = 'Bug解決方案統計'; -$lang->bug->report->charts['bugsPerStatus'] = 'Bug狀態統計'; -$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次數統計'; -$lang->bug->report->charts['bugsPerType'] = 'Bug類型統計'; -$lang->bug->report->charts['bugsPerAssignedTo'] = '指派給統計'; -//$lang->bug->report->charts['bugLiveDays'] = 'Bug處理時間統計'; -//$lang->bug->report->charts['bugHistories'] = 'Bug處理步驟統計'; - -$lang->bug->report->options->swf = 'pie2d'; -$lang->bug->report->options->width = 'auto'; -$lang->bug->report->options->height = 300; -$lang->bug->report->options->graph->baseFontSize = 12; -$lang->bug->report->options->graph->showNames = 1; -$lang->bug->report->options->graph->formatNumber = 1; -$lang->bug->report->options->graph->decimalPrecision = 0; -$lang->bug->report->options->graph->animation = 0; -$lang->bug->report->options->graph->rotateNames = 0; -$lang->bug->report->options->graph->yAxisName = 'COUNT'; -$lang->bug->report->options->graph->pieRadius = 100; // 餅圖直徑。 -$lang->bug->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 - -$lang->bug->report->bugsPerProject->graph->xAxisName = '項目'; -$lang->bug->report->bugsPerModule->graph->xAxisName = '模組'; - -$lang->bug->report->openedBugsPerDay->swf = 'column2d'; -$lang->bug->report->openedBugsPerDay->height = 400; -$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; -$lang->bug->report->resolvedBugsPerDay->height = 400; -$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->closedBugsPerDay->swf = 'column2d'; -$lang->bug->report->closedBugsPerDay->height = 400; -$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期'; -$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; - -$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用戶'; -$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用戶'; -$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用戶'; - -$lang->bug->report->bugsPerSeverity->graph->xAxisName = '嚴重程度'; -$lang->bug->report->bugsPerResolution->graph->xAxisName = '解決方案'; -$lang->bug->report->bugsPerStatus->graph->xAxisName = '狀態'; -$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次數'; -$lang->bug->report->bugsPerType->graph->xAxisName = '類型'; -$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派給'; -$lang->bug->report->bugLiveDays->graph->xAxisName = '處理時間'; -$lang->bug->report->bugHistories->graph->xAxisName = '處理步驟'; - -/* 操作記錄。*/ -$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra。', 'extra' => $lang->bug->resolutionList); -$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求,編號為 $extra。'); -$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務,編號為 $extra。'); + + * @package bug + * @version $Id: zh-tw.php 2484 2011-12-27 08:45:57Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +/* 欄位列表。*/ +$lang->bug->common = '缺陷管理'; +$lang->bug->id = 'Bug編號'; +$lang->bug->product = '所屬產品'; +$lang->bug->module = '所屬模組'; +$lang->bug->path = '模組路徑'; +$lang->bug->project = '所屬項目'; +$lang->bug->story = '相關需求'; +$lang->bug->storyVersion = '需求版本'; +$lang->bug->task = '相關任務'; +$lang->bug->title = 'Bug標題'; +$lang->bug->severity = '嚴重程度'; +$lang->bug->severityAB = '級別'; +$lang->bug->pri = '優先順序'; +$lang->bug->type = 'Bug類型'; +$lang->bug->os = '操作系統'; +$lang->bug->hardware = '硬件平台'; +$lang->bug->browser = '瀏覽器'; +$lang->bug->machine = '機器硬件'; +$lang->bug->found = '如何發現'; +$lang->bug->steps = '重現步驟'; +$lang->bug->status = 'Bug狀態'; +$lang->bug->statusAB = '狀態'; +$lang->bug->activatedCount = '激活次數'; +$lang->bug->activatedCountAB = '激活次數'; +$lang->bug->confirmed = '是否確認'; +$lang->bug->toTask = '轉任務'; +$lang->bug->toStory = '轉需求'; +$lang->bug->mailto = '抄送給'; +$lang->bug->openedBy = '由誰創建'; +$lang->bug->openedByAB = '創建'; +$lang->bug->openedDate = '創建日期'; +$lang->bug->openedDateAB = '創建日期'; +$lang->bug->openedBuild = '影響版本'; +$lang->bug->assignedTo = '指派給'; +$lang->bug->assignedDate = '指派日期'; +$lang->bug->resolvedBy = '解決者'; +$lang->bug->resolvedByAB = '解決'; +$lang->bug->resolution = '解決方案'; +$lang->bug->resolutionAB = '方案'; +$lang->bug->resolvedBuild = '解決版本'; +$lang->bug->resolvedDate = '解決日期'; +$lang->bug->resolvedDateAB = '解決日期'; +$lang->bug->closedBy = '由誰關閉'; +$lang->bug->closedDate = '關閉日期'; +$lang->bug->duplicateBug = '重複Bug'; +$lang->bug->lastEditedBy = '最後修改者'; +$lang->bug->lastEditedDate = '最後修改日期'; +$lang->bug->linkBug = '相關Bug'; +$lang->bug->case = '相關用例'; +$lang->bug->files = '附件'; +$lang->bug->keywords = '關鍵詞'; +$lang->bug->lastEditedByAB = '修改者'; +$lang->bug->lastEditedDateAB = '修改日期'; + +/* 方法列表。*/ +$lang->bug->index = '首頁'; +$lang->bug->create = '創建Bug'; +$lang->bug->confirmBug = '確認'; +$lang->bug->edit = '編輯Bug'; +$lang->bug->browse = 'Bug列表'; +$lang->bug->view = 'Bug詳情'; +$lang->bug->resolve = '解決Bug'; +$lang->bug->close = '關閉Bug'; +$lang->bug->activate = '激活Bug'; +$lang->bug->reportChart = '報表統計'; +$lang->bug->export = '導出數據'; +$lang->bug->delete = '刪除Bug'; +$lang->bug->saveTemplate = '保存模板'; +$lang->bug->deleteTemplate = '刪除模板'; +$lang->bug->customFields = '自定義欄位'; +$lang->bug->restoreDefault = '恢復預設'; +$lang->bug->ajaxGetUserBugs = '介面:我的Bug'; +$lang->bug->ajaxGetModuleOwner = '介面:獲得模組的預設指派人'; +$lang->bug->confirmStoryChange = '確認需求變動'; + +/* 查詢條件列表。*/ +$lang->bug->selectProduct = '請選擇產品'; +$lang->bug->byModule = '按模組'; +$lang->bug->assignToMe = '指派給我'; +$lang->bug->openedByMe = '由我創建'; +$lang->bug->resolvedByMe = '由我解決'; +$lang->bug->closedByMe = '由我關閉'; +$lang->bug->assignToNull = '未指派'; +$lang->bug->unResolved = '未解決'; +$lang->bug->unclosed = '未關閉'; +$lang->bug->longLifeBugs = '久未處理'; +$lang->bug->postponedBugs = '被延期'; +$lang->bug->allBugs = '所有Bug'; +$lang->bug->moduleBugs = '按模組瀏覽'; +$lang->bug->byQuery = '搜索'; +$lang->bug->needConfirm = '需求變動'; +$lang->bug->allProduct = '所有產品'; + +/* 頁面標籤。*/ +$lang->bug->lblProductAndModule = '產品模組'; +$lang->bug->lblProjectAndTask = '項目任務'; +$lang->bug->lblStory = '相關需求'; +$lang->bug->lblTypeAndSeverity = '類型/嚴重程度'; +$lang->bug->lblSystemBrowserAndHardware = '系統/瀏覽器'; +$lang->bug->lblAssignedTo = '當前指派'; +$lang->bug->lblMailto = '抄送給'; +$lang->bug->lblLastEdited = '最後修改'; +$lang->bug->lblResolved = '由誰解決'; +$lang->bug->lblAllFields = '所有欄位'; +$lang->bug->lblCustomFields = '自定義欄位'; + +/* legend列表。*/ +$lang->bug->legendBasicInfo = '基本信息'; +$lang->bug->legendMailto = '抄送給'; +$lang->bug->legendAttatch = '附件'; +$lang->bug->legendLinkBugs = '相關Bug'; +$lang->bug->legendPrjStoryTask = '項目/需求/任務'; +$lang->bug->legendCases = '相關用例'; +$lang->bug->legendSteps = '重現步驟'; +$lang->bug->legendAction = '操作'; +$lang->bug->legendHistory = '歷史記錄'; +$lang->bug->legendComment = '備註'; +$lang->bug->legendLife = 'BUG的一生'; +$lang->bug->legendMisc = '其相關他'; + +/* 功能按鈕。*/ +$lang->bug->buttonConfirm = '確認'; +$lang->bug->buttonCopy = '複製'; +$lang->bug->buttonEdit = '編輯'; +$lang->bug->buttonActivate = '激活'; +$lang->bug->buttonResolve = '解決'; +$lang->bug->buttonClose = '關閉'; +$lang->bug->buttonToList = '返回'; +$lang->bug->buttonCreateTestcase = '建用例'; + +/* 交互提示。*/ +$lang->bug->confirmChangeProduct = '修改產品會導致相應的項目、需求和任務發生變化,確定嗎?'; +$lang->bug->confirmDelete = '您確認要刪除該Bug嗎?'; +$lang->bug->setTemplateTitle = '請輸入bug模板標題(保存之前請先填寫bug重現步驟):'; +$lang->bug->remindTask = '該Bug已經轉化為任務,是否更新任務(編號:%s)狀態 ?'; + +/* 模板。*/ +$lang->bug->tplStep = "

[步驟]

"; +$lang->bug->tplResult = "

[結果]

"; +$lang->bug->tplExpect = "

[期望]

"; + +/* 各個欄位取值列表。*/ +$lang->bug->severityList[3] = '3'; +$lang->bug->severityList[1] = '1'; +$lang->bug->severityList[2] = '2'; +$lang->bug->severityList[4] = '4'; + +$lang->bug->priList[0] = ''; +$lang->bug->priList[3] = '3'; +$lang->bug->priList[1] = '1'; +$lang->bug->priList[2] = '2'; +$lang->bug->priList[4] = '4'; + +$lang->bug->osList[''] = ''; +$lang->bug->osList['all'] = '全部'; +$lang->bug->osList['windows'] = 'Windows'; +$lang->bug->osList['winxp'] = 'Windows XP'; +$lang->bug->osList['win7'] = 'Windows 7'; +$lang->bug->osList['vista'] = 'Windows Vista'; +$lang->bug->osList['win2000'] = 'Windows 2000'; +$lang->bug->osList['win2003'] = 'Windows 2003'; +$lang->bug->osList['win2008'] = 'Windows 2008'; +$lang->bug->osList['winnt'] = 'Windows NT'; +$lang->bug->osList['win98'] = 'Windows 98'; +$lang->bug->osList['andriod'] = 'Andriod'; +$lang->bug->osList['ios'] = 'IOS'; +$lang->bug->osList['wp7'] = 'WP7'; +$lang->bug->osList['symbian'] = 'Symbian'; +$lang->bug->osList['linux'] = 'Linux'; +$lang->bug->osList['freebsd'] = 'FreeBSD'; +$lang->bug->osList['mac'] = 'Mac OS'; +$lang->bug->osList['unix'] = 'Unix'; +$lang->bug->osList['others'] = '其他'; + +$lang->bug->browserList[''] = ''; +$lang->bug->browserList['all'] = '全部'; +$lang->bug->browserList['ie'] = 'IE系列'; +$lang->bug->browserList['ie8'] = 'IE8'; +$lang->bug->browserList['ie9'] = 'IE9'; +$lang->bug->browserList['ie6'] = 'IE6'; +$lang->bug->browserList['ie7'] = 'IE7'; +$lang->bug->browserList['chrome'] = 'chrome'; +$lang->bug->browserList['firefox'] = 'firefox系列'; +$lang->bug->browserList['firefox2'] = 'firefox2'; +$lang->bug->browserList['firefox3'] = 'firefox3'; +$lang->bug->browserList['firefox4'] = 'firefox4'; +$lang->bug->browserList['opera'] = 'opera系列'; +$lang->bug->browserList['opera9'] = 'opera9'; +$lang->bug->browserList['oprea10'] = 'opera10'; +$lang->bug->browserList['oprea11'] = 'opera11'; +$lang->bug->browserList['safari'] = 'safari'; +$lang->bug->browserList['maxthon'] = '傲游'; +$lang->bug->browserList['uc'] = 'UC'; +$lang->bug->browserList['other'] = '其他'; + +$lang->bug->typeList[''] = ''; +$lang->bug->typeList['codeerror'] = '代碼錯誤'; +$lang->bug->typeList['interface'] = '界面優化'; +$lang->bug->typeList['designchange'] = '設計變更'; +$lang->bug->typeList['newfeature'] = '新增需求'; +$lang->bug->typeList['designdefect'] = '設計缺陷'; +$lang->bug->typeList['config'] = '配置相關'; +$lang->bug->typeList['install'] = '安裝部署'; +$lang->bug->typeList['security'] = '安全相關'; +$lang->bug->typeList['performance'] = '性能問題'; +$lang->bug->typeList['standard'] = '標準規範'; +$lang->bug->typeList['automation'] = '測試腳本'; +$lang->bug->typeList['trackthings'] = '事務跟蹤'; +$lang->bug->typeList['others'] = '其他'; + +$lang->bug->statusList[''] = ''; +$lang->bug->statusList['active'] = '激活'; +$lang->bug->statusList['resolved'] = '已解決'; +$lang->bug->statusList['closed'] = '已關閉'; + +$lang->bug->confirmedList[1] = '已確認'; +$lang->bug->confirmedList[0] = '未確認'; + +$lang->bug->resolutionList[''] = ''; +$lang->bug->resolutionList['bydesign'] = '設計如此'; +$lang->bug->resolutionList['duplicate'] = '重複Bug'; +$lang->bug->resolutionList['external'] = '外部原因'; +$lang->bug->resolutionList['fixed'] = '已解決'; +$lang->bug->resolutionList['notrepro'] = '無法重現'; +$lang->bug->resolutionList['postponed'] = '延期處理'; +$lang->bug->resolutionList['willnotfix'] = "不予解決"; +$lang->bug->resolutionList['tostory'] = '轉為需求'; + +/* 統計報表。*/ +$lang->bug->report->common = '統計報表'; +$lang->bug->report->select = '請選擇報表類型'; +$lang->bug->report->create = '生成報表'; +$lang->bug->report->selectAll = '全選'; +$lang->bug->report->selectReverse = '反選'; + +$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量'; +$lang->bug->report->charts['bugsPerModule'] = '模組Bug數量'; +$lang->bug->report->charts['openedBugsPerDay'] = '每天新增Bug數'; +$lang->bug->report->charts['resolvedBugsPerDay'] = '每天解決Bug數'; +$lang->bug->report->charts['closedBugsPerDay'] = '每天關閉的Bug數'; +$lang->bug->report->charts['openedBugsPerUser'] = '每人提交的Bug數'; +$lang->bug->report->charts['resolvedBugsPerUser'] = '每人解決的Bug數'; +$lang->bug->report->charts['closedBugsPerUser'] = '每人關閉的Bug數'; +$lang->bug->report->charts['bugsPerSeverity'] = 'Bug嚴重程度統計'; +$lang->bug->report->charts['bugsPerResolution'] = 'Bug解決方案統計'; +$lang->bug->report->charts['bugsPerStatus'] = 'Bug狀態統計'; +$lang->bug->report->charts['bugsPerActivatedCount'] = 'Bug激活次數統計'; +$lang->bug->report->charts['bugsPerType'] = 'Bug類型統計'; +$lang->bug->report->charts['bugsPerAssignedTo'] = '指派給統計'; +//$lang->bug->report->charts['bugLiveDays'] = 'Bug處理時間統計'; +//$lang->bug->report->charts['bugHistories'] = 'Bug處理步驟統計'; + +$lang->bug->report->options->swf = 'pie2d'; +$lang->bug->report->options->width = 'auto'; +$lang->bug->report->options->height = 300; +$lang->bug->report->options->graph->baseFontSize = 12; +$lang->bug->report->options->graph->showNames = 1; +$lang->bug->report->options->graph->formatNumber = 1; +$lang->bug->report->options->graph->decimalPrecision = 0; +$lang->bug->report->options->graph->animation = 0; +$lang->bug->report->options->graph->rotateNames = 0; +$lang->bug->report->options->graph->yAxisName = 'COUNT'; +$lang->bug->report->options->graph->pieRadius = 100; // 餅圖直徑。 +$lang->bug->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 + +$lang->bug->report->bugsPerProject->graph->xAxisName = '項目'; +$lang->bug->report->bugsPerModule->graph->xAxisName = '模組'; + +$lang->bug->report->openedBugsPerDay->swf = 'column2d'; +$lang->bug->report->openedBugsPerDay->height = 400; +$lang->bug->report->openedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->openedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->resolvedBugsPerDay->swf = 'column2d'; +$lang->bug->report->resolvedBugsPerDay->height = 400; +$lang->bug->report->resolvedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->resolvedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->closedBugsPerDay->swf = 'column2d'; +$lang->bug->report->closedBugsPerDay->height = 400; +$lang->bug->report->closedBugsPerDay->graph->xAxisName = '日期'; +$lang->bug->report->closedBugsPerDay->graph->rotateNames = 1; + +$lang->bug->report->openedBugsPerUser->graph->xAxisName = '用戶'; +$lang->bug->report->resolvedBugsPerUser->graph->xAxisName= '用戶'; +$lang->bug->report->closedBugsPerUser->graph->xAxisName = '用戶'; + +$lang->bug->report->bugsPerSeverity->graph->xAxisName = '嚴重程度'; +$lang->bug->report->bugsPerResolution->graph->xAxisName = '解決方案'; +$lang->bug->report->bugsPerStatus->graph->xAxisName = '狀態'; +$lang->bug->report->bugsPerActivatedCount->graph->xAxisName = '激活次數'; +$lang->bug->report->bugsPerType->graph->xAxisName = '類型'; +$lang->bug->report->bugsPerAssignedTo->graph->xAxisName = '指派給'; +$lang->bug->report->bugLiveDays->graph->xAxisName = '處理時間'; +$lang->bug->report->bugHistories->graph->xAxisName = '處理步驟'; + +/* 操作記錄。*/ +$lang->bug->action->resolved = array('main' => '$date, 由 $actor 解決,方案為 $extra。', 'extra' => $lang->bug->resolutionList); +$lang->bug->action->tostory = array('main' => '$date, 由 $actor 轉為需求,編號為 $extra。'); +$lang->bug->action->totask = array('main' => '$date, 由 $actor 導入為任務,編號為 $extra。'); diff --git a/module/bug/model.php b/module/bug/model.php index b2cf5064c2..d15a3ca542 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1,988 +1,988 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> -loadModel('product')->setMenu($products, $productID); - $selectHtml = $this->product->select($products, $productID, 'bug', 'browse'); - foreach($this->lang->bug->menu as $key => $menu) - { - $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow : $productID; - common::setMenuVars($this->lang->bug->menu, $key, $replace); - } - } - - /** - * Create a bug. - * - * @access public - * @return int|bool - */ - public function create() - { - $now = helper::now(); - $bug = fixer::input('post') - ->add('openedBy', $this->app->user->account) - ->add('openedDate', $now) - ->setDefault('project,story,task', 0) - ->setDefault('openedBuild', '') - ->setIF($this->post->assignedTo != '', 'assignedDate', $now) - ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - ->specialChars('title,keyword') - ->cleanInt('product, module, severity') - ->join('openedBuild', ',') - ->remove('files, labels') - ->get(); - $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); - if(!dao::isError()) - { - $bugID = $this->dao->lastInsertID(); - $this->loadModel('file')->saveUpload('bug', $bugID); - return $bugID; - } - return false; - } - - /** - * Get bugs of a module. - * - * @param int $productID - * @param string|array $moduleIds - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getModuleBugs($productID, $moduleIds = 0, $projects, $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('*')->from(TABLE_BUG) - ->where('product')->eq((int)$productID) - ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get info of a bug. - * - * @param int $bugID - * @access public - * @return object - */ - public function getById($bugID) - { - $bug = $this->dao->select('t1.*, t2.name AS projectName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id') - ->leftJoin(TABLE_TASK)->alias('t4')->on('t1.task = t4.id') - ->where('t1.id')->eq((int)$bugID)->fetch(); - if(!$bug) return false; - $bug->steps = $this->loadModel('file')->setImgSize($bug->steps); - foreach($bug as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $bug->$key = ''; - if($bug->mailto) - { - $bug->mailto = ltrim(trim($bug->mailto), ','); // Remove the first , - $bug->mailto = str_replace(' ', '', $bug->mailto); - $bug->mailto = rtrim($bug->mailto, ',') . ','; - $bug->mailto = str_replace(',', ', ', $bug->mailto); - } - if($bug->duplicateBug) $bug->duplicateBugTitle = $this->dao->findById($bug->duplicateBug)->from(TABLE_BUG)->fields('title')->fetch('title'); - if($bug->case) $bug->caseTitle = $this->dao->findById($bug->case)->from(TABLE_CASE)->fields('title')->fetch('title'); - if($bug->linkBug) $bug->linkBugTitles = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs(); - if($bug->toStory > 0) $bug->toStoryTitle = $this->dao->findById($bug->toStory)->from(TABLE_STORY)->fields('title')->fetch('title'); - if($bug->toTask > 0) $bug->toTaskTitle = $this->dao->findById($bug->toTask)->from(TABLE_TASK)->fields('name')->fetch('name'); - $bug->files = $this->loadModel('file')->getByObject('bug', $bugID); - return $bug; - } - - /** - * getActiveBugs - * - * @param object $pager - * @param int $projectID - * @access public - * @return array - */ - public function getActiveBugs($pager, $projectID, $products) - { - return $this->dao->select('*')->from(TABLE_BUG) - ->where('status')->eq('active') - ->andWhere('toTask')->eq(0) - ->andWhere('tostory')->eq(0) - ->beginIF(!empty($products))->andWhere('product')->in($products)->fi() - ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy('id desc') - ->page($pager) - ->fetchAll(); - } - - /** - * Update a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function update($bugID) - { - $oldBug = $this->getById($bugID); - $now = helper::now(); - $bug = fixer::input('post') - ->cleanInt('product,module,severity,project,story,task') - ->specialChars('title,keyword') - ->remove('comment,files,labels') - ->setDefault('project,module,project,story,task,duplicateBug', 0) - ->setDefault('openedBuild', '') - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->join('openedBuild', ',') - ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now) - ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) - ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) - ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account) - ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now) - ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account) - ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed') - ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now) - ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved') - ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed') - ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy) - ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now) - ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active') - ->setIF($this->post->resolution != '', 'confirmed', 1) - ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - ->get(); - - $this->dao->update(TABLE_BUG)->data($bug) - ->autoCheck() - ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') - ->checkIF($bug->resolvedBy, 'resolution', 'notempty') - ->checkIF($bug->closedBy, 'resolution', 'notempty') - ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') - ->where('id')->eq((int)$bugID) - ->exec(); - if(!dao::isError()) return common::createChanges($oldBug, $bug); - } - - /** - * Confirm a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function confirm($bugID) - { - $now = helper::now(); - $bug->confirmed = 1; - $bug->lastEditedBy = $this->app->user->account; - $bug->lastEditedDate = $now; - $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); - } - - /** - * Resolve a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function resolve($bugID) - { - $now = helper::now(); - $bug = fixer::input('post') - ->add('resolvedBy', $this->app->user->account) - ->add('resolvedDate', $now) - ->add('status', 'resolved') - ->add('confirmed', 1) - ->add('assignedDate', $now) - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->setDefault('duplicateBug', 0) - ->setDefault('assignedTo', $oldBug->openedBy) - ->remove('comment') - ->get(); - - $this->dao->update(TABLE_BUG)->data($bug) - ->autoCheck() - ->batchCheck($this->config->bug->resolve->requiredFields, 'notempty') - ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') - ->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty') - ->where('id')->eq((int)$bugID) - ->exec(); - } - - /** - * Activate a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function activate($bugID) - { - $oldBug = $this->getById($bugID); - $now = helper::now(); - $bug = fixer::input('post') - ->setDefault('assignedTo', $oldBug->resolvedBy) - ->add('assignedDate', $now) - ->add('resolution', '') - ->add('status', 'active') - ->add('resolvedDate', '0000-00-00') - ->add('resolvedBy', '') - ->add('resolvedBuild', '') - ->add('closedBy', '') - ->add('closedDate', '0000-00-00') - ->add('duplicateBug', 0) - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->join('openedBuild', ',') - ->remove('comment,files,labels') - ->get(); - - $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); - $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec(); - } - - /** - * Close a bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function close($bugID) - { - $oldBug = $this->getById($bugID); - $now = helper::now(); - $bug = fixer::input('post') - ->add('assignedTo', 'closed') - ->add('assignedDate', $now) - ->add('status', 'closed') - ->add('closedBy', $this->app->user->account) - ->add('closedDate', $now) - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->add('confirmed', 1) - ->remove('comment') - ->get(); - - $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); - } - - /** - * Extract accounts from some bugs. - * - * @param int $bugs - * @access public - * @return array - */ - public function extractAccountsFromList($bugs) - { - $accounts = array(); - foreach($bugs as $bug) - { - if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; - if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; - if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; - if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; - if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; - } - return array_unique($accounts); - } - - /** - * Extract accounts from a bug. - * - * @param object $bug - * @access public - * @return array - */ - public function extractAccountsFromSingle($bug) - { - $accounts = array(); - if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; - if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; - if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; - if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; - if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; - return array_unique($accounts); - } - - /** - * Get bug pairs of a user. - * - * @param int $account - * @param bool $appendProduct - * @param int $limit - * @access public - * @return array - */ - public function getUserBugPairs($account, $appendProduct = true, $limit = 0) - { - $bugs = array(); - $stmt = $this->dao->select('t1.id, t1.title, t2.name as product') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product=t2.id') - ->where('t1.assignedTo')->eq($account) - ->andWhere('t1.deleted')->eq(0) - ->orderBy('id desc') - ->beginIF($limit > 0)->limit($limit)->fi() - ->query(); - while($bug = $stmt->fetch()) - { - if($appendProduct) $bug->title = $bug->product . ' / ' . $bug->title; - $bugs[$bug->id] = $bug->title; - } - return $bugs; - } - - /** - * Get bugs of a project. - * - * @param int $projectID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getProjectBugs($projectID, $orderBy = 'id_desc', $pager = null, $build = 0) - { - return $this->dao->select('*')->from(TABLE_BUG) - ->where('project')->eq((int)$projectID) - ->beginIF($build != 0)->andWhere('openedBuild')->eq($build)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bug info from a result. - * - * @param int $resultID - * @param int $caseID - * @param int $version - * @access public - * @return array - */ - public function getBugInfoFromResult($resultID, $caseID = 0, $version = 0) - { - $title = ''; - $bugSteps = ''; - - $result = $this->dao->findById($resultID)->from(TABLE_TESTRESULT)->fetch(); - if($caseID > 0) - $run->case = $this->loadModel('testcase')->getById($caseID, $result->version); - else - $run = $this->loadModel('testtask')->getRunById($result->run); - if($result and $result->caseResult == 'fail') - { - $title = $run->case->title; - $caseSteps = $run->case->steps; - $stepResults = unserialize($result->stepResults); - if($run->case->precondition != '') - { - $bugSteps = "

[" . $this->lang->testcase->precondition . "]

" . "\n" . $run->case->precondition; - } - $bugSteps .= $this->lang->bug->tplStep; - if(!empty($stepResults)) - { - foreach($caseSteps as $key => $step) - { - $bugSteps .= ($key + 1) . '. ' .$step->desc . "
"; - if($stepResults[$step->id]['result'] == 'fail') - { - $bugSteps .= $this->lang->bug->tplResult; - $bugSteps .= $stepResults[$step->id]['real'] . "
"; - $bugSteps .= $this->lang->bug->tplExpect; - $bugSteps .= $step->expect; - break; - } - } - } - else - { - $bugSteps .= $this->lang->bug->tplResult; - $bugSteps .= $this->lang->bug->tplExpect; - } - } - return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story); - } - - /** - * Get report data of bugs per project - * - * @access public - * @return array - */ - public function getDataOfBugsPerProject() - { - $datas = $this->dao->select('project as name, count(project) as value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('project')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $projects = $this->loadModel('project')->getPairs(); - foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of bugs per module - * - * @access public - * @return array - */ - public function getDataOfBugsPerModule() - { - $datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('module')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs(); - foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/'; - return $datas; - } - - /** - * Get report data of opened bugs per day. - * - * @access public - * @return array - */ - public function getDataOfOpenedBugsPerDay() - { - return $this->dao->select('DATE_FORMAT(openedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('openedDate')->fetchAll(); - } - - /** - * Get report data of resolved bugs per day. - * - * @access public - * @return array - */ - public function getDataOfResolvedBugsPerDay() - { - return $this->dao->select('DATE_FORMAT(resolvedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG) - ->where($this->session->bugReportCondition)->groupBy('name') - ->having('name != 0000-00-00') - ->orderBy('resolvedDate') - ->fetchAll(); - } - - /** - * Get report data of closed bugs per day. - * - * @access public - * @return array - */ - public function getDataOfClosedBugsPerDay() - { - return $this->dao->select('DATE_FORMAT(closedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG) - ->where($this->session->bugReportCondition)->groupBy('name') - ->having('name != 0000-00-00') - ->orderBy('closedDate')->fetchAll(); - } - - /** - * Get report data of openeded bugs per user. - * - * @access public - * @return array - */ - public function getDataOfOpenedBugsPerUser() - { - $datas = $this->dao->select('openedBy AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - return $datas; - } - - /** - * Get report data of resolved bugs per user. - * - * @access public - * @return array - */ - public function getDataOfResolvedBugsPerUser() - { - $datas = $this->dao->select('resolvedBy AS name, COUNT(*) AS value') - ->from(TABLE_BUG)->where($this->session->bugReportCondition) - ->andWhere('resolvedBy')->ne('') - ->groupBy('name') - ->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - return $datas; - } - - /** - * Get report data of closed bugs per user. - * - * @access public - * @return array - */ - public function getDataOfClosedBugsPerUser() - { - $datas = $this->dao->select('closedBy AS name, COUNT(*) AS value') - ->from(TABLE_BUG) - ->where($this->session->bugReportCondition) - ->andWhere('closedBy')->ne('') - ->groupBy('name') - ->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - return $datas; - } - - /** - * Get report data of bugs per severity. - * - * @access public - * @return array - */ - public function getDataOfBugsPerSeverity() - { - $datas = $this->dao->select('severity AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $severity => $data) if(isset($this->lang->bug->severityList[$severity])) $data->name = $this->lang->bug->severityList[$severity]; - return $datas; - } - - /** - * Get report data of bugs per resolution. - * - * @access public - * @return array - */ - public function getDataOfBugsPerResolution() - { - $datas = $this->dao->select('resolution AS name, COUNT(*) AS value') - ->from(TABLE_BUG) - ->where($this->session->bugReportCondition) - ->andWhere('resolution')->ne('') - ->groupBy('name')->orderBy('value DESC') - ->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $resolution => $data) if(isset($this->lang->bug->resolutionList[$resolution])) $data->name = $this->lang->bug->resolutionList[$resolution]; - return $datas; - } - - /** - * Get report data of bugs per status. - * - * @access public - * @return array - */ - public function getDataOfBugsPerStatus() - { - $datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status]; - return $datas; - } - - /** - * Get report data of bugs per status. - * - * @access public - * @return array - */ - public function getDataOfBugsPerActivatedCount() - { - $datas = $this->dao->select('activatedCount AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerActivatedCount->graph->xAxisName . ':' . $data->name; - return $datas; - } - - /** - * Get report data of bugs per type. - * - * @access public - * @return array - */ - public function getDataOfBugsPerType() - { - $datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $type => $data) if(isset($this->lang->bug->typeList[$type])) $data->name = $this->lang->bug->typeList[$type]; - return $datas; - } - - /** - * getDataOfBugsPerAssignedTo - * - * @access public - * @return void - */ - public function getDataOfBugsPerAssignedTo() - { - $datas = $this->dao->select('assignedTo AS name, COUNT(*) AS value') - ->from(TABLE_BUG)->where($this->session->bugReportCondition) - ->groupBy('name') - ->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - return $datas; - } - - /** - * Merge the default chart settings and the settings of current chart. - * - * @param string $chartType - * @access public - * @return void - */ - public function mergeChartOption($chartType) - { - $chartOption = $this->lang->bug->report->$chartType; - $commonOption = $this->lang->bug->report->options; - - $chartOption->graph->caption = $this->lang->bug->report->charts[$chartType]; - if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; - if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; - if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; - - /* 合并配置。*/ - foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; - } - - /** - * Get bug templates of a user. - * - * @param string $account - * @access public - * @return array - */ - public function getUserBugTemplates($account) - { - $templates = $this->dao->select('id, title, content') - ->from(TABLE_USERTPL) - ->where('account')->eq($account) - ->orderBy('id') - ->fetchAll(); - return $templates; - } - - /** - * Save user template. - * - * @access public - * @return void - */ - public function saveUserBugTemplate() - { - $template = fixer::input('post') - ->specialChars('title') - ->add('account', $this->app->user->account) - ->add('type', 'bug') - ->get(); - $this->dao->insert(TABLE_USERTPL)->data($template)->autoCheck('title, content', 'notempty')->check('title', 'unique')->exec(); - } - - /** - * Return the file => label pairs of some fields. - * - * @param string $fields - * @access public - * @return array - */ - public function getFieldPairs($fields) - { - $fields = explode(',', $fields); - foreach($fields as $key => $field) - { - $field = trim($field); - $fields[$field] = $this->lang->bug->$field; - unset($fields[$key]); - } - return $fields; - } - - /** - * Get all bugs. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getAllBugs($productID, $projects, $orderBy, $pager) - { - return $this->dao->select('*')->from(TABLE_BUG)->where('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs of assign to me. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByAssigntome($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs of opened by me. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByOpenedbyme($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs of resolved by me. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByResolvedbyme($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs of nobody to do. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByAssigntonull($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs the status is active or unclosed. - * - * @param int $productID - * @param array $projects - * @param string $status - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByStatus($productID, $projects, $status, $orderBy, $pager) - { - return $this->dao->select('*')->from(TABLE_BUG) - ->where('project')->in(array_keys($projects)) - ->andWhere('product')->eq($productID) - ->beginIF($status == 'unclosed')->andWhere('status')->ne('closed')->fi() - ->beginIF($status == 'unresolved')->andWhere('status')->eq('active')->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get unresolve bugs for long time. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByLonglifebugs($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByLastEditedDate("<", date(DT_DATE1, strtotime('-7 days')))->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->andWhere('openedDate')->lt(date(DT_DATE1,strtotime('-7 days'))) - ->andWhere('deleted')->eq(0) - ->andWhere('status')->ne('closed')->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get postponed bugs. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByPostponedbugs($productID, $projects, $orderBy, $pager) - { - return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->eq($productID) - ->andWhere('project')->in(array_keys($projects)) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get bugs need confirm. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByNeedconfirm($productID, $projects, $orderBy, $pager) - { - return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->where("t2.status = 'active'") - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t2.version > t1.storyVersion') - ->andWhere('t1.project')->in(array_keys($projects)) - ->orderBy($orderBy) - ->fetchAll(); - } - - /** - * Get bugs by search. - * - * @param int $productID - * @param array $projects - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getBySearch($productID, $projects, $queryID, $orderBy, $pager) - { - if($queryID) - { - $query = $this->loadModel('search')->getQuery($queryID); - if($query) - { - $this->session->set('bugQuery', $query->sql); - $this->session->set('bugForm', $query->form); - } - else - { - $this->session->set('bugQuery', ' 1 = 1'); - } - } - else - { - if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1'); - } - - /* check the purview of projects.*/ - if(strpos($this->session->bugQuery, '`project`') === false) - { - $var = $this->session->bugQuery . 'AND `project`' . helper::dbIN(array_keys($projects)); - $this->session->set('bugQuery', "$var"); - } - - $bugQuery = str_replace("`product` = 'all'", '1', $this->session->bugQuery); // Search all product. - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - return $bugs; - } - - /** - * Form customed bugs. - * - * @param array $bugs - * @access public - * @return array - */ - public function formCustomedBugs($bugs) - { - /* Get related objects id lists. */ - $relatedModuleIdList = array(); - $relatedStoryIdList = array(); - $relatedTaskIdList = array(); - $relatedCaseIdList = array(); - $relatedProjectIdList = array(); - - foreach($bugs as $bug) - { - $relatedModuleIdList[$bug->module] = $bug->module; - $relatedStoryIdList[$bug->story] = $bug->story; - $relatedTaskIdList[$bug->task] = $bug->task; - $relatedCaseIdList[$bug->case] = $bug->case; - $relatedProjectIdList[$bug->project] = $bug->project; - - /* Get related objects title or names. */ - $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); - $relatedStories = $this->dao->select('id, title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); - $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs(); - $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); - $relatedProjects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->in($relatedProjectIdList)->fetchPairs(); - - /* fill some field with useful value. */ - if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module]; - if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story]; - if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task]; - if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case]; - if(isset($relatedProjects[$bug->project])) $bug->project = $relatedProjects[$bug->project]; - } - return $bugs; - } -} + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('product')->setMenu($products, $productID); + $selectHtml = $this->product->select($products, $productID, 'bug', 'browse'); + foreach($this->lang->bug->menu as $key => $menu) + { + $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow : $productID; + common::setMenuVars($this->lang->bug->menu, $key, $replace); + } + } + + /** + * Create a bug. + * + * @access public + * @return int|bool + */ + public function create() + { + $now = helper::now(); + $bug = fixer::input('post') + ->add('openedBy', $this->app->user->account) + ->add('openedDate', $now) + ->setDefault('project,story,task', 0) + ->setDefault('openedBuild', '') + ->setIF($this->post->assignedTo != '', 'assignedDate', $now) + ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + ->specialChars('title,keyword') + ->cleanInt('product, module, severity') + ->join('openedBuild', ',') + ->remove('files, labels') + ->get(); + $this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec(); + if(!dao::isError()) + { + $bugID = $this->dao->lastInsertID(); + $this->loadModel('file')->saveUpload('bug', $bugID); + return $bugID; + } + return false; + } + + /** + * Get bugs of a module. + * + * @param int $productID + * @param string|array $moduleIds + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getModuleBugs($productID, $moduleIds = 0, $projects, $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('*')->from(TABLE_BUG) + ->where('product')->eq((int)$productID) + ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get info of a bug. + * + * @param int $bugID + * @access public + * @return object + */ + public function getById($bugID) + { + $bug = $this->dao->select('t1.*, t2.name AS projectName, t3.title AS storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, t4.name AS taskName') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id') + ->leftJoin(TABLE_TASK)->alias('t4')->on('t1.task = t4.id') + ->where('t1.id')->eq((int)$bugID)->fetch(); + if(!$bug) return false; + $bug->steps = $this->loadModel('file')->setImgSize($bug->steps); + foreach($bug as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $bug->$key = ''; + if($bug->mailto) + { + $bug->mailto = ltrim(trim($bug->mailto), ','); // Remove the first , + $bug->mailto = str_replace(' ', '', $bug->mailto); + $bug->mailto = rtrim($bug->mailto, ',') . ','; + $bug->mailto = str_replace(',', ', ', $bug->mailto); + } + if($bug->duplicateBug) $bug->duplicateBugTitle = $this->dao->findById($bug->duplicateBug)->from(TABLE_BUG)->fields('title')->fetch('title'); + if($bug->case) $bug->caseTitle = $this->dao->findById($bug->case)->from(TABLE_CASE)->fields('title')->fetch('title'); + if($bug->linkBug) $bug->linkBugTitles = $this->dao->select('id,title')->from(TABLE_BUG)->where('id')->in($bug->linkBug)->fetchPairs(); + if($bug->toStory > 0) $bug->toStoryTitle = $this->dao->findById($bug->toStory)->from(TABLE_STORY)->fields('title')->fetch('title'); + if($bug->toTask > 0) $bug->toTaskTitle = $this->dao->findById($bug->toTask)->from(TABLE_TASK)->fields('name')->fetch('name'); + $bug->files = $this->loadModel('file')->getByObject('bug', $bugID); + return $bug; + } + + /** + * getActiveBugs + * + * @param object $pager + * @param int $projectID + * @access public + * @return array + */ + public function getActiveBugs($pager, $projectID, $products) + { + return $this->dao->select('*')->from(TABLE_BUG) + ->where('status')->eq('active') + ->andWhere('toTask')->eq(0) + ->andWhere('tostory')->eq(0) + ->beginIF(!empty($products))->andWhere('product')->in($products)->fi() + ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy('id desc') + ->page($pager) + ->fetchAll(); + } + + /** + * Update a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function update($bugID) + { + $oldBug = $this->getById($bugID); + $now = helper::now(); + $bug = fixer::input('post') + ->cleanInt('product,module,severity,project,story,task') + ->specialChars('title,keyword') + ->remove('comment,files,labels') + ->setDefault('project,module,project,story,task,duplicateBug', 0) + ->setDefault('openedBuild', '') + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->join('openedBuild', ',') + ->setIF($this->post->assignedTo != $oldBug->assignedTo, 'assignedDate', $now) + ->setIF($this->post->resolvedBy != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) + ->setIF($this->post->resolution != '' and $this->post->resolvedDate == '', 'resolvedDate', $now) + ->setIF($this->post->resolution != '' and $this->post->resolvedBy == '', 'resolvedBy', $this->app->user->account) + ->setIF($this->post->closedBy != '' and $this->post->closedDate == '', 'closedDate', $now) + ->setIF($this->post->closedDate != '' and $this->post->closedBy == '', 'closedBy', $this->app->user->account) + ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedTo', 'closed') + ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'assignedDate', $now) + ->setIF($this->post->resolution != '' or $this->post->resolvedDate != '', 'status', 'resolved') + ->setIF($this->post->closedBy != '' or $this->post->closedDate != '', 'status', 'closed') + ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedTo', $oldBug->openedBy) + ->setIF(($this->post->resolution != '' or $this->post->resolvedDate != '') and $this->post->assignedTo == '', 'assignedDate', $now) + ->setIF($this->post->resolution == '' and $this->post->resolvedDate =='', 'status', 'active') + ->setIF($this->post->resolution != '', 'confirmed', 1) + ->setIF($this->post->story != false and $this->post->story != $oldBug->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + ->get(); + + $this->dao->update(TABLE_BUG)->data($bug) + ->autoCheck() + ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') + ->checkIF($bug->resolvedBy, 'resolution', 'notempty') + ->checkIF($bug->closedBy, 'resolution', 'notempty') + ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') + ->where('id')->eq((int)$bugID) + ->exec(); + if(!dao::isError()) return common::createChanges($oldBug, $bug); + } + + /** + * Confirm a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function confirm($bugID) + { + $now = helper::now(); + $bug->confirmed = 1; + $bug->lastEditedBy = $this->app->user->account; + $bug->lastEditedDate = $now; + $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); + } + + /** + * Resolve a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function resolve($bugID) + { + $now = helper::now(); + $bug = fixer::input('post') + ->add('resolvedBy', $this->app->user->account) + ->add('resolvedDate', $now) + ->add('status', 'resolved') + ->add('confirmed', 1) + ->add('assignedDate', $now) + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->setDefault('duplicateBug', 0) + ->setDefault('assignedTo', $oldBug->openedBy) + ->remove('comment') + ->get(); + + $this->dao->update(TABLE_BUG)->data($bug) + ->autoCheck() + ->batchCheck($this->config->bug->resolve->requiredFields, 'notempty') + ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') + ->checkIF($bug->resolution == 'fixed', 'resolvedBuild','notempty') + ->where('id')->eq((int)$bugID) + ->exec(); + } + + /** + * Activate a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function activate($bugID) + { + $oldBug = $this->getById($bugID); + $now = helper::now(); + $bug = fixer::input('post') + ->setDefault('assignedTo', $oldBug->resolvedBy) + ->add('assignedDate', $now) + ->add('resolution', '') + ->add('status', 'active') + ->add('resolvedDate', '0000-00-00') + ->add('resolvedBy', '') + ->add('resolvedBuild', '') + ->add('closedBy', '') + ->add('closedDate', '0000-00-00') + ->add('duplicateBug', 0) + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->join('openedBuild', ',') + ->remove('comment,files,labels') + ->get(); + + $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); + $this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec(); + } + + /** + * Close a bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function close($bugID) + { + $oldBug = $this->getById($bugID); + $now = helper::now(); + $bug = fixer::input('post') + ->add('assignedTo', 'closed') + ->add('assignedDate', $now) + ->add('status', 'closed') + ->add('closedBy', $this->app->user->account) + ->add('closedDate', $now) + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->add('confirmed', 1) + ->remove('comment') + ->get(); + + $this->dao->update(TABLE_BUG)->data($bug)->autoCheck()->where('id')->eq((int)$bugID)->exec(); + } + + /** + * Extract accounts from some bugs. + * + * @param int $bugs + * @access public + * @return array + */ + public function extractAccountsFromList($bugs) + { + $accounts = array(); + foreach($bugs as $bug) + { + if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; + if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; + if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; + if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; + if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; + } + return array_unique($accounts); + } + + /** + * Extract accounts from a bug. + * + * @param object $bug + * @access public + * @return array + */ + public function extractAccountsFromSingle($bug) + { + $accounts = array(); + if(!empty($bug->openedBy)) $accounts[] = $bug->openedBy; + if(!empty($bug->assignedTo)) $accounts[] = $bug->assignedTo; + if(!empty($bug->resolvedBy)) $accounts[] = $bug->resolvedBy; + if(!empty($bug->closedBy)) $accounts[] = $bug->closedBy; + if(!empty($bug->lastEditedBy)) $accounts[] = $bug->lastEditedBy; + return array_unique($accounts); + } + + /** + * Get bug pairs of a user. + * + * @param int $account + * @param bool $appendProduct + * @param int $limit + * @access public + * @return array + */ + public function getUserBugPairs($account, $appendProduct = true, $limit = 0) + { + $bugs = array(); + $stmt = $this->dao->select('t1.id, t1.title, t2.name as product') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product=t2.id') + ->where('t1.assignedTo')->eq($account) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('id desc') + ->beginIF($limit > 0)->limit($limit)->fi() + ->query(); + while($bug = $stmt->fetch()) + { + if($appendProduct) $bug->title = $bug->product . ' / ' . $bug->title; + $bugs[$bug->id] = $bug->title; + } + return $bugs; + } + + /** + * Get bugs of a project. + * + * @param int $projectID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getProjectBugs($projectID, $orderBy = 'id_desc', $pager = null, $build = 0) + { + return $this->dao->select('*')->from(TABLE_BUG) + ->where('project')->eq((int)$projectID) + ->beginIF($build != 0)->andWhere('openedBuild')->eq($build)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bug info from a result. + * + * @param int $resultID + * @param int $caseID + * @param int $version + * @access public + * @return array + */ + public function getBugInfoFromResult($resultID, $caseID = 0, $version = 0) + { + $title = ''; + $bugSteps = ''; + + $result = $this->dao->findById($resultID)->from(TABLE_TESTRESULT)->fetch(); + if($caseID > 0) + $run->case = $this->loadModel('testcase')->getById($caseID, $result->version); + else + $run = $this->loadModel('testtask')->getRunById($result->run); + if($result and $result->caseResult == 'fail') + { + $title = $run->case->title; + $caseSteps = $run->case->steps; + $stepResults = unserialize($result->stepResults); + if($run->case->precondition != '') + { + $bugSteps = "

[" . $this->lang->testcase->precondition . "]

" . "\n" . $run->case->precondition; + } + $bugSteps .= $this->lang->bug->tplStep; + if(!empty($stepResults)) + { + foreach($caseSteps as $key => $step) + { + $bugSteps .= ($key + 1) . '. ' .$step->desc . "
"; + if($stepResults[$step->id]['result'] == 'fail') + { + $bugSteps .= $this->lang->bug->tplResult; + $bugSteps .= $stepResults[$step->id]['real'] . "
"; + $bugSteps .= $this->lang->bug->tplExpect; + $bugSteps .= $step->expect; + break; + } + } + } + else + { + $bugSteps .= $this->lang->bug->tplResult; + $bugSteps .= $this->lang->bug->tplExpect; + } + } + return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story); + } + + /** + * Get report data of bugs per project + * + * @access public + * @return array + */ + public function getDataOfBugsPerProject() + { + $datas = $this->dao->select('project as name, count(project) as value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('project')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $projects = $this->loadModel('project')->getPairs(); + foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of bugs per module + * + * @access public + * @return array + */ + public function getDataOfBugsPerModule() + { + $datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('module')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs(); + foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/'; + return $datas; + } + + /** + * Get report data of opened bugs per day. + * + * @access public + * @return array + */ + public function getDataOfOpenedBugsPerDay() + { + return $this->dao->select('DATE_FORMAT(openedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('openedDate')->fetchAll(); + } + + /** + * Get report data of resolved bugs per day. + * + * @access public + * @return array + */ + public function getDataOfResolvedBugsPerDay() + { + return $this->dao->select('DATE_FORMAT(resolvedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG) + ->where($this->session->bugReportCondition)->groupBy('name') + ->having('name != 0000-00-00') + ->orderBy('resolvedDate') + ->fetchAll(); + } + + /** + * Get report data of closed bugs per day. + * + * @access public + * @return array + */ + public function getDataOfClosedBugsPerDay() + { + return $this->dao->select('DATE_FORMAT(closedDate, "%Y-%m-%d") AS name, COUNT(*) AS value')->from(TABLE_BUG) + ->where($this->session->bugReportCondition)->groupBy('name') + ->having('name != 0000-00-00') + ->orderBy('closedDate')->fetchAll(); + } + + /** + * Get report data of openeded bugs per user. + * + * @access public + * @return array + */ + public function getDataOfOpenedBugsPerUser() + { + $datas = $this->dao->select('openedBy AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + return $datas; + } + + /** + * Get report data of resolved bugs per user. + * + * @access public + * @return array + */ + public function getDataOfResolvedBugsPerUser() + { + $datas = $this->dao->select('resolvedBy AS name, COUNT(*) AS value') + ->from(TABLE_BUG)->where($this->session->bugReportCondition) + ->andWhere('resolvedBy')->ne('') + ->groupBy('name') + ->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + return $datas; + } + + /** + * Get report data of closed bugs per user. + * + * @access public + * @return array + */ + public function getDataOfClosedBugsPerUser() + { + $datas = $this->dao->select('closedBy AS name, COUNT(*) AS value') + ->from(TABLE_BUG) + ->where($this->session->bugReportCondition) + ->andWhere('closedBy')->ne('') + ->groupBy('name') + ->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + return $datas; + } + + /** + * Get report data of bugs per severity. + * + * @access public + * @return array + */ + public function getDataOfBugsPerSeverity() + { + $datas = $this->dao->select('severity AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $severity => $data) if(isset($this->lang->bug->severityList[$severity])) $data->name = $this->lang->bug->severityList[$severity]; + return $datas; + } + + /** + * Get report data of bugs per resolution. + * + * @access public + * @return array + */ + public function getDataOfBugsPerResolution() + { + $datas = $this->dao->select('resolution AS name, COUNT(*) AS value') + ->from(TABLE_BUG) + ->where($this->session->bugReportCondition) + ->andWhere('resolution')->ne('') + ->groupBy('name')->orderBy('value DESC') + ->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $resolution => $data) if(isset($this->lang->bug->resolutionList[$resolution])) $data->name = $this->lang->bug->resolutionList[$resolution]; + return $datas; + } + + /** + * Get report data of bugs per status. + * + * @access public + * @return array + */ + public function getDataOfBugsPerStatus() + { + $datas = $this->dao->select('status AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $status => $data) if(isset($this->lang->bug->statusList[$status])) $data->name = $this->lang->bug->statusList[$status]; + return $datas; + } + + /** + * Get report data of bugs per status. + * + * @access public + * @return array + */ + public function getDataOfBugsPerActivatedCount() + { + $datas = $this->dao->select('activatedCount AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $data) $data->name = $this->lang->bug->report->bugsPerActivatedCount->graph->xAxisName . ':' . $data->name; + return $datas; + } + + /** + * Get report data of bugs per type. + * + * @access public + * @return array + */ + public function getDataOfBugsPerType() + { + $datas = $this->dao->select('type AS name, COUNT(*) AS value')->from(TABLE_BUG)->where($this->session->bugReportCondition)->groupBy('name')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $type => $data) if(isset($this->lang->bug->typeList[$type])) $data->name = $this->lang->bug->typeList[$type]; + return $datas; + } + + /** + * getDataOfBugsPerAssignedTo + * + * @access public + * @return void + */ + public function getDataOfBugsPerAssignedTo() + { + $datas = $this->dao->select('assignedTo AS name, COUNT(*) AS value') + ->from(TABLE_BUG)->where($this->session->bugReportCondition) + ->groupBy('name') + ->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + return $datas; + } + + /** + * Merge the default chart settings and the settings of current chart. + * + * @param string $chartType + * @access public + * @return void + */ + public function mergeChartOption($chartType) + { + $chartOption = $this->lang->bug->report->$chartType; + $commonOption = $this->lang->bug->report->options; + + $chartOption->graph->caption = $this->lang->bug->report->charts[$chartType]; + if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; + if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; + if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; + + /* 合并配置。*/ + foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; + } + + /** + * Get bug templates of a user. + * + * @param string $account + * @access public + * @return array + */ + public function getUserBugTemplates($account) + { + $templates = $this->dao->select('id, title, content') + ->from(TABLE_USERTPL) + ->where('account')->eq($account) + ->orderBy('id') + ->fetchAll(); + return $templates; + } + + /** + * Save user template. + * + * @access public + * @return void + */ + public function saveUserBugTemplate() + { + $template = fixer::input('post') + ->specialChars('title') + ->add('account', $this->app->user->account) + ->add('type', 'bug') + ->get(); + $this->dao->insert(TABLE_USERTPL)->data($template)->autoCheck('title, content', 'notempty')->check('title', 'unique')->exec(); + } + + /** + * Return the file => label pairs of some fields. + * + * @param string $fields + * @access public + * @return array + */ + public function getFieldPairs($fields) + { + $fields = explode(',', $fields); + foreach($fields as $key => $field) + { + $field = trim($field); + $fields[$field] = $this->lang->bug->$field; + unset($fields[$key]); + } + return $fields; + } + + /** + * Get all bugs. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getAllBugs($productID, $projects, $orderBy, $pager) + { + return $this->dao->select('*')->from(TABLE_BUG)->where('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs of assign to me. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByAssigntome($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs of opened by me. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByOpenedbyme($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs of resolved by me. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByResolvedbyme($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs of nobody to do. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByAssigntonull($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs the status is active or unclosed. + * + * @param int $productID + * @param array $projects + * @param string $status + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByStatus($productID, $projects, $status, $orderBy, $pager) + { + return $this->dao->select('*')->from(TABLE_BUG) + ->where('project')->in(array_keys($projects)) + ->andWhere('product')->eq($productID) + ->beginIF($status == 'unclosed')->andWhere('status')->ne('closed')->fi() + ->beginIF($status == 'unresolved')->andWhere('status')->eq('active')->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get unresolve bugs for long time. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByLonglifebugs($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByLastEditedDate("<", date(DT_DATE1, strtotime('-7 days')))->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->andWhere('openedDate')->lt(date(DT_DATE1,strtotime('-7 days'))) + ->andWhere('deleted')->eq(0) + ->andWhere('status')->ne('closed')->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get postponed bugs. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByPostponedbugs($productID, $projects, $orderBy, $pager) + { + return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->eq($productID) + ->andWhere('project')->in(array_keys($projects)) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get bugs need confirm. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByNeedconfirm($productID, $projects, $orderBy, $pager) + { + return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where("t2.status = 'active'") + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.version > t1.storyVersion') + ->andWhere('t1.project')->in(array_keys($projects)) + ->orderBy($orderBy) + ->fetchAll(); + } + + /** + * Get bugs by search. + * + * @param int $productID + * @param array $projects + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getBySearch($productID, $projects, $queryID, $orderBy, $pager) + { + if($queryID) + { + $query = $this->loadModel('search')->getQuery($queryID); + if($query) + { + $this->session->set('bugQuery', $query->sql); + $this->session->set('bugForm', $query->form); + } + else + { + $this->session->set('bugQuery', ' 1 = 1'); + } + } + else + { + if($this->session->bugQuery == false) $this->session->set('bugQuery', ' 1 = 1'); + } + + /* check the purview of projects.*/ + if(strpos($this->session->bugQuery, '`project`') === false) + { + $var = $this->session->bugQuery . 'AND `project`' . helper::dbIN(array_keys($projects)); + $this->session->set('bugQuery', "$var"); + } + + $bugQuery = str_replace("`product` = 'all'", '1', $this->session->bugQuery); // Search all product. + $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + return $bugs; + } + + /** + * Form customed bugs. + * + * @param array $bugs + * @access public + * @return array + */ + public function formCustomedBugs($bugs) + { + /* Get related objects id lists. */ + $relatedModuleIdList = array(); + $relatedStoryIdList = array(); + $relatedTaskIdList = array(); + $relatedCaseIdList = array(); + $relatedProjectIdList = array(); + + foreach($bugs as $bug) + { + $relatedModuleIdList[$bug->module] = $bug->module; + $relatedStoryIdList[$bug->story] = $bug->story; + $relatedTaskIdList[$bug->task] = $bug->task; + $relatedCaseIdList[$bug->case] = $bug->case; + $relatedProjectIdList[$bug->project] = $bug->project; + + /* Get related objects title or names. */ + $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); + $relatedStories = $this->dao->select('id, title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); + $relatedTasks = $this->dao->select('id, name')->from(TABLE_TASK)->where('id')->in($relatedTaskIdList)->fetchPairs(); + $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); + $relatedProjects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->in($relatedProjectIdList)->fetchPairs(); + + /* fill some field with useful value. */ + if(isset($relatedModules[$bug->module])) $bug->module = $relatedModules[$bug->module]; + if(isset($relatedStories[$bug->story])) $bug->story = $relatedStories[$bug->story]; + if(isset($relatedTasks[$bug->task])) $bug->task = $relatedTasks[$bug->task]; + if(isset($relatedCases[$bug->case])) $bug->case = $relatedCases[$bug->case]; + if(isset($relatedProjects[$bug->project])) $bug->project = $relatedProjects[$bug->project]; + } + return $bugs; + } +} diff --git a/module/bug/view/activate.html.php b/module/bug/view/activate.html.php index 7c7b973c09..a09b694da7 100644 --- a/module/bug/view/activate.html.php +++ b/module/bug/view/activate.html.php @@ -1,43 +1,43 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
- - - - - - - - - - - - - - - - - - - - - -
title;?>
bug->assignedTo;?>resolvedBy, 'class=select-3');?>
bug->openedBuild;?>openedBuild, 'size=4 multiple=multiple class=select-3');?>
comment;?>
bug->files;?>fetch('file', 'buildform');?>
- - -
- -
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + + + + + + + + + + + + + +
title;?>
bug->assignedTo;?>resolvedBy, 'class=select-3');?>
bug->openedBuild;?>openedBuild, 'size=4 multiple=multiple class=select-3');?>
comment;?>
bug->files;?>fetch('file', 'buildform');?>
+ + +
+ +
+ diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index b838312f58..0787e6ab7f 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -1,175 +1,175 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
-
- " . $lang->bug->moduleBugs . " "; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToMe¶m=0"), $lang->bug->assignToMe) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=openedByMe¶m=0"), $lang->bug->openedByMe) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=resolvedByMe¶m=0"), $lang->bug->resolvedByMe) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToNull¶m=0"), $lang->bug->assignToNull) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unResolved¶m=0"), $lang->bug->unResolved) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unclosed¶m=0"), $lang->bug->unclosed) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=longLifeBugs¶m=0"), $lang->bug->longLifeBugs) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=postponedBugs¶m=0"), $lang->bug->postponedBugs) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->bug->allBugs) . ""; - echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->bug->needConfirm) . ""; - echo "{$lang->bug->byQuery} "; - ?> -
-
- export, '', 'class="export"'); ?> - bug->customFields, '', "class='iframe'"); ?> - bug->report->common); ?> - bug->create); ?> -
-
-
'>
- - - - - - - - - -
-
-
- -
- createLink('tree', 'browse', "productID=$productID&view=bug"), $lang->tree->manage);?> -
-
-
- recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - id");?> - - status == 'active' ? 'active' . $bug->severity : $bug->status;?> - - - - - confirmed;?> - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - - cookie->windowWidth > $this->config->wideSize ? 12 : 9;?> - - - -
idAB);?> bug->severityAB);?> priAB);?>bug->title);?>bug->statusAB);?>bug->story);?>actions;?>openedByAB);?> bug->openedDateAB);?>assignedToAB);?>bug->resolvedByAB);?>bug->resolutionAB);?> bug->resolvedDateAB);?>actions;?>
bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>[{$lang->bug->confirmedList[$bug->confirmed]}] " . html::a($bugLink, $bug->title);?>bug->statusList[$bug->status];?>createLink('story', 'view', "stoyID=$bug->story"), $bug->storyTitle, '_blank');?>id"), $lang->confirm, 'hiddenwin')?>openedBy];?>openedDate, 5, 11)?>assignedTo == $this->app->user->account) echo 'class="red"';?>>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>resolvedDate, 5, 11)?> - id"; - if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; - if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; - common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); - if($this->cookie->windowWidth >= $this->config->wideSize) common::printLink('bug', 'create', "product=$bug->product&extra=bugID=$bug->id", $lang->bug->buttonCopy); - ?> -
-
- bug->statusList as $status => $label) - { - if($status != 'active') - { - echo " $label "; - continue; - } - rsort($this->lang->bug->severityList); - foreach($this->lang->bug->severityList as $severity) - { - echo " {$lang->bug->severity}:$severity "; - } - } - ?> -
-
show();?>
-
-
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
+
+ " . $lang->bug->moduleBugs . " "; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToMe¶m=0"), $lang->bug->assignToMe) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=openedByMe¶m=0"), $lang->bug->openedByMe) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=resolvedByMe¶m=0"), $lang->bug->resolvedByMe) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=assignToNull¶m=0"), $lang->bug->assignToNull) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unResolved¶m=0"), $lang->bug->unResolved) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=unclosed¶m=0"), $lang->bug->unclosed) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=longLifeBugs¶m=0"), $lang->bug->longLifeBugs) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=postponedBugs¶m=0"), $lang->bug->postponedBugs) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->bug->allBugs) . ""; + echo "" . html::a($this->createLink('bug', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->bug->needConfirm) . ""; + echo "{$lang->bug->byQuery} "; + ?> +
+
+ export, '', 'class="export"'); ?> + bug->customFields, '', "class='iframe'"); ?> + bug->report->common); ?> + bug->create); ?> +
+
+
'>
+ + + + + + + + + +
+
+
+ +
+ createLink('tree', 'browse', "productID=$productID&view=bug"), $lang->tree->manage);?> +
+
+
+ recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + id");?> + + status == 'active' ? 'active' . $bug->severity : $bug->status;?> + + + + + confirmed;?> + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + + cookie->windowWidth > $this->config->wideSize ? 12 : 9;?> + + + +
idAB);?> bug->severityAB);?> priAB);?>bug->title);?>bug->statusAB);?>bug->story);?>actions;?>openedByAB);?> bug->openedDateAB);?>assignedToAB);?>bug->resolvedByAB);?>bug->resolutionAB);?> bug->resolvedDateAB);?>actions;?>
bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>[{$lang->bug->confirmedList[$bug->confirmed]}] " . html::a($bugLink, $bug->title);?>bug->statusList[$bug->status];?>createLink('story', 'view', "stoyID=$bug->story"), $bug->storyTitle, '_blank');?>id"), $lang->confirm, 'hiddenwin')?>openedBy];?>openedDate, 5, 11)?>assignedTo == $this->app->user->account) echo 'class="red"';?>>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>resolvedDate, 5, 11)?> + id"; + if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; + if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; + common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); + if($this->cookie->windowWidth >= $this->config->wideSize) common::printLink('bug', 'create', "product=$bug->product&extra=bugID=$bug->id", $lang->bug->buttonCopy); + ?> +
+
+ bug->statusList as $status => $label) + { + if($status != 'active') + { + echo " $label "; + continue; + } + rsort($this->lang->bug->severityList); + foreach($this->lang->bug->severityList as $severity) + { + echo " {$lang->bug->severity}:$severity "; + } + } + ?> +
+
show();?>
+
+
+ diff --git a/module/bug/view/close.html.php b/module/bug/view/close.html.php index 932930ef6a..c1ff9253fa 100644 --- a/module/bug/view/close.html.php +++ b/module/bug/view/close.html.php @@ -1,31 +1,31 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
- - - - - - - - - -
title;?>
comment;?>
- - -
- -
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + +
title;?>
comment;?>
+ + +
+ +
+ diff --git a/module/bug/view/confirmbug.html.php b/module/bug/view/confirmbug.html.php index bf0dcc65cd..0aa2fc52a1 100755 --- a/module/bug/view/confirmbug.html.php +++ b/module/bug/view/confirmbug.html.php @@ -1,31 +1,31 @@ - - * @package bug - * @version $Id: resolve.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -?> - -
- - - - - - - - - -
title;?>
comment;?>
- bug->buttonConfirm);?> - -
- -
- + + * @package bug + * @version $Id: resolve.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + +
title;?>
comment;?>
+ bug->buttonConfirm);?> + +
+ +
+ diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php index 71642e13bb..54c7466f7c 100644 --- a/module/bug/view/create.html.php +++ b/module/bug/view/create.html.php @@ -1,102 +1,102 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bug->create;?>
bug->lblProductAndModule;?> - - -
bug->project;?>
bug->openedBuild;?> - -
bug->lblAssignedTo;?>
bug->title;?>
bug->steps;?> - - - - - -
fetch('bug', 'buildTemplates');?>
-
bug->lblStory;?> - -
bug->task;?>
bug->lblTypeAndSeverity;?> - bug->typeList, $type, 'class=select-2');?> - bug->severityList, $severity, 'class=select-2');?> -
bug->lblSystemBrowserAndHardware;?> - bug->osList, $os, 'class=select-2');?> - bug->browserList, $browser, 'class=select-2');?> -
bug->lblMailto;?>
bug->keywords;?>
bug->files;?>fetch('file', 'buildform', 'fileCount=2&percent=0.85');?>
- -
-
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bug->create;?>
bug->lblProductAndModule;?> + + +
bug->project;?>
bug->openedBuild;?> + +
bug->lblAssignedTo;?>
bug->title;?>
bug->steps;?> + + + + + +
fetch('bug', 'buildTemplates');?>
+
bug->lblStory;?> + +
bug->task;?>
bug->lblTypeAndSeverity;?> + bug->typeList, $type, 'class=select-2');?> + bug->severityList, $severity, 'class=select-2');?> +
bug->lblSystemBrowserAndHardware;?> + bug->osList, $os, 'class=select-2');?> + bug->browserList, $browser, 'class=select-2');?> +
bug->lblMailto;?>
bug->keywords;?>
bug->files;?>fetch('file', 'buildform', 'fileCount=2&percent=0.85');?>
+ +
+
+ diff --git a/module/bug/view/customfields.html.php b/module/bug/view/customfields.html.php index 576fa07ffd..cc6f2df478 100644 --- a/module/bug/view/customfields.html.php +++ b/module/bug/view/customfields.html.php @@ -1,49 +1,49 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
- - - - - - - - - - - - - - - -
bug->customFields;?>
bug->lblAllFields;?>bug->lblCustomFields;?>
- - - ', "onclick=\"addItem('allFields', 'customFields')\"") . '
'; - echo html::commonButton('<', "onclick=delItem('customFields')") . '
'; - ?> -
- '; - echo html::commonButton('-', "onclick=downItem('customFields')") . '
'; - echo html::commonButton($lang->bug->restoreDefault, "onclick=restoreDefault()") . '
'; - ?> -
-
- + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
+ + + + + + + + + + + + + + + +
bug->customFields;?>
bug->lblAllFields;?>bug->lblCustomFields;?>
+ + + ', "onclick=\"addItem('allFields', 'customFields')\"") . '
'; + echo html::commonButton('<', "onclick=delItem('customFields')") . '
'; + ?> +
+ '; + echo html::commonButton('-', "onclick=downItem('customFields')") . '
'; + echo html::commonButton($lang->bug->restoreDefault, "onclick=restoreDefault()") . '
'; + ?> +
+
+ diff --git a/module/bug/view/edit.html.php b/module/bug/view/edit.html.php index 3db2107e0e..e15296c932 100644 --- a/module/bug/view/edit.html.php +++ b/module/bug/view/edit.html.php @@ -1,206 +1,206 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
-
-
- BUG #id . $lang->colon;?> - title), 'class=text-1');?> -
-
-
- - - - - - - -
- - -
-
- bug->legendSteps;?> -
steps), "rows='12'");?>
-
-
- bug->legendComment;?> - -
-
- bug->legendAttatch;?> - fetch('file', 'buildform', 'filecount=2');?> -
-
- session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product"); - echo html::linkButton($lang->goback, $browseLink); - ?> -
-
- -
-
- bug->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bug->product;?> - -
bug->module;?> - -
bug->type;?>bug->typeList, $bug->type, 'class=select-3');?> -
bug->severity;?>bug->severityList, $bug->severity, 'class=select-3');?> -
bug->pri;?>bug->priList, $bug->pri, 'class=select-3');?> -
bug->status;?>bug->statusList, $bug->status, 'class=select-3');?>
bug->confirmed;?>bug->confirmedList[$bug->confirmed];?>
bug->assignedTo;?>assignedTo, 'class=select-3');?>
bug->os;?>bug->osList, $bug->os, 'class=select-3');?>
bug->browser;?>bug->browserList, $bug->browser, 'class=select-3');?>
bug->keywords;?>keywords, 'class="text-3"');?>
-
- -
- bug->legendPrjStoryTask;?> - - - - - - - - - - - - - -
bug->project;?>project, 'class=select-3 onchange=loadProjectRelated(this.value)');?>
bug->story;?>
story, "class=select-3");?>
- -
bug->task;?>
task, 'class=select-3');?>
- -
-
- -
- bug->legendLife;?> - - - - - - - - - - - - - - - - - - - - - - - - - - resolution != 'duplicate') echo "style='display:none'";?>> - - - - - - - - - - - -
bug->openedBy;?>openedBy];?>
bug->openedBuild;?>openedBuild, 'size=4 multiple=multiple class=select-3');?>
bug->resolvedBy;?>resolvedBy, 'class=select-3');?>
bug->resolvedDate;?>resolvedDate, 'class=text-3');?>
bug->resolvedBuild;?>resolvedBuild, 'class=select-3');?>
bug->resolution;?>bug->resolutionList, $bug->resolution, 'class=select-3 onchange=setDuplicate(this.value)');?>
bug->duplicateBug;?>duplicateBug, 'class=text-3');?>
bug->closedBy;?>closedBy, 'class=select-3');?>
bug->closedDate;?>closedDate, 'class=text-3');?>
-
-
- bug->legendMisc;?> - - - - - - - - - - - - - -
bug->mailto;?>mailto, 'class="text-3"');?>
bug->linkBug;?>linkBug, 'class="text-3"');?>
bug->case;?>case, 'class="text-3"');?>
-
-
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
+
+ BUG #id . $lang->colon;?> + title), 'class=text-1');?> +
+
+
+ + + + + + + +
+ + +
+
+ bug->legendSteps;?> +
steps), "rows='12'");?>
+
+
+ bug->legendComment;?> + +
+
+ bug->legendAttatch;?> + fetch('file', 'buildform', 'filecount=2');?> +
+
+ session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product"); + echo html::linkButton($lang->goback, $browseLink); + ?> +
+
+ +
+
+ bug->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bug->product;?> + +
bug->module;?> + +
bug->type;?>bug->typeList, $bug->type, 'class=select-3');?> +
bug->severity;?>bug->severityList, $bug->severity, 'class=select-3');?> +
bug->pri;?>bug->priList, $bug->pri, 'class=select-3');?> +
bug->status;?>bug->statusList, $bug->status, 'class=select-3');?>
bug->confirmed;?>bug->confirmedList[$bug->confirmed];?>
bug->assignedTo;?>assignedTo, 'class=select-3');?>
bug->os;?>bug->osList, $bug->os, 'class=select-3');?>
bug->browser;?>bug->browserList, $bug->browser, 'class=select-3');?>
bug->keywords;?>keywords, 'class="text-3"');?>
+
+ +
+ bug->legendPrjStoryTask;?> + + + + + + + + + + + + + +
bug->project;?>project, 'class=select-3 onchange=loadProjectRelated(this.value)');?>
bug->story;?>
story, "class=select-3");?>
+ +
bug->task;?>
task, 'class=select-3');?>
+ +
+
+ +
+ bug->legendLife;?> + + + + + + + + + + + + + + + + + + + + + + + + + + resolution != 'duplicate') echo "style='display:none'";?>> + + + + + + + + + + + +
bug->openedBy;?>openedBy];?>
bug->openedBuild;?>openedBuild, 'size=4 multiple=multiple class=select-3');?>
bug->resolvedBy;?>resolvedBy, 'class=select-3');?>
bug->resolvedDate;?>resolvedDate, 'class=text-3');?>
bug->resolvedBuild;?>resolvedBuild, 'class=select-3');?>
bug->resolution;?>bug->resolutionList, $bug->resolution, 'class=select-3 onchange=setDuplicate(this.value)');?>
bug->duplicateBug;?>duplicateBug, 'class=text-3');?>
bug->closedBy;?>closedBy, 'class=select-3');?>
bug->closedDate;?>closedDate, 'class=text-3');?>
+
+
+ bug->legendMisc;?> + + + + + + + + + + + + + +
bug->mailto;?>mailto, 'class="text-3"');?>
bug->linkBug;?>linkBug, 'class="text-3"');?>
bug->case;?>case, 'class="text-3"');?>
+
+
+ diff --git a/module/bug/view/export.html.php b/module/bug/view/export.html.php index 7719b29366..228c01d5da 100755 --- a/module/bug/view/export.html.php +++ b/module/bug/view/export.html.php @@ -1,13 +1,13 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + diff --git a/module/bug/view/report.html.php b/module/bug/view/report.html.php index c69683bbe4..1932051a27 100644 --- a/module/bug/view/report.html.php +++ b/module/bug/view/report.html.php @@ -1,62 +1,62 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
-
bug->report->common;?>
-
goback); ?>
-
- - - - - - - -
-
bug->report->select;?>
-
- - bug->report->charts, $checkedCharts);?> - - -

- bug->report->create);?> -
-
- - - $chartContent):?> - - - - - -
bug->report->common;?>
- - - - - - - $data):?> - - - - - - -
report->item;?>report->value;?>report->percent;?>
name;?>value;?>percent * 100) . '%';?>
-
-
- - + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
bug->report->common;?>
+
goback); ?>
+
+ + + + + + + +
+
bug->report->select;?>
+
+ + bug->report->charts, $checkedCharts);?> + + +

+ bug->report->create);?> +
+
+ + + $chartContent):?> + + + + + +
bug->report->common;?>
+ + + + + + + $data):?> + + + + + + +
report->item;?>report->value;?>report->percent;?>
name;?>value;?>percent * 100) . '%';?>
+
+
+ + diff --git a/module/bug/view/resolve.html.php b/module/bug/view/resolve.html.php index 7c88839050..1ff035e6a9 100644 --- a/module/bug/view/resolve.html.php +++ b/module/bug/view/resolve.html.php @@ -1,47 +1,47 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
title;?>
bug->resolution;?>bug->resolutionList['tostory']); echo html::select('resolution', $lang->bug->resolutionList, '', 'class=select-3 onchange=setDuplicate(this.value)');?>
bug->resolvedBuild;?>
bug->assignedTo;?>openedBy, 'class=select-3');?>
comment;?>
- - -
- -
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
title;?>
bug->resolution;?>bug->resolutionList['tostory']); echo html::select('resolution', $lang->bug->resolutionList, '', 'class=select-3 onchange=setDuplicate(this.value)');?>
bug->resolvedBuild;?>
bug->assignedTo;?>openedBy, 'class=select-3');?>
comment;?>
+ + +
+ +
+ diff --git a/module/bug/view/sendmail.html.php b/module/bug/view/sendmail.html.php index 818dac4c56..e5cb9603e3 100644 --- a/module/bug/view/sendmail.html.php +++ b/module/bug/view/sendmail.html.php @@ -1,22 +1,22 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
- BUG #id . "=>$bug->assignedTo " . html::a(common::getSysURL() . $this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?> -
+ + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
+ BUG #id . "=>$bug->assignedTo " . html::a(common::getSysURL() . $this->createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?> +
diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index 5e8c83fae6..4705920f2c 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -1,272 +1,272 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
-
deleted) echo "class='deleted'";?>>BUG #id . $lang->colon . $bug->title;?>
-
- session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product"); - $params = "bugID=$bug->id"; - $copyParams = "productID=$productID&extras=bugID=$bug->id"; - $convertParams = "productID=$productID&moduleID=0&from=bug&bugID=$bug->id"; - if(!$bug->deleted) - { - if(!($bug->status == 'active' and $bug->confirmed == 0 and common::printLink('bug', 'confirmBug', $params, $lang->bug->buttonConfirm))) echo $lang->bug->buttonConfirm . ' '; - if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; - common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); - if(common::hasPriv('bug', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; - if(!(($bug->status == 'closed' or $bug->status == 'resolved') and $bug->resolution != 'tostory' and common::printLink('bug', 'activate', $params, $lang->bug->buttonActivate))) echo $lang->bug->buttonActivate . ' '; - common::printLink('bug', 'create', $copyParams, $lang->bug->buttonCopy); - if($bug->status == 'active' and common::hasPriv('story', 'create')) - { - common::printLink('story', 'create', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $lang->bug->toStory) . ' '; - } - else - { - echo $lang->bug->toStory . ' '; - } - common::printLink('testcase', 'create', $convertParams, $lang->bug->buttonCreateTestcase); - common::printLink('bug', 'delete', $params, $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
-
- - - - - - - -
-
- bug->legendSteps;?> -
[', '

[', $bug->steps);?>

-
- fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?> - -
- deleted) - { - if(!($bug->status == 'active' and $bug->confirmed == 0 and common::printLink('bug', 'confirmBug', $params, $lang->bug->buttonConfirm))) echo $lang->bug->buttonConfirm . ' '; - if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; - common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); - if(common::hasPriv('bug', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; - if(!(($bug->status == 'closed' or $bug->status == 'resolved') and $bug->resolution != 'tostory' and common::printLink('bug', 'activate', $params, $lang->bug->buttonActivate))) echo $lang->bug->buttonActivate . ' '; - common::printLink('bug', 'create', $copyParams, $lang->bug->buttonCopy); - if($bug->status == 'active' and common::hasPriv('bug', 'resolve')) - { - common::printLink('story', 'create', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $lang->bug->toStory) . ' '; - } - else - { - echo $lang->bug->toStory . ' '; - } - common::printLink('testcase', 'create', $convertParams, $lang->bug->buttonCreateTestcase); - common::printLink('bug', 'delete', $params, $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
- -
-
- bug->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bug->product;?>product", $productName)) echo $productName;?> -
bug->module;?> - $module) - { - if(!common::printLink('bug', 'browse', "productID=$bug->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; - if(isset($modulePath[$key + 1])) echo $lang->arrow; - } - ?> -
bug->type;?>bug->typeList[$bug->type])) echo $lang->bug->typeList[$bug->type]; else echo $bug->type;?>
bug->severity;?>bug->severityList[$bug->severity];?>
bug->pri;?>bug->priList[$bug->pri];?>
bug->status;?>bug->statusList[$bug->status];?>
bug->activatedCount;?>activatedCount;?>
bug->confirmed;?>bug->confirmedList[$bug->confirmed];?>
bug->lblAssignedTo;?>assignedTo) echo $users[$bug->assignedTo] . $lang->at . $bug->assignedDate;?>
bug->os;?>bug->osList[$bug->os];?>
bug->browser;?>bug->browserList[$bug->browser];?>
bug->keywords;?>keywords;?>
-
-
- bug->legendLife;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bug->openedBy;?> openedBy] . $lang->at . $bug->openedDate;?>
bug->openedBuild;?> - openedBuild) - { - $openedBuilds = explode(',', $bug->openedBuild); - foreach($openedBuilds as $openedBuild) isset($builds[$openedBuild]) ? print($builds[$openedBuild] . '
') : print($openedBuild . '
'); - } - else - { - echo $bug->openedBuild; - } - ?> -
bug->lblResolved;?>resolvedBy) echo $users[$bug->resolvedBy] . $lang->at . $bug->resolvedDate;?> -
bug->resolvedBuild;?>resolvedBuild])) echo $builds[$bug->resolvedBuild]; else echo $bug->resolvedBuild;?>
bug->resolution;?> - bug->resolutionList[$bug->resolution]; - if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug"), $bug->duplicateBugTitle); - ?> -
bug->closedBy;?>closedBy) echo $users[$bug->closedBy] . $lang->at . $bug->closedDate;?>
bug->lblLastEdited;?>lastEditedBy) echo $users[$bug->lastEditedBy] . $lang->at . $bug->lastEditedDate?>
-
- -
- bug->legendPrjStoryTask;?> - - - - - - - - - - - - - -
bug->project;?>project) echo html::a($this->createLink('project', 'browse', "projectid=$bug->project"), $bug->projectName);?>
bug->story;?> - story) echo html::a($this->createLink('story', 'view', "storyID=$bug->story"), $bug->storyTitle); - if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion) - { - echo "({$lang->story->changed} "; - echo html::a($this->createLink('bug', 'confirmStoryChange', "bugID=$bug->id"), $lang->confirm, 'hiddenwin'); - echo ")"; - } - ?> -
bug->task;?>task) echo html::a($this->createLink('task', 'view', "taskID=$bug->task"), $bug->taskName);?>
-
-
- bug->legendMisc;?> - - - - - - - - - - - - - - - - - - - - - -
bug->mailto;?>mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
bug->linkBug;?> - linkBugTitles)) - { - foreach($bug->linkBugTitles as $linkBugID => $linkBugTitle) - { - echo html::a($this->createLink('bug', 'view', "bugID=$linkBugID"), "#$linkBugID $linkBugTitle", '_blank') . '
'; - } - } - ?> -
bug->case;?>caseTitle)) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?>
bug->toStory;?>toStory != 0) echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?>
bug->toTask;?>toTask != 0) echo html::a($this->createLink('bug', 'view', "bugID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
-
-
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
deleted) echo "class='deleted'";?>>BUG #id . $lang->colon . $bug->title;?>
+
+ session->bugList != false ? $app->session->bugList : inlink('browse', "productID=$bug->product"); + $params = "bugID=$bug->id"; + $copyParams = "productID=$productID&extras=bugID=$bug->id"; + $convertParams = "productID=$productID&moduleID=0&from=bug&bugID=$bug->id"; + if(!$bug->deleted) + { + if(!($bug->status == 'active' and $bug->confirmed == 0 and common::printLink('bug', 'confirmBug', $params, $lang->bug->buttonConfirm))) echo $lang->bug->buttonConfirm . ' '; + if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; + common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); + if(common::hasPriv('bug', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; + if(!(($bug->status == 'closed' or $bug->status == 'resolved') and $bug->resolution != 'tostory' and common::printLink('bug', 'activate', $params, $lang->bug->buttonActivate))) echo $lang->bug->buttonActivate . ' '; + common::printLink('bug', 'create', $copyParams, $lang->bug->buttonCopy); + if($bug->status == 'active' and common::hasPriv('story', 'create')) + { + common::printLink('story', 'create', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $lang->bug->toStory) . ' '; + } + else + { + echo $lang->bug->toStory . ' '; + } + common::printLink('testcase', 'create', $convertParams, $lang->bug->buttonCreateTestcase); + common::printLink('bug', 'delete', $params, $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
+
+ + + + + + + +
+
+ bug->legendSteps;?> +
[', '

[', $bug->steps);?>

+
+ fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?> + +
+ deleted) + { + if(!($bug->status == 'active' and $bug->confirmed == 0 and common::printLink('bug', 'confirmBug', $params, $lang->bug->buttonConfirm))) echo $lang->bug->buttonConfirm . ' '; + if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; + common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); + if(common::hasPriv('bug', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; + if(!(($bug->status == 'closed' or $bug->status == 'resolved') and $bug->resolution != 'tostory' and common::printLink('bug', 'activate', $params, $lang->bug->buttonActivate))) echo $lang->bug->buttonActivate . ' '; + common::printLink('bug', 'create', $copyParams, $lang->bug->buttonCopy); + if($bug->status == 'active' and common::hasPriv('bug', 'resolve')) + { + common::printLink('story', 'create', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $lang->bug->toStory) . ' '; + } + else + { + echo $lang->bug->toStory . ' '; + } + common::printLink('testcase', 'create', $convertParams, $lang->bug->buttonCreateTestcase); + common::printLink('bug', 'delete', $params, $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
+ +
+
+ bug->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bug->product;?>product", $productName)) echo $productName;?> +
bug->module;?> + $module) + { + if(!common::printLink('bug', 'browse', "productID=$bug->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; + if(isset($modulePath[$key + 1])) echo $lang->arrow; + } + ?> +
bug->type;?>bug->typeList[$bug->type])) echo $lang->bug->typeList[$bug->type]; else echo $bug->type;?>
bug->severity;?>bug->severityList[$bug->severity];?>
bug->pri;?>bug->priList[$bug->pri];?>
bug->status;?>bug->statusList[$bug->status];?>
bug->activatedCount;?>activatedCount;?>
bug->confirmed;?>bug->confirmedList[$bug->confirmed];?>
bug->lblAssignedTo;?>assignedTo) echo $users[$bug->assignedTo] . $lang->at . $bug->assignedDate;?>
bug->os;?>bug->osList[$bug->os];?>
bug->browser;?>bug->browserList[$bug->browser];?>
bug->keywords;?>keywords;?>
+
+
+ bug->legendLife;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bug->openedBy;?> openedBy] . $lang->at . $bug->openedDate;?>
bug->openedBuild;?> + openedBuild) + { + $openedBuilds = explode(',', $bug->openedBuild); + foreach($openedBuilds as $openedBuild) isset($builds[$openedBuild]) ? print($builds[$openedBuild] . '
') : print($openedBuild . '
'); + } + else + { + echo $bug->openedBuild; + } + ?> +
bug->lblResolved;?>resolvedBy) echo $users[$bug->resolvedBy] . $lang->at . $bug->resolvedDate;?> +
bug->resolvedBuild;?>resolvedBuild])) echo $builds[$bug->resolvedBuild]; else echo $bug->resolvedBuild;?>
bug->resolution;?> + bug->resolutionList[$bug->resolution]; + if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug"), $bug->duplicateBugTitle); + ?> +
bug->closedBy;?>closedBy) echo $users[$bug->closedBy] . $lang->at . $bug->closedDate;?>
bug->lblLastEdited;?>lastEditedBy) echo $users[$bug->lastEditedBy] . $lang->at . $bug->lastEditedDate?>
+
+ +
+ bug->legendPrjStoryTask;?> + + + + + + + + + + + + + +
bug->project;?>project) echo html::a($this->createLink('project', 'browse', "projectid=$bug->project"), $bug->projectName);?>
bug->story;?> + story) echo html::a($this->createLink('story', 'view', "storyID=$bug->story"), $bug->storyTitle); + if($bug->storyStatus == 'active' and $bug->latestStoryVersion > $bug->storyVersion) + { + echo "({$lang->story->changed} "; + echo html::a($this->createLink('bug', 'confirmStoryChange', "bugID=$bug->id"), $lang->confirm, 'hiddenwin'); + echo ")"; + } + ?> +
bug->task;?>task) echo html::a($this->createLink('task', 'view', "taskID=$bug->task"), $bug->taskName);?>
+
+
+ bug->legendMisc;?> + + + + + + + + + + + + + + + + + + + + + +
bug->mailto;?>mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
bug->linkBug;?> + linkBugTitles)) + { + foreach($bug->linkBugTitles as $linkBugID => $linkBugTitle) + { + echo html::a($this->createLink('bug', 'view', "bugID=$linkBugID"), "#$linkBugID $linkBugTitle", '_blank') . '
'; + } + } + ?> +
bug->case;?>caseTitle)) echo html::a($this->createLink('testcase', 'view', "caseID=$bug->case"), "#$bug->case $bug->caseTitle", '_blank');?>
bug->toStory;?>toStory != 0) echo html::a($this->createLink('story', 'view', "storyID=$bug->toStory"), "#$bug->toStory $bug->toStoryTitle", '_blank');?>
bug->toTask;?>toTask != 0) echo html::a($this->createLink('bug', 'view', "bugID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
+
+
+ diff --git a/module/build/control.php b/module/build/control.php index 8bd52d35d2..0f06d9560a 100644 --- a/module/build/control.php +++ b/module/build/control.php @@ -1,186 +1,186 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -class build extends control -{ - /** - * Create a buld. - * - * @param int $projectID - * @access public - * @return void - */ - public function create($projectID) - { - if(!empty($_POST)) - { - $buildID = $this->build->create($projectID); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('build', $buildID, 'opened'); - die(js::locate($this->createLink('project', 'build', "project=$projectID"), 'parent')); - } - - /* Load these models. */ - $this->loadModel('story'); - $this->loadModel('bug'); - $this->loadModel('task'); - $this->loadModel('project'); - $this->loadModel('user'); - - /* Set menu. */ - $this->project->setMenu($this->project->getPairs(), $projectID); - - /* Get stories and bugs. */ - $orderBy = 'status_asc, stage_asc, id_desc'; - $stories = $this->story->getProjectStories($projectID, $orderBy); - $bugs = $this->project->getResolvedBugs($projectID); - - /* Assign. */ - $this->view->header->title = $this->lang->build->create; - $this->view->products = $this->project->getProducts($projectID); - $this->view->projectID = $projectID; - $this->view->users = $this->user->getPairs(); - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->orderBy = $orderBy; - $this->display(); - } - - /** - * Edit a build. - * - * @param int $buildID - * @access public - * @return void - */ - public function edit($buildID) - { - if(!empty($_POST)) - { - $changes = $this->build->update($buildID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('build', $buildID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "buildID=$buildID"), 'parent')); - } - - $this->loadModel('story'); - $this->loadModel('bug'); - $this->loadModel('project'); - - /* Set menu. */ - $build = $this->build->getById((int)$buildID); - $this->project->setMenu($this->project->getPairs(), $build->project); - - /* Get stories and bugs. */ - $orderBy = 'status_asc, stage_asc, id_desc'; - $stories = $this->story->getProjectStories($build->project, $orderBy); - $bugs = $this->project->getResolvedBugs($build->project); - - /* Assign. */ - $this->view->header->title = $this->lang->build->edit; - $this->view->position[] = $this->lang->build->edit; - $this->view->products = $this->project->getProducts($build->project); - $this->view->users = $this->loadModel('user')->getPairs(); - $this->view->build = $build; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->orderBy = $orderBy; - $this->display(); - } - - /** - * View a build. - * - * @param int $buildID - * @access public - * @return void - */ - public function view($buildID) - { - $this->loadModel('story'); - $this->loadModel('bug'); - - /* Set menu. */ - $build = $this->build->getById((int)$buildID); - if(!$build) die(js::error($this->lang->notFound) . js::locate('back')); - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll(); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll(); - - $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project); - - /* Assign. */ - $this->view->header->title = $this->lang->build->view; - $this->view->position[] = $this->lang->build->view; - $this->view->products = $this->project->getProducts($build->project); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->build = $build; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->actions = $this->loadModel('action')->getList('build', $buildID); - $this->display(); - } - - /** - * Delete a build. - * - * @param int $buildID - * @param string $confirm yes|noe - * @access public - * @return void - */ - public function delete($buildID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes"))); - } - else - { - $build = $this->build->getById($buildID); - $this->build->delete(TABLE_BUILD, $buildID); - die(js::locate($this->createLink('project', 'build', "projectID=$build->project"), 'parent')); - } - } - - /** - * AJAX: get builds of a product in html select. - * - * @param int $productID - * @param string $varName the name of the select object to create - * @param string $build build to selected - * @access public - * @return string - */ - public function ajaxGetProductBuilds($productID, $varName, $build = '') - { - if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'size=4 class=select-3 multiple')); - if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'class=select-3')); - } - - /** - * AJAX: get builds of a project in html select. - * - * @param int $projectID - * @param string $varName the name of the select object to create - * @param string $build build to selected - * @access public - * @return string - */ - public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '') - { - if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'size=4 class=select-3 multiple')); - if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3')); - } -} + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +class build extends control +{ + /** + * Create a buld. + * + * @param int $projectID + * @access public + * @return void + */ + public function create($projectID) + { + if(!empty($_POST)) + { + $buildID = $this->build->create($projectID); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('build', $buildID, 'opened'); + die(js::locate($this->createLink('project', 'build', "project=$projectID"), 'parent')); + } + + /* Load these models. */ + $this->loadModel('story'); + $this->loadModel('bug'); + $this->loadModel('task'); + $this->loadModel('project'); + $this->loadModel('user'); + + /* Set menu. */ + $this->project->setMenu($this->project->getPairs(), $projectID); + + /* Get stories and bugs. */ + $orderBy = 'status_asc, stage_asc, id_desc'; + $stories = $this->story->getProjectStories($projectID, $orderBy); + $bugs = $this->project->getResolvedBugs($projectID); + + /* Assign. */ + $this->view->header->title = $this->lang->build->create; + $this->view->products = $this->project->getProducts($projectID); + $this->view->projectID = $projectID; + $this->view->users = $this->user->getPairs(); + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->orderBy = $orderBy; + $this->display(); + } + + /** + * Edit a build. + * + * @param int $buildID + * @access public + * @return void + */ + public function edit($buildID) + { + if(!empty($_POST)) + { + $changes = $this->build->update($buildID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('build', $buildID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "buildID=$buildID"), 'parent')); + } + + $this->loadModel('story'); + $this->loadModel('bug'); + $this->loadModel('project'); + + /* Set menu. */ + $build = $this->build->getById((int)$buildID); + $this->project->setMenu($this->project->getPairs(), $build->project); + + /* Get stories and bugs. */ + $orderBy = 'status_asc, stage_asc, id_desc'; + $stories = $this->story->getProjectStories($build->project, $orderBy); + $bugs = $this->project->getResolvedBugs($build->project); + + /* Assign. */ + $this->view->header->title = $this->lang->build->edit; + $this->view->position[] = $this->lang->build->edit; + $this->view->products = $this->project->getProducts($build->project); + $this->view->users = $this->loadModel('user')->getPairs(); + $this->view->build = $build; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->orderBy = $orderBy; + $this->display(); + } + + /** + * View a build. + * + * @param int $buildID + * @access public + * @return void + */ + public function view($buildID) + { + $this->loadModel('story'); + $this->loadModel('bug'); + + /* Set menu. */ + $build = $this->build->getById((int)$buildID); + if(!$build) die(js::error($this->lang->notFound) . js::locate('back')); + $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll(); + $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll(); + + $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project); + + /* Assign. */ + $this->view->header->title = $this->lang->build->view; + $this->view->position[] = $this->lang->build->view; + $this->view->products = $this->project->getProducts($build->project); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->build = $build; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->actions = $this->loadModel('action')->getList('build', $buildID); + $this->display(); + } + + /** + * Delete a build. + * + * @param int $buildID + * @param string $confirm yes|noe + * @access public + * @return void + */ + public function delete($buildID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->build->confirmDelete, $this->createLink('build', 'delete', "buildID=$buildID&confirm=yes"))); + } + else + { + $build = $this->build->getById($buildID); + $this->build->delete(TABLE_BUILD, $buildID); + die(js::locate($this->createLink('project', 'build', "projectID=$build->project"), 'parent')); + } + } + + /** + * AJAX: get builds of a product in html select. + * + * @param int $productID + * @param string $varName the name of the select object to create + * @param string $build build to selected + * @access public + * @return string + */ + public function ajaxGetProductBuilds($productID, $varName, $build = '') + { + if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'size=4 class=select-3 multiple')); + if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProductBuildPairs($productID, 'noempty'), $build, 'class=select-3')); + } + + /** + * AJAX: get builds of a project in html select. + * + * @param int $projectID + * @param string $varName the name of the select object to create + * @param string $build build to selected + * @access public + * @return string + */ + public function ajaxGetProjectBuilds($projectID, $productID, $varName, $build = '') + { + if($varName == 'openedBuild') die(html::select($varName . '[]', $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'size=4 class=select-3 multiple')); + if($varName == 'resolvedBuild') die(html::select($varName, $this->build->getProjectBuildPairs($projectID, $productID, 'noempty'), $build, 'class=select-3')); + } +} diff --git a/module/build/lang/en.php b/module/build/lang/en.php index a2b8b6e998..2ab6393426 100644 --- a/module/build/lang/en.php +++ b/module/build/lang/en.php @@ -1,35 +1,35 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->build->common = 'Build'; -$lang->build->create = "Create"; -$lang->build->edit = "Edit"; -$lang->build->delete = "Delete"; -$lang->build->view = "Info"; -$lang->build->ajaxGetProductBuilds = 'API:Product builds'; -$lang->build->ajaxGetProjectBuilds = 'API:Project builds'; - -$lang->build->confirmDelete = "Are sure to delete this build?"; - -$lang->build->id = 'ID'; -$lang->build->product = 'Product'; -$lang->build->project = 'Project'; -$lang->build->name = 'Name'; -$lang->build->date = 'Build date'; -$lang->build->builder = 'Builder'; -$lang->build->scmPath = 'Source code path'; -$lang->build->filePath = 'Package file path'; -$lang->build->desc = 'Desc'; -$lang->build->linkStoriesAndBugs = 'stories and bugs'; -$lang->build->linkStories = 'Stories'; -$lang->build->linkBugs = 'Bugs'; -$lang->build->stories = 'Linked stories'; -$lang->build->bugs = 'Linked bugs'; + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->build->common = 'Build'; +$lang->build->create = "Create"; +$lang->build->edit = "Edit"; +$lang->build->delete = "Delete"; +$lang->build->view = "Info"; +$lang->build->ajaxGetProductBuilds = 'API:Product builds'; +$lang->build->ajaxGetProjectBuilds = 'API:Project builds'; + +$lang->build->confirmDelete = "Are sure to delete this build?"; + +$lang->build->id = 'ID'; +$lang->build->product = 'Product'; +$lang->build->project = 'Project'; +$lang->build->name = 'Name'; +$lang->build->date = 'Build date'; +$lang->build->builder = 'Builder'; +$lang->build->scmPath = 'Source code path'; +$lang->build->filePath = 'Package file path'; +$lang->build->desc = 'Desc'; +$lang->build->linkStoriesAndBugs = 'stories and bugs'; +$lang->build->linkStories = 'Stories'; +$lang->build->linkBugs = 'Bugs'; +$lang->build->stories = 'Linked stories'; +$lang->build->bugs = 'Linked bugs'; diff --git a/module/build/lang/zh-cn.php b/module/build/lang/zh-cn.php index 94923144f5..91e7c9483a 100644 --- a/module/build/lang/zh-cn.php +++ b/module/build/lang/zh-cn.php @@ -1,35 +1,35 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->build->common = 'Build'; -$lang->build->create = "创建Build"; -$lang->build->edit = "编辑Build"; -$lang->build->delete = "删除Build"; -$lang->build->view = "Build详情"; -$lang->build->ajaxGetProductBuilds = '接口:产品Build列表'; -$lang->build->ajaxGetProjectBuilds = '接口:项目Build列表'; - -$lang->build->confirmDelete = "您确认删除该build吗?"; - -$lang->build->id = 'ID'; -$lang->build->product = '产品'; -$lang->build->project = '项目'; -$lang->build->name = '名称编号'; -$lang->build->date = 'Build日期'; -$lang->build->builder = '构建者'; -$lang->build->scmPath = '源代码地址'; -$lang->build->filePath = '存储地址'; -$lang->build->desc = '描述'; -$lang->build->linkStoriesAndBugs = '关联需求和Bug'; -$lang->build->linkStories = '相关需求'; -$lang->build->linkBugs = '相关Bug'; -$lang->build->stories = '已关联需求'; -$lang->build->bugs = '已关联Bug'; + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->build->common = 'Build'; +$lang->build->create = "创建Build"; +$lang->build->edit = "编辑Build"; +$lang->build->delete = "删除Build"; +$lang->build->view = "Build详情"; +$lang->build->ajaxGetProductBuilds = '接口:产品Build列表'; +$lang->build->ajaxGetProjectBuilds = '接口:项目Build列表'; + +$lang->build->confirmDelete = "您确认删除该build吗?"; + +$lang->build->id = 'ID'; +$lang->build->product = '产品'; +$lang->build->project = '项目'; +$lang->build->name = '名称编号'; +$lang->build->date = 'Build日期'; +$lang->build->builder = '构建者'; +$lang->build->scmPath = '源代码地址'; +$lang->build->filePath = '存储地址'; +$lang->build->desc = '描述'; +$lang->build->linkStoriesAndBugs = '关联需求和Bug'; +$lang->build->linkStories = '相关需求'; +$lang->build->linkBugs = '相关Bug'; +$lang->build->stories = '已关联需求'; +$lang->build->bugs = '已关联Bug'; diff --git a/module/build/lang/zh-tw.php b/module/build/lang/zh-tw.php index 05136eaa55..a7830c1a9f 100644 --- a/module/build/lang/zh-tw.php +++ b/module/build/lang/zh-tw.php @@ -1,35 +1,35 @@ - - * @package build - * @version $Id: zh-tw.php 2527 2012-01-04 00:16:23Z wwccss $ - * @link http://www.zentao.net - */ -$lang->build->common = 'Build'; -$lang->build->create = "創建Build"; -$lang->build->edit = "編輯Build"; -$lang->build->delete = "刪除Build"; -$lang->build->view = "Build詳情"; -$lang->build->ajaxGetProductBuilds = '介面:產品Build列表'; -$lang->build->ajaxGetProjectBuilds = '介面:項目Build列表'; - -$lang->build->confirmDelete = "您確認刪除該build嗎?"; - -$lang->build->id = 'ID'; -$lang->build->product = '產品'; -$lang->build->project = '項目'; -$lang->build->name = '名稱編號'; -$lang->build->date = 'Build日期'; -$lang->build->builder = '構建者'; -$lang->build->scmPath = '原始碼地址'; -$lang->build->filePath = '存儲地址'; -$lang->build->desc = '描述'; -$lang->build->linkStoriesAndBugs = '關聯需求和Bug'; -$lang->build->linkStories = '相關需求'; -$lang->build->linkBugs = '相關Bug'; -$lang->build->stories = '已關聯需求'; -$lang->build->bugs = '已關聯Bug'; + + * @package build + * @version $Id: zh-tw.php 2527 2012-01-04 00:16:23Z wwccss $ + * @link http://www.zentao.net + */ +$lang->build->common = 'Build'; +$lang->build->create = "創建Build"; +$lang->build->edit = "編輯Build"; +$lang->build->delete = "刪除Build"; +$lang->build->view = "Build詳情"; +$lang->build->ajaxGetProductBuilds = '介面:產品Build列表'; +$lang->build->ajaxGetProjectBuilds = '介面:項目Build列表'; + +$lang->build->confirmDelete = "您確認刪除該build嗎?"; + +$lang->build->id = 'ID'; +$lang->build->product = '產品'; +$lang->build->project = '項目'; +$lang->build->name = '名稱編號'; +$lang->build->date = 'Build日期'; +$lang->build->builder = '構建者'; +$lang->build->scmPath = '原始碼地址'; +$lang->build->filePath = '存儲地址'; +$lang->build->desc = '描述'; +$lang->build->linkStoriesAndBugs = '關聯需求和Bug'; +$lang->build->linkStories = '相關需求'; +$lang->build->linkBugs = '相關Bug'; +$lang->build->stories = '已關聯需求'; +$lang->build->bugs = '已關聯Bug'; diff --git a/module/build/model.php b/module/build/model.php index e0027f909b..7d16a89d8f 100644 --- a/module/build/model.php +++ b/module/build/model.php @@ -1,152 +1,152 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->select('t1.*, t2.name as projectName, t3.name as productName') - ->from(TABLE_BUILD)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') - ->where('t1.id')->eq((int)$buildID) - ->orderBy('t1.id DESC') - ->fetch(); - if(!$build) return false; - $build->desc = $this->loadModel('file')->setImgSize($build->desc); - return $build; - } - - /** - * Get builds of a project. - * - * @param int $projectID - * @access public - * @return array - */ - public function getProjectBuilds($projectID) - { - return $this->dao->select('t1.*, t2.name as projectName, t3.name as productName') - ->from(TABLE_BUILD)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy('t1.date DESC, t1.id desc') - ->fetchAll(); - } - - /** - * Get builds of a project in pairs. - * - * @param int $projectID - * @param int $productID - * @param string $params noempty|notrunk, can be a set of them - * @access public - * @return array - */ - public function getProjectBuildPairs($projectID, $productID, $params = '') - { - $sysBuilds = array(); - if(strpos($params, 'noempty') === false) $sysBuilds = array('' => ''); - if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk'); - - $builds = $this->dao->select('id,name')->from(TABLE_BUILD) - ->where('project')->eq((int)$projectID) - ->beginIF($productID)->andWhere('product')->eq((int)$productID)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy('date desc, id desc')->fetchPairs(); - if(!$builds) return $sysBuilds; - $releases = $this->dao->select('build,name')->from(TABLE_RELEASE) - ->where('build')->in(array_keys($builds)) - ->andWhere('deleted')->eq(0) - ->fetchPairs(); - foreach($releases as $buildID => $releaseName) $builds[$buildID] = $releaseName; - return $sysBuilds + $builds; - } - - /** - * Get builds of a product in pairs. - * - * @param int $productID - * @param string $params noempty|notrunk, can be a set of them - * @access public - * @return string - */ - public function getProductBuildPairs($productID, $params = '') - { - $sysBuilds = array(); - if(strpos($params, 'noempty') === false) $sysBuilds = array('' => ''); - if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk'); - - $builds = $this->dao->select('id,name')->from(TABLE_BUILD) - ->where('product')->eq((int)$productID) - ->andWhere('deleted')->eq(0) - ->orderBy('date desc, id desc')->fetchPairs(); - if(!$builds) return $sysBuilds; - return $sysBuilds + $builds; - } - - /** - * Create a build - * - * @param int $projectID - * @access public - * @return void - */ - public function create($projectID) - { - $build->stories = ''; - $build->bugs = ''; - - $build = fixer::input('post')->stripTags('name') - ->join('stories', ',') - ->join('bugs', ',') - ->add('project', (int)$projectID)->get(); - $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->batchCheck($this->config->build->create->requiredFields, 'notempty')->check('name','unique')->exec(); - if(!dao::isError()) return $this->dao->lastInsertID(); - } - - /** - * Update a build. - * - * @param int $buildID - * @access public - * @return void - */ - public function update($buildID) - { - $oldBuild = $this->getByID($buildID); - $build = fixer::input('post') - ->stripTags('name') - ->setDefault('stories', '') - ->setDefault('bugs', '') - ->join('stories', ',') - ->join('bugs', ',') - ->get(); - $this->dao->update(TABLE_BUILD)->data($build) - ->autoCheck() - ->batchCheck($this->config->build->edit->requiredFields, 'notempty') - ->where('id')->eq((int)$buildID) - ->check('name','unique', "id != $buildID") - ->exec(); - if(!dao::isError()) return common::createChanges($oldBuild, $build); - } -} + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->select('t1.*, t2.name as projectName, t3.name as productName') + ->from(TABLE_BUILD)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') + ->where('t1.id')->eq((int)$buildID) + ->orderBy('t1.id DESC') + ->fetch(); + if(!$build) return false; + $build->desc = $this->loadModel('file')->setImgSize($build->desc); + return $build; + } + + /** + * Get builds of a project. + * + * @param int $projectID + * @access public + * @return array + */ + public function getProjectBuilds($projectID) + { + return $this->dao->select('t1.*, t2.name as projectName, t3.name as productName') + ->from(TABLE_BUILD)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('t1.date DESC, t1.id desc') + ->fetchAll(); + } + + /** + * Get builds of a project in pairs. + * + * @param int $projectID + * @param int $productID + * @param string $params noempty|notrunk, can be a set of them + * @access public + * @return array + */ + public function getProjectBuildPairs($projectID, $productID, $params = '') + { + $sysBuilds = array(); + if(strpos($params, 'noempty') === false) $sysBuilds = array('' => ''); + if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk'); + + $builds = $this->dao->select('id,name')->from(TABLE_BUILD) + ->where('project')->eq((int)$projectID) + ->beginIF($productID)->andWhere('product')->eq((int)$productID)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy('date desc, id desc')->fetchPairs(); + if(!$builds) return $sysBuilds; + $releases = $this->dao->select('build,name')->from(TABLE_RELEASE) + ->where('build')->in(array_keys($builds)) + ->andWhere('deleted')->eq(0) + ->fetchPairs(); + foreach($releases as $buildID => $releaseName) $builds[$buildID] = $releaseName; + return $sysBuilds + $builds; + } + + /** + * Get builds of a product in pairs. + * + * @param int $productID + * @param string $params noempty|notrunk, can be a set of them + * @access public + * @return string + */ + public function getProductBuildPairs($productID, $params = '') + { + $sysBuilds = array(); + if(strpos($params, 'noempty') === false) $sysBuilds = array('' => ''); + if(strpos($params, 'notrunk') === false) $sysBuilds = $sysBuilds + array('trunk' => 'Trunk'); + + $builds = $this->dao->select('id,name')->from(TABLE_BUILD) + ->where('product')->eq((int)$productID) + ->andWhere('deleted')->eq(0) + ->orderBy('date desc, id desc')->fetchPairs(); + if(!$builds) return $sysBuilds; + return $sysBuilds + $builds; + } + + /** + * Create a build + * + * @param int $projectID + * @access public + * @return void + */ + public function create($projectID) + { + $build->stories = ''; + $build->bugs = ''; + + $build = fixer::input('post')->stripTags('name') + ->join('stories', ',') + ->join('bugs', ',') + ->add('project', (int)$projectID)->get(); + $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->batchCheck($this->config->build->create->requiredFields, 'notempty')->check('name','unique')->exec(); + if(!dao::isError()) return $this->dao->lastInsertID(); + } + + /** + * Update a build. + * + * @param int $buildID + * @access public + * @return void + */ + public function update($buildID) + { + $oldBuild = $this->getByID($buildID); + $build = fixer::input('post') + ->stripTags('name') + ->setDefault('stories', '') + ->setDefault('bugs', '') + ->join('stories', ',') + ->join('bugs', ',') + ->get(); + $this->dao->update(TABLE_BUILD)->data($build) + ->autoCheck() + ->batchCheck($this->config->build->edit->requiredFields, 'notempty') + ->where('id')->eq((int)$buildID) + ->check('name','unique', "id != $buildID") + ->exec(); + if(!dao::isError()) return common::createChanges($oldBuild, $build); + } +} diff --git a/module/build/view/create.html.php b/module/build/view/create.html.php index 41b4bae324..7b07a201a7 100644 --- a/module/build/view/create.html.php +++ b/module/build/view/create.html.php @@ -1,97 +1,97 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
build->create;?>
build->product;?>
build->name;?>
build->builder;?>user->account, 'class="select-3"');?>
build->date;?>
build->scmPath;?>
build->filePath;?>
build->linkStoriesAndBugs;?> -
- - -
-
build->desc;?>
-
- + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
build->create;?>
build->product;?>
build->name;?>
build->builder;?>user->account, 'class="select-3"');?>
build->date;?>
build->scmPath;?>
build->filePath;?>
build->linkStoriesAndBugs;?> +
+ + +
+
build->desc;?>
+
+ diff --git a/module/build/view/edit.html.php b/module/build/view/edit.html.php index 2e10bd353e..07e35e236e 100644 --- a/module/build/view/edit.html.php +++ b/module/build/view/edit.html.php @@ -1,97 +1,97 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
build->edit;?>
build->product;?>product, "class='select-3'");?>
build->name;?>name, "class='text-3'");?>
build->builder;?>builder, 'class="select-3"');?>
build->date;?>date, "class='text-3 date'");?>
build->scmPath;?>scmPath, "class='text-1'");?>
build->filePath;?>filePath, "class='text-1'");?>
build->linkStoriesAndBugs;?> -
- - -
-
build->desc;?>desc), "rows='15' class='area-1'");?>
project);?>
-
- + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
build->edit;?>
build->product;?>product, "class='select-3'");?>
build->name;?>name, "class='text-3'");?>
build->builder;?>builder, 'class="select-3"');?>
build->date;?>date, "class='text-3 date'");?>
build->scmPath;?>scmPath, "class='text-1'");?>
build->filePath;?>filePath, "class='text-1'");?>
build->linkStoriesAndBugs;?> +
+ + +
+
build->desc;?>desc), "rows='15' class='area-1'");?>
project);?>
+
+ diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php index c8d94831f1..655d30cfc5 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -1,117 +1,117 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
build->view;?>
build->product;?>productName;?>
build->name;?>'>name;?>
build->builder;?>builder];?>
build->date;?>date;?>
build->scmPath;?>scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>
build->filePath;?>filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>
build->stories;?> -
- - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - - - - -
idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
id);?>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
-
-
build->bugs;?> -
- - - - - - - - - - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - - - - - -
idAB;?>bug->title;?>bug->status;?>openedByAB;?>bug->openedDateAB;?>bug->resolvedByAB;?>bug->resolvedDateAB;?>
id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>openedBy];?>openedDate, 5, 11)?>resolvedBy];?>resolvedDate, 5, 11)?>
-
-
build->desc;?>desc;?>
-
- session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project"); - if(!$build->deleted) - { - common::printLink('build', 'edit', "buildID=$build->id", $lang->edit); - common::printLink('build', 'delete', "buildID=$build->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
- - + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
build->view;?>
build->product;?>productName;?>
build->name;?>'>name;?>
build->builder;?>builder];?>
build->date;?>date;?>
build->scmPath;?>scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>
build->filePath;?>filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>
build->stories;?> +
+ + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + + + + +
idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
id);?>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
+
+
build->bugs;?> +
+ + + + + + + + + + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + + + + + +
idAB;?>bug->title;?>bug->status;?>openedByAB;?>bug->openedDateAB;?>bug->resolvedByAB;?>bug->resolvedDateAB;?>
id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>openedBy];?>openedDate, 5, 11)?>resolvedBy];?>resolvedDate, 5, 11)?>
+
+
build->desc;?>desc;?>
+
+ session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project"); + if(!$build->deleted) + { + common::printLink('build', 'edit', "buildID=$build->id", $lang->edit); + common::printLink('build', 'delete', "buildID=$build->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
+ + diff --git a/module/common/control.php b/module/common/control.php index 4ba1032672..be741fbee2 100644 --- a/module/common/control.php +++ b/module/common/control.php @@ -1,265 +1,265 @@ - - * @package common - * @version $Id$ - * @link http://www.zentao.net - */ -class common extends control -{ - /** - * The construc method, to do some auto things. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->common->startSession(); - $this->common->sendHeader(); - $this->common->setCompany(); - $this->common->setUser(); - $this->app->loadLang('company'); - } - - /** - * Check the user has permission to access this method, if not, locate to the login page or deny page. - * - * @access public - * @return void - */ - public function checkPriv() - { - $module = $this->app->getModuleName(); - $method = $this->app->getMethodName(); - if($this->common->isOpenMethod($module, $method)) return true; - if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth(); - if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie(); - - if(isset($this->app->user)) - { - if(!common::hasPriv($module, $method)) $this->common->deny($module, $method); - } - else - { - $referer = helper::safe64Encode($this->app->getURI(true)); - $this->locate($this->createLink('user', 'login', "referer=$referer")); - } - } - - /** - * Check upgrade's status file is ok or not. - * - * @access public - * @return void - */ - public function checkUpgradeStatus() - { - $statusFile = $this->app->getAppRoot() . 'www' . $this->pathFix . 'ok'; - if(!file_exists($statusFile) or time() - filemtime($statusFile) > 3600) - { - $this->app->loadLang('upgrade'); - echo ""; - echo "
"; - printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile); - die('
'); - } - } - - /** - * Check the user has permisson of one method of one module. - * - * @param string $module - * @param string $method - * @static - * @access public - * @return bool - */ - public static function hasPriv($module, $method) - { - global $app; - - /* Check is the super admin or not. */ - $account = ',' . $app->user->account . ','; - if(strpos($app->company->admins, $account) !== false) return true; - - /* If not super admin, check the rights. */ - $rights = $app->user->rights; - if(isset($rights[strtolower($module)][strtolower($method)])) return true; - return false; - } - - /** - * Replace the %s of one key of a menu by $params. - * - * All the menus are defined in the common's language file. But there're many dynamic params, so in the defination, - * we used %s as placeholder. These %s should be setted in one module. - * - * The items of one module's menu may be an string or array. For example, please see module/common/lang. - * - * @param string $object the menus of one module - * @param string $key the menu item to be replaced - * @param string $params the params passed to the menu item - * @access public - * @return void - */ - public function setMenuVars($menu, $key, $params) - { - if(is_array($params)) - { - if(is_array($menu->$key)) - { - $menu->$key = (object)$menu->$key; - $menu->$key->link = vsprintf($menu->$key->link, $params); - $menu->$key = (array)$menu->$key; - } - else - { - $menu->$key = vsprintf($menu->$key, $params); - } - } - else - { - if(is_array($menu->$key)) - { - $menu->$key = (object)$menu->$key; - $menu->$key->link = sprintf($menu->$key->link, $params); - $menu->$key = (array)$menu->$key; - } - else - { - $menu->$key = sprintf($menu->$key, $params); - } - } - } - - /** - * Print the link contains orderBy field. - * - * This method will auto set the orderby param according the params. Fox example, if the order by is desc, - * will be changed to asc. - * - * @param string $fieldName the field name to sort by - * @param string $orderBy the order by string - * @param string $vars the vars to be passed - * @param string $label the label of the link - * @param string $module the module name - * @param string $method the method name - * @static - * @access public - * @return void - */ - public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '') - { - global $lang, $app; - if(empty($module)) $module= $app->getModuleName(); - if(empty($method)) $method= $app->getMethodName(); - $className = 'header'; - - if(strpos($orderBy, $fieldName) !== false) - { - if(stripos($orderBy, 'desc') !== false) - { - $orderBy = str_ireplace('desc', 'asc', $orderBy); - $className = 'headerSortUp'; - } - elseif(stripos($orderBy, 'asc') !== false) - { - $orderBy = str_ireplace('asc', 'desc', $orderBy); - $className = 'headerSortDown'; - } - } - else - { - $orderBy = $fieldName . '_' . 'asc'; - $className = 'header'; - } - $link = helper::createLink($module, $method, sprintf($vars, $orderBy)); - echo "
" . html::a($link, $label) . '
'; - } - - /** - * Print link to an modules' methd. - * - * Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true. - * - * @param string $module the module name - * @param string $method the method - * @param string $vars vars to be passed - * @param string $label the label of the link - * @param string $target the target of the link - * @param string $misc others - * @static - * @access public - * @return bool - */ - public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '') - { - if(!common::hasPriv($module, $method)) return false; - echo html::a(helper::createLink($module, $method, $vars), $label, $target, $misc); - return true; - } - - /** - * Create changes of one object. - * - * @param mixed $old the old object - * @param mixed $new the new object - * @static - * @access public - * @return array - */ - public static function createChanges($old, $new) - { - global $config; - $changes = array(); - $magicQuote = get_magic_quotes_gpc(); - foreach($new as $key => $value) - { - if(strtolower($key) == 'lastediteddate') continue; - if(strtolower($key) == 'lasteditedby') continue; - if(strtolower($key) == 'assigneddate') continue; - if(strtolower($key) == 'editedby') continue; - if(strtolower($key) == 'editeddate') continue; - - if($magicQuote) $value = stripslashes($value); - if($value != $old->$key) - { - $diff = ''; - if(substr_count($value, "\n") > 1 or substr_count($old->$key, "\n") > 1 or strpos('name,title,desc,spec,steps,content,digest', strtolower($key)) !== false) $diff = commonModel::diff($old->$key, $value); - $changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff); - } - } - return $changes; - } - - /** - * Get the full url of the system. - * - * @access public - * @return string - */ - public function getSysURL() - { - $httpType = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' ? 'https' : 'http'; - $httpHost = $_SERVER['HTTP_HOST']; - return "$httpType://$httpHost"; - } - - /** - * Print the run info. - * - * @param mixed $startTime the start time. - * @access public - * @return void - */ - public function printRunInfo($startTime) - { - vprintf($this->lang->runInfo, $this->common->getRunInfo($startTime)); - } -} + + * @package common + * @version $Id$ + * @link http://www.zentao.net + */ +class common extends control +{ + /** + * The construc method, to do some auto things. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->common->startSession(); + $this->common->sendHeader(); + $this->common->setCompany(); + $this->common->setUser(); + $this->app->loadLang('company'); + } + + /** + * Check the user has permission to access this method, if not, locate to the login page or deny page. + * + * @access public + * @return void + */ + public function checkPriv() + { + $module = $this->app->getModuleName(); + $method = $this->app->getMethodName(); + if($this->common->isOpenMethod($module, $method)) return true; + if(!$this->loadModel('user')->isLogon() and $this->server->php_auth_user) $this->user->identifyByPhpAuth(); + if(!$this->loadModel('user')->isLogon() and $this->cookie->za) $this->user->identifyByCookie(); + + if(isset($this->app->user)) + { + if(!common::hasPriv($module, $method)) $this->common->deny($module, $method); + } + else + { + $referer = helper::safe64Encode($this->app->getURI(true)); + $this->locate($this->createLink('user', 'login', "referer=$referer")); + } + } + + /** + * Check upgrade's status file is ok or not. + * + * @access public + * @return void + */ + public function checkUpgradeStatus() + { + $statusFile = $this->app->getAppRoot() . 'www' . $this->pathFix . 'ok'; + if(!file_exists($statusFile) or time() - filemtime($statusFile) > 3600) + { + $this->app->loadLang('upgrade'); + echo ""; + echo "
"; + printf($this->lang->upgrade->setStatusFile, $statusFile, $statusFile, $statusFile); + die('
'); + } + } + + /** + * Check the user has permisson of one method of one module. + * + * @param string $module + * @param string $method + * @static + * @access public + * @return bool + */ + public static function hasPriv($module, $method) + { + global $app; + + /* Check is the super admin or not. */ + $account = ',' . $app->user->account . ','; + if(strpos($app->company->admins, $account) !== false) return true; + + /* If not super admin, check the rights. */ + $rights = $app->user->rights; + if(isset($rights[strtolower($module)][strtolower($method)])) return true; + return false; + } + + /** + * Replace the %s of one key of a menu by $params. + * + * All the menus are defined in the common's language file. But there're many dynamic params, so in the defination, + * we used %s as placeholder. These %s should be setted in one module. + * + * The items of one module's menu may be an string or array. For example, please see module/common/lang. + * + * @param string $object the menus of one module + * @param string $key the menu item to be replaced + * @param string $params the params passed to the menu item + * @access public + * @return void + */ + public function setMenuVars($menu, $key, $params) + { + if(is_array($params)) + { + if(is_array($menu->$key)) + { + $menu->$key = (object)$menu->$key; + $menu->$key->link = vsprintf($menu->$key->link, $params); + $menu->$key = (array)$menu->$key; + } + else + { + $menu->$key = vsprintf($menu->$key, $params); + } + } + else + { + if(is_array($menu->$key)) + { + $menu->$key = (object)$menu->$key; + $menu->$key->link = sprintf($menu->$key->link, $params); + $menu->$key = (array)$menu->$key; + } + else + { + $menu->$key = sprintf($menu->$key, $params); + } + } + } + + /** + * Print the link contains orderBy field. + * + * This method will auto set the orderby param according the params. Fox example, if the order by is desc, + * will be changed to asc. + * + * @param string $fieldName the field name to sort by + * @param string $orderBy the order by string + * @param string $vars the vars to be passed + * @param string $label the label of the link + * @param string $module the module name + * @param string $method the method name + * @static + * @access public + * @return void + */ + public static function printOrderLink($fieldName, $orderBy, $vars, $label, $module = '', $method = '') + { + global $lang, $app; + if(empty($module)) $module= $app->getModuleName(); + if(empty($method)) $method= $app->getMethodName(); + $className = 'header'; + + if(strpos($orderBy, $fieldName) !== false) + { + if(stripos($orderBy, 'desc') !== false) + { + $orderBy = str_ireplace('desc', 'asc', $orderBy); + $className = 'headerSortUp'; + } + elseif(stripos($orderBy, 'asc') !== false) + { + $orderBy = str_ireplace('asc', 'desc', $orderBy); + $className = 'headerSortDown'; + } + } + else + { + $orderBy = $fieldName . '_' . 'asc'; + $className = 'header'; + } + $link = helper::createLink($module, $method, sprintf($vars, $orderBy)); + echo "
" . html::a($link, $label) . '
'; + } + + /** + * Print link to an modules' methd. + * + * Before printing, check the privilege first. If no privilege, return fasle. Else, print the link, return true. + * + * @param string $module the module name + * @param string $method the method + * @param string $vars vars to be passed + * @param string $label the label of the link + * @param string $target the target of the link + * @param string $misc others + * @static + * @access public + * @return bool + */ + public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '') + { + if(!common::hasPriv($module, $method)) return false; + echo html::a(helper::createLink($module, $method, $vars), $label, $target, $misc); + return true; + } + + /** + * Create changes of one object. + * + * @param mixed $old the old object + * @param mixed $new the new object + * @static + * @access public + * @return array + */ + public static function createChanges($old, $new) + { + global $config; + $changes = array(); + $magicQuote = get_magic_quotes_gpc(); + foreach($new as $key => $value) + { + if(strtolower($key) == 'lastediteddate') continue; + if(strtolower($key) == 'lasteditedby') continue; + if(strtolower($key) == 'assigneddate') continue; + if(strtolower($key) == 'editedby') continue; + if(strtolower($key) == 'editeddate') continue; + + if($magicQuote) $value = stripslashes($value); + if($value != $old->$key) + { + $diff = ''; + if(substr_count($value, "\n") > 1 or substr_count($old->$key, "\n") > 1 or strpos('name,title,desc,spec,steps,content,digest', strtolower($key)) !== false) $diff = commonModel::diff($old->$key, $value); + $changes[] = array('field' => $key, 'old' => $old->$key, 'new' => $value, 'diff' => $diff); + } + } + return $changes; + } + + /** + * Get the full url of the system. + * + * @access public + * @return string + */ + public function getSysURL() + { + $httpType = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == 'on' ? 'https' : 'http'; + $httpHost = $_SERVER['HTTP_HOST']; + return "$httpType://$httpHost"; + } + + /** + * Print the run info. + * + * @param mixed $startTime the start time. + * @access public + * @return void + */ + public function printRunInfo($startTime) + { + vprintf($this->lang->runInfo, $this->common->getRunInfo($startTime)); + } +} diff --git a/module/common/lang/en.php b/module/common/lang/en.php index d03aba5db1..dbf69f4de9 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -1,296 +1,296 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->arrow = ' » '; -$lang->colon = '::'; -$lang->comma = ','; -$lang->dot = '.'; -$lang->at = ' at '; -$lang->downArrow = '↓'; - -$lang->ZenTaoPMS = 'ZenTaoPMS'; -$lang->welcome = "Welcome to『%s』{$lang->colon} {$lang->ZenTaoPMS}"; -$lang->myControl = "Dashboard"; -$lang->currentPos = 'Current'; -$lang->logout = 'Logout'; -$lang->login = 'Login'; -$lang->aboutZenTao = 'About'; -$lang->todayIs = '%s, '; -$lang->runInfo = "
Time: %s ms, Memory: %s KB, Queries: %s.
"; - -$lang->reset = 'Reset'; -$lang->edit = 'Edit'; -$lang->copy = 'Copy'; -$lang->delete = 'Delete'; -$lang->close = 'Close'; -$lang->link = 'Link'; -$lang->unlink = 'Unlink'; -$lang->import = 'Import'; -$lang->export = 'Export'; -$lang->setFileName = 'Filename:'; -$lang->activate = 'Activate'; -$lang->submitting = 'Saving...'; -$lang->save = 'Save'; -$lang->confirm = 'Confirm'; -$lang->preview = 'View'; -$lang->goback = 'Back'; -$lang->go = 'GO'; -$lang->more = 'More'; - -$lang->actions = 'Actions'; -$lang->comment = 'Comment'; -$lang->history = 'History'; -$lang->attatch = 'Attatch'; -$lang->reverse = '[Reverse]'; -$lang->switchDisplay= '[Toggle Show]'; -$lang->switchHelp = 'Toggle Help'; -$lang->addFiles = 'Add Files'; -$lang->files = 'Files '; -$lang->unfold = '+'; -$lang->fold = '-'; - -$lang->selectAll = 'Select All'; -$lang->notFound = 'Sorry, the object not found.'; -$lang->showAll = '++ Show All ++'; -$lang->hideClosed = '-- Hide Closed--'; - -$lang->future = 'Future'; -$lang->year = 'Year'; -$lang->workingHour = 'Hour'; - -$lang->idAB = 'ID'; -$lang->priAB = 'P'; -$lang->statusAB = 'Status'; -$lang->openedByAB = 'Open'; -$lang->assignedToAB = 'To'; -$lang->typeAB = 'Type'; - -$lang->common->common = 'Common module'; - -/* The main menu. */ -$lang->menu->my = 'Dashboard|my|index'; -$lang->menu->product = 'Product|product|index'; -$lang->menu->project = 'Project|project|index'; -$lang->menu->qa = 'Test|qa|index'; -$lang->menu->doc = 'Doc|doc|index'; -$lang->menu->company = 'Company|company|index'; -$lang->menu->admin = 'Admin|admin|index'; - -/* The objects in the search box. */ -$lang->searchObjects['bug'] = 'Bug'; -$lang->searchObjects['story'] = 'Story'; -$lang->searchObjects['task'] = 'Task'; -$lang->searchObjects['testcase'] = 'Test Case'; -$lang->searchObjects['project'] = 'Project'; -$lang->searchObjects['product'] = 'Product'; -$lang->searchObjects['user'] = 'User'; -$lang->searchObjects['build'] = 'Build'; -$lang->searchObjects['release'] = 'Release'; -$lang->searchObjects['productplan'] = 'Plan'; -$lang->searchObjects['testtask'] = 'Test Task'; -$lang->searchObjects['doc'] = 'Doc'; -$lang->searchTips = 'Id here'; - -/* File type of export. */ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -/* Themes. */ -$lang->themes['default'] = 'Default'; -$lang->themes['green'] = 'Green'; -$lang->themes['red'] = 'Red'; -$lang->themes['classblue'] = 'Blue'; - -/* Index mododule menu. */ -$lang->index->menu->product = 'Products|product|browse'; -$lang->index->menu->project = 'Projects|project|browse'; - -/* Dashboard menu. */ -$lang->my->menu->account = '%s' . $lang->arrow; -$lang->my->menu->index = 'Index|my|index'; -$lang->my->menu->todo = array('link' => 'Todo|my|todo|', 'subModule' => 'todo'); -$lang->my->menu->task = 'Task|my|task|'; -$lang->my->menu->bug = 'Bug|my|bug|'; -$lang->my->menu->testtask = 'Test|my|testtask|'; -$lang->my->menu->story = 'Story|my|story|'; -$lang->my->menu->myProject = 'Project|my|project|'; -$lang->my->menu->dynamic = 'Dynamic|my|dynamic|'; -$lang->my->menu->profile = array('link' => 'Profile|my|profile|', 'alias' => 'editprofile'); -$lang->todo->menu = $lang->my->menu; - -/* Product menu. */ -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'subModule' => 'story'); -$lang->product->menu->dynamic = 'Dynamic|product|dynamic|productID=%s'; -$lang->product->menu->plan = array('link' => 'Plan|productplan|browse|productID=%s', 'subModule' => 'productplan'); -$lang->product->menu->release = array('link' => 'Release|release|browse|productID=%s', 'subModule' => 'release'); -$lang->product->menu->roadmap = 'Roadmap|product|roadmap|productID=%s'; -$lang->product->menu->doc = array('link' => 'Doc|product|doc|productID=%s', 'subModule' => 'doc'); -$lang->product->menu->view = 'Info|product|view|productID=%s'; -$lang->product->menu->edit = 'Edit|product|edit|productID=%s'; -$lang->product->menu->delete = array('link' => 'Delete|product|delete|productID=%s', 'target' => 'hiddenwin'); -$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story'; -$lang->product->menu->create = array('link' => 'New Product|product|create', 'float' => 'right'); -$lang->product->menu->project = array('link' => 'Project list|product|project|status=all&productID=%s', 'float' => 'right'); -$lang->product->menu->all = array('link' => 'All product|product|index|locate=false', 'float' => 'right'); -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* Project menu. */ -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); -$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = 'Dynamic|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = 'Testtask|project|testtask|projectID=%s'; -$lang->project->menu->burn = 'Burn|project|burn|projectID=%s'; -$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers'); -$lang->project->menu->doc = array('link' => 'Doc|project|doc|porjectID=%s', 'subModule' => 'doc'); -$lang->project->menu->product = 'Link Product|project|manageproducts|projectID=%s'; -$lang->project->menu->linkstory = array('link' => 'Link Story|project|linkstory|projectID=%s'); -$lang->project->menu->view = 'Info|project|view|projectID=%s'; -$lang->project->menu->edit = 'Edit|project|edit|projectID=%s'; -$lang->project->menu->delete = array('link' => 'Delete|project|delete|projectID=%s', 'target' => 'hiddenwin'); -$lang->project->menu->create = array('link' => 'New Project|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => 'Project list|project|index|locate=no', 'float' => 'right'); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA menu. */ -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); -$lang->bug->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); -$lang->bug->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s'); - -$lang->testcase->menu->product = '%s'; -$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testcase->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s'); - -$lang->testtask->menu->product = '%s'; -$lang->testtask->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testtask->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s'); -$lang->testtask->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -/* Doc menu. */ -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s'); -$lang->doc->menu->edit = 'Edit Library|doc|editLib|libID=%s'; -$lang->doc->menu->module = 'Modules|tree|browse|libID=%s&viewType=doc'; -$lang->doc->menu->delete = array('link' => 'Delete Library|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); -$lang->doc->menu->create = array('link' => 'New Library|doc|createLib', 'float' => 'right'); - -/* Company menu. */ -$lang->company->menu->name = '%s' . $lang->arrow; -$lang->company->menu->browseUser = array('link' => 'Users|company|browse', 'subModule' => 'user'); -$lang->company->menu->dept = array('link' => 'Department|dept|browse', 'subModule' => 'dept'); -$lang->company->menu->browseGroup = array('link' => 'Group|group|browse', 'subModule' => 'group'); -$lang->company->menu->edit = array('link' => 'Company|company|edit'); -$lang->company->menu->dynamic = 'Dynamic|company|dynamic|'; -$lang->company->menu->addGroup = array('link' => 'Add Group|group|create', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => 'Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right'); -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; - -/* User menu. */ -$lang->user->menu->account = '%s' . $lang->arrow; -$lang->user->menu->todo = array('link' => 'Todo|user|todo|account=%s', 'subModule' => 'todo'); -$lang->user->menu->task = 'Task|user|task|account=%s'; -$lang->user->menu->bug = 'Bug|user|bug|account=%s'; -$lang->user->menu->dynamic = 'Dynamic|user|dynamic|type=today&account=%s'; -$lang->user->menu->projectList = 'Project|user|project|account=%s'; -$lang->user->menu->profile = array('link' => 'Profile|user|profile|account=%s', 'alias' => 'edit'); -$lang->user->menu->browse = array('link' => 'Manage user|company|browse|', 'float' => 'right'); - -/* Admin menu. */ -$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension'); -$lang->admin->menu->editor = array('link' => 'Extension editor|editor|index', 'subModule' => 'editor'); -$lang->admin->menu->mail = array('link' => 'ConfigEmail|mail|set', 'subModule' => 'mail'); -$lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert'); -$lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action'); -$lang->convert->menu = $lang->admin->menu; -$lang->upgrade->menu = $lang->admin->menu; -$lang->action->menu = $lang->admin->menu; -$lang->extension->menu = $lang->admin->menu; -$lang->editor->menu = $lang->admin->menu; -$lang->mail->menu = $lang->admin->menu; - -/* Groups. */ -$lang->menugroup->release = 'product'; -$lang->menugroup->story = 'product'; -$lang->menugroup->productplan = 'product'; -$lang->menugroup->task = 'project'; -$lang->menugroup->build = 'project'; -$lang->menugroup->convert = 'admin'; -$lang->menugroup->upgrade = 'admin'; -$lang->menugroup->user = 'company'; -$lang->menugroup->group = 'company'; -$lang->menugroup->bug = 'qa'; -$lang->menugroup->testcase = 'qa'; -$lang->menugroup->testtask = 'qa'; -$lang->menugroup->people = 'company'; -$lang->menugroup->dept = 'company'; -$lang->menugroup->todo = 'my'; -$lang->menugroup->action = 'admin'; -$lang->menugroup->extension = 'admin'; -$lang->menugroup->editor = 'admin'; -$lang->menugroup->mail = 'admin'; - -/* Error info. */ -$lang->error->companyNotFound = "The domain %s does not exist."; -$lang->error->length = array("『%s』length should be『%s』", "『%s』length should between『%s』and 『%s』."); -$lang->error->reg = "『%s』should like『%s』"; -$lang->error->unique = "『%s』has『%s』already."; -$lang->error->gt = "『%s』must great than『%s』."; -$lang->error->notempty = "『%s』can not be empty."; -$lang->error->empty = "『%s』 must be empty."; -$lang->error->equal = "『%s』must be『%s』."; -$lang->error->int = array("『%s』should be interger", "『%s』should between『%s-%s』."); -$lang->error->float = "『%s』should be a interger or float."; -$lang->error->email = "『%s』should be email."; -$lang->error->date = "『%s』should be date"; -$lang->error->account = "『%s』should be a valid account."; -$lang->error->passwordsame = "Two passwords must be the same"; -$lang->error->passwordrule = "Password should more than six letters."; -$lang->error->accessDenied = 'No purview'; - -/* Pager. */ -$lang->pager->noRecord = "No records yet."; -$lang->pager->digest = "%s records, %s per page, %s/%s "; -$lang->pager->first = "First"; -$lang->pager->pre = "Previous"; -$lang->pager->next = "Next"; -$lang->pager->last = "Last"; -$lang->pager->locate = "GO!"; - -$lang->zentaoSite = "Official Site"; -$lang->chinaScrum = "Scrum community "; -$lang->agileTraining = "Training "; -$lang->donate = "Donate "; -$lang->zentaoKeywords = "Open Source Project Management System"; -$lang->zentaoDESC = "ZenTaoPMS is an open sourced project management system."; - - - -/* Date times. */ -define('DT_DATETIME1', 'Y-m-d H:i:s'); -define('DT_DATETIME2', 'y-m-d H:i'); -define('DT_MONTHTIME1', 'n/d H:i'); -define('DT_MONTHTIME2', 'F j, H:i'); -define('DT_DATE1', 'Y-m-d'); -define('DT_DATE2', 'Ymd'); -define('DT_DATE3', 'F j, Y '); -define('DT_DATE4', 'M j'); -define('DT_TIME1', 'H:i:s'); -define('DT_TIME2', 'H:i'); + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->arrow = ' » '; +$lang->colon = '::'; +$lang->comma = ','; +$lang->dot = '.'; +$lang->at = ' at '; +$lang->downArrow = '↓'; + +$lang->ZenTaoPMS = 'ZenTaoPMS'; +$lang->welcome = "Welcome to『%s』{$lang->colon} {$lang->ZenTaoPMS}"; +$lang->myControl = "Dashboard"; +$lang->currentPos = 'Current'; +$lang->logout = 'Logout'; +$lang->login = 'Login'; +$lang->aboutZenTao = 'About'; +$lang->todayIs = '%s, '; +$lang->runInfo = "
Time: %s ms, Memory: %s KB, Queries: %s.
"; + +$lang->reset = 'Reset'; +$lang->edit = 'Edit'; +$lang->copy = 'Copy'; +$lang->delete = 'Delete'; +$lang->close = 'Close'; +$lang->link = 'Link'; +$lang->unlink = 'Unlink'; +$lang->import = 'Import'; +$lang->export = 'Export'; +$lang->setFileName = 'Filename:'; +$lang->activate = 'Activate'; +$lang->submitting = 'Saving...'; +$lang->save = 'Save'; +$lang->confirm = 'Confirm'; +$lang->preview = 'View'; +$lang->goback = 'Back'; +$lang->go = 'GO'; +$lang->more = 'More'; + +$lang->actions = 'Actions'; +$lang->comment = 'Comment'; +$lang->history = 'History'; +$lang->attatch = 'Attatch'; +$lang->reverse = '[Reverse]'; +$lang->switchDisplay= '[Toggle Show]'; +$lang->switchHelp = 'Toggle Help'; +$lang->addFiles = 'Add Files'; +$lang->files = 'Files '; +$lang->unfold = '+'; +$lang->fold = '-'; + +$lang->selectAll = 'Select All'; +$lang->notFound = 'Sorry, the object not found.'; +$lang->showAll = '++ Show All ++'; +$lang->hideClosed = '-- Hide Closed--'; + +$lang->future = 'Future'; +$lang->year = 'Year'; +$lang->workingHour = 'Hour'; + +$lang->idAB = 'ID'; +$lang->priAB = 'P'; +$lang->statusAB = 'Status'; +$lang->openedByAB = 'Open'; +$lang->assignedToAB = 'To'; +$lang->typeAB = 'Type'; + +$lang->common->common = 'Common module'; + +/* The main menu. */ +$lang->menu->my = 'Dashboard|my|index'; +$lang->menu->product = 'Product|product|index'; +$lang->menu->project = 'Project|project|index'; +$lang->menu->qa = 'Test|qa|index'; +$lang->menu->doc = 'Doc|doc|index'; +$lang->menu->company = 'Company|company|index'; +$lang->menu->admin = 'Admin|admin|index'; + +/* The objects in the search box. */ +$lang->searchObjects['bug'] = 'Bug'; +$lang->searchObjects['story'] = 'Story'; +$lang->searchObjects['task'] = 'Task'; +$lang->searchObjects['testcase'] = 'Test Case'; +$lang->searchObjects['project'] = 'Project'; +$lang->searchObjects['product'] = 'Product'; +$lang->searchObjects['user'] = 'User'; +$lang->searchObjects['build'] = 'Build'; +$lang->searchObjects['release'] = 'Release'; +$lang->searchObjects['productplan'] = 'Plan'; +$lang->searchObjects['testtask'] = 'Test Task'; +$lang->searchObjects['doc'] = 'Doc'; +$lang->searchTips = 'Id here'; + +/* File type of export. */ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +/* Themes. */ +$lang->themes['default'] = 'Default'; +$lang->themes['green'] = 'Green'; +$lang->themes['red'] = 'Red'; +$lang->themes['classblue'] = 'Blue'; + +/* Index mododule menu. */ +$lang->index->menu->product = 'Products|product|browse'; +$lang->index->menu->project = 'Projects|project|browse'; + +/* Dashboard menu. */ +$lang->my->menu->account = '%s' . $lang->arrow; +$lang->my->menu->index = 'Index|my|index'; +$lang->my->menu->todo = array('link' => 'Todo|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->task = 'Task|my|task|'; +$lang->my->menu->bug = 'Bug|my|bug|'; +$lang->my->menu->testtask = 'Test|my|testtask|'; +$lang->my->menu->story = 'Story|my|story|'; +$lang->my->menu->myProject = 'Project|my|project|'; +$lang->my->menu->dynamic = 'Dynamic|my|dynamic|'; +$lang->my->menu->profile = array('link' => 'Profile|my|profile|', 'alias' => 'editprofile'); +$lang->todo->menu = $lang->my->menu; + +/* Product menu. */ +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'subModule' => 'story'); +$lang->product->menu->dynamic = 'Dynamic|product|dynamic|productID=%s'; +$lang->product->menu->plan = array('link' => 'Plan|productplan|browse|productID=%s', 'subModule' => 'productplan'); +$lang->product->menu->release = array('link' => 'Release|release|browse|productID=%s', 'subModule' => 'release'); +$lang->product->menu->roadmap = 'Roadmap|product|roadmap|productID=%s'; +$lang->product->menu->doc = array('link' => 'Doc|product|doc|productID=%s', 'subModule' => 'doc'); +$lang->product->menu->view = 'Info|product|view|productID=%s'; +$lang->product->menu->edit = 'Edit|product|edit|productID=%s'; +$lang->product->menu->delete = array('link' => 'Delete|product|delete|productID=%s', 'target' => 'hiddenwin'); +$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story'; +$lang->product->menu->create = array('link' => 'New Product|product|create', 'float' => 'right'); +$lang->product->menu->project = array('link' => 'Project list|product|project|status=all&productID=%s', 'float' => 'right'); +$lang->product->menu->all = array('link' => 'All product|product|index|locate=false', 'float' => 'right'); +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* Project menu. */ +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); +$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = 'Dynamic|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = 'Testtask|project|testtask|projectID=%s'; +$lang->project->menu->burn = 'Burn|project|burn|projectID=%s'; +$lang->project->menu->team = array('link' => 'Team|project|team|projectID=%s', 'alias' => 'managemembers'); +$lang->project->menu->doc = array('link' => 'Doc|project|doc|porjectID=%s', 'subModule' => 'doc'); +$lang->project->menu->product = 'Link Product|project|manageproducts|projectID=%s'; +$lang->project->menu->linkstory = array('link' => 'Link Story|project|linkstory|projectID=%s'); +$lang->project->menu->view = 'Info|project|view|projectID=%s'; +$lang->project->menu->edit = 'Edit|project|edit|projectID=%s'; +$lang->project->menu->delete = array('link' => 'Delete|project|delete|projectID=%s', 'target' => 'hiddenwin'); +$lang->project->menu->create = array('link' => 'New Project|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => 'Project list|project|index|locate=no', 'float' => 'right'); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA menu. */ +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); +$lang->bug->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); +$lang->bug->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s'); + +$lang->testcase->menu->product = '%s'; +$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); +$lang->testcase->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s'); + +$lang->testtask->menu->product = '%s'; +$lang->testtask->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); +$lang->testtask->menu->testcase = array('link' => 'Test Case|testcase|browse|productID=%s'); +$lang->testtask->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +/* Doc menu. */ +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s'); +$lang->doc->menu->edit = 'Edit Library|doc|editLib|libID=%s'; +$lang->doc->menu->module = 'Modules|tree|browse|libID=%s&viewType=doc'; +$lang->doc->menu->delete = array('link' => 'Delete Library|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); +$lang->doc->menu->create = array('link' => 'New Library|doc|createLib', 'float' => 'right'); + +/* Company menu. */ +$lang->company->menu->name = '%s' . $lang->arrow; +$lang->company->menu->browseUser = array('link' => 'Users|company|browse', 'subModule' => 'user'); +$lang->company->menu->dept = array('link' => 'Department|dept|browse', 'subModule' => 'dept'); +$lang->company->menu->browseGroup = array('link' => 'Group|group|browse', 'subModule' => 'group'); +$lang->company->menu->edit = array('link' => 'Company|company|edit'); +$lang->company->menu->dynamic = 'Dynamic|company|dynamic|'; +$lang->company->menu->addGroup = array('link' => 'Add Group|group|create', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => 'Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right'); +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; + +/* User menu. */ +$lang->user->menu->account = '%s' . $lang->arrow; +$lang->user->menu->todo = array('link' => 'Todo|user|todo|account=%s', 'subModule' => 'todo'); +$lang->user->menu->task = 'Task|user|task|account=%s'; +$lang->user->menu->bug = 'Bug|user|bug|account=%s'; +$lang->user->menu->dynamic = 'Dynamic|user|dynamic|type=today&account=%s'; +$lang->user->menu->projectList = 'Project|user|project|account=%s'; +$lang->user->menu->profile = array('link' => 'Profile|user|profile|account=%s', 'alias' => 'edit'); +$lang->user->menu->browse = array('link' => 'Manage user|company|browse|', 'float' => 'right'); + +/* Admin menu. */ +$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension'); +$lang->admin->menu->editor = array('link' => 'Extension editor|editor|index', 'subModule' => 'editor'); +$lang->admin->menu->mail = array('link' => 'ConfigEmail|mail|set', 'subModule' => 'mail'); +$lang->admin->menu->convert = array('link' => 'Import|convert|index', 'subModule' => 'convert'); +$lang->admin->menu->trashes = array('link' => 'Trash|action|trash', 'subModule' => 'action'); +$lang->convert->menu = $lang->admin->menu; +$lang->upgrade->menu = $lang->admin->menu; +$lang->action->menu = $lang->admin->menu; +$lang->extension->menu = $lang->admin->menu; +$lang->editor->menu = $lang->admin->menu; +$lang->mail->menu = $lang->admin->menu; + +/* Groups. */ +$lang->menugroup->release = 'product'; +$lang->menugroup->story = 'product'; +$lang->menugroup->productplan = 'product'; +$lang->menugroup->task = 'project'; +$lang->menugroup->build = 'project'; +$lang->menugroup->convert = 'admin'; +$lang->menugroup->upgrade = 'admin'; +$lang->menugroup->user = 'company'; +$lang->menugroup->group = 'company'; +$lang->menugroup->bug = 'qa'; +$lang->menugroup->testcase = 'qa'; +$lang->menugroup->testtask = 'qa'; +$lang->menugroup->people = 'company'; +$lang->menugroup->dept = 'company'; +$lang->menugroup->todo = 'my'; +$lang->menugroup->action = 'admin'; +$lang->menugroup->extension = 'admin'; +$lang->menugroup->editor = 'admin'; +$lang->menugroup->mail = 'admin'; + +/* Error info. */ +$lang->error->companyNotFound = "The domain %s does not exist."; +$lang->error->length = array("『%s』length should be『%s』", "『%s』length should between『%s』and 『%s』."); +$lang->error->reg = "『%s』should like『%s』"; +$lang->error->unique = "『%s』has『%s』already."; +$lang->error->gt = "『%s』must great than『%s』."; +$lang->error->notempty = "『%s』can not be empty."; +$lang->error->empty = "『%s』 must be empty."; +$lang->error->equal = "『%s』must be『%s』."; +$lang->error->int = array("『%s』should be interger", "『%s』should between『%s-%s』."); +$lang->error->float = "『%s』should be a interger or float."; +$lang->error->email = "『%s』should be email."; +$lang->error->date = "『%s』should be date"; +$lang->error->account = "『%s』should be a valid account."; +$lang->error->passwordsame = "Two passwords must be the same"; +$lang->error->passwordrule = "Password should more than six letters."; +$lang->error->accessDenied = 'No purview'; + +/* Pager. */ +$lang->pager->noRecord = "No records yet."; +$lang->pager->digest = "%s records, %s per page, %s/%s "; +$lang->pager->first = "First"; +$lang->pager->pre = "Previous"; +$lang->pager->next = "Next"; +$lang->pager->last = "Last"; +$lang->pager->locate = "GO!"; + +$lang->zentaoSite = "Official Site"; +$lang->chinaScrum = "Scrum community "; +$lang->agileTraining = "Training "; +$lang->donate = "Donate "; +$lang->zentaoKeywords = "Open Source Project Management System"; +$lang->zentaoDESC = "ZenTaoPMS is an open sourced project management system."; + + + +/* Date times. */ +define('DT_DATETIME1', 'Y-m-d H:i:s'); +define('DT_DATETIME2', 'y-m-d H:i'); +define('DT_MONTHTIME1', 'n/d H:i'); +define('DT_MONTHTIME2', 'F j, H:i'); +define('DT_DATE1', 'Y-m-d'); +define('DT_DATE2', 'Ymd'); +define('DT_DATE3', 'F j, Y '); +define('DT_DATE4', 'M j'); +define('DT_TIME1', 'H:i:s'); +define('DT_TIME2', 'H:i'); diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index da032065ec..a748bfe424 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -1,296 +1,296 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->arrow = ' » '; -$lang->colon = '::'; -$lang->comma = ','; -$lang->dot = '。'; -$lang->at = ' 于 '; -$lang->downArrow = '↓'; - -$lang->ZenTaoPMS = '禅道管理'; -$lang->welcome = "欢迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}"; -$lang->myControl = "我的地盘"; -$lang->currentPos = '当前位置:'; -$lang->logout = '退出'; -$lang->login = '登录'; -$lang->aboutZenTao = '关于'; -$lang->todayIs = '今天是%s,'; -$lang->runInfo = "
时间: %s 毫秒, 内存: %s KB, 查询: %s.
"; - -$lang->reset = '重填'; -$lang->edit = '编辑'; -$lang->copy = '复制'; -$lang->delete = '删除'; -$lang->close = '关闭'; -$lang->link = '关联'; -$lang->unlink = '移除'; -$lang->import = '导入'; -$lang->export = '导出'; -$lang->setFileName = '文件名:'; -$lang->activate = '激活'; -$lang->submitting = '稍候...'; -$lang->save = '保存'; -$lang->confirm = '确认'; -$lang->preview = '查看'; -$lang->goback = '返回'; -$lang->go = 'GO'; -$lang->more = '更多'; - -$lang->actions = '操作'; -$lang->comment = '备注'; -$lang->history = '历史记录'; -$lang->attatch = '附件'; -$lang->reverse = '[切换顺序]'; -$lang->switchDisplay= '[切换显示]'; -$lang->switchHelp = '切换帮助'; -$lang->addFiles = '上传了附件 '; -$lang->files = '附件 '; -$lang->unfold = '+'; -$lang->fold = '-'; - -$lang->selectAll = '全选'; -$lang->notFound = '抱歉,您访问的对象并不存在!'; -$lang->showAll = '++ 全部显示 ++'; -$lang->hideClosed = '-- 隐藏已结束 --'; - -$lang->future = '未来'; -$lang->year = '年'; -$lang->workingHour = '工时'; - -$lang->idAB = 'ID'; -$lang->priAB = 'P'; -$lang->statusAB = '状态'; -$lang->openedByAB = '创建'; -$lang->assignedToAB = '指派'; -$lang->typeAB = '类型'; - -$lang->common->common = '公有模块'; - -/* 主导航菜单。*/ -$lang->menu->my = '我的地盘|my|index'; -$lang->menu->product = '产品视图|product|index'; -$lang->menu->project = '项目视图|project|index'; -$lang->menu->qa = '测试视图|qa|index'; -$lang->menu->doc = '文档视图|doc|index'; -$lang->menu->company = '组织视图|company|index'; -$lang->menu->admin = '后台管理|admin|index'; - -/* 查询条中可以选择的对象列表。*/ -$lang->searchObjects['bug'] = 'B:Bug'; -$lang->searchObjects['story'] = 'S:需求'; -$lang->searchObjects['task'] = 'T:任务'; -$lang->searchObjects['testcase'] = 'C:用例'; -$lang->searchObjects['project'] = 'P:项目'; -$lang->searchObjects['product'] = 'P:产品'; -$lang->searchObjects['user'] = 'U:用户'; -$lang->searchObjects['build'] = 'B:Build'; -$lang->searchObjects['release'] = 'R:发布'; -$lang->searchObjects['productplan'] = 'P:产品计划'; -$lang->searchObjects['testtask'] = 'T:测试任务'; -$lang->searchObjects['doc'] = 'D:文档'; -$lang->searchTips = '输入编号'; - -/* 导出文件的类型列表。*/ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -/* 风格列表。*/ -$lang->themes['default'] = '默认'; -$lang->themes['green'] = '绿色'; -$lang->themes['red'] = '红色'; -$lang->themes['classblue'] = '经典蓝'; - -/* 首页菜单设置。*/ -$lang->index->menu->product = '浏览产品|product|browse'; -$lang->index->menu->project = '浏览项目|project|browse'; - -/* 我的地盘菜单设置。*/ -$lang->my->menu->account = '%s' . $lang->arrow; -$lang->my->menu->index = '首页|my|index'; -$lang->my->menu->todo = array('link' => '我的TODO|my|todo|', 'subModule' => 'todo'); -$lang->my->menu->task = '我的任务|my|task|'; -$lang->my->menu->bug = '我的Bug|my|bug|'; -$lang->my->menu->testtask = '我的测试|my|testtask|'; -$lang->my->menu->story = '我的需求|my|story|'; -$lang->my->menu->myProject = '我的项目|my|project|'; -$lang->my->menu->dynamic = '我的动态|my|dynamic|'; -$lang->my->menu->profile = array('link' => '我的档案|my|profile|', 'alias' => 'editprofile'); -$lang->todo->menu = $lang->my->menu; - -/* 产品视图设置。*/ -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'subModule' => 'story'); -$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s'; -$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan'); -$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release'); -$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s'; -$lang->product->menu->doc = array('link' => '文档|product|doc|productID=%s', 'subModule' => 'doc'); -$lang->product->menu->view = '概况|product|view|productID=%s'; -$lang->product->menu->edit = '编辑|product|edit|productID=%s'; -$lang->product->menu->delete = array('link' => '删除|product|delete|productID=%s', 'target' => 'hiddenwin'); -$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; -$lang->product->menu->create = array('link' => '新增产品|product|create', 'float' => 'right'); -$lang->product->menu->project = array('link' => '项目列表|product|project|status=all&productID=%s', 'float' => 'right'); -$lang->product->menu->all = array('link' => '所有产品|product|index|locate=false', 'float' => 'right'); -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* 项目视图菜单设置。*/ -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = '测试任务|project|testtask|projectID=%s'; -$lang->project->menu->burn = '燃尽图|project|burn|projectID=%s'; -$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers'); -$lang->project->menu->doc = array('link' => '文档|project|doc|porjectID=%s', 'subModule' => 'doc'); -$lang->project->menu->product = '产品|project|manageproducts|projectID=%s'; -$lang->project->menu->linkstory = array('link' => '关联需求|project|linkstory|projectID=%s'); -$lang->project->menu->view = '概况|project|view|projectID=%s'; -$lang->project->menu->edit = '编辑|project|edit|projectID=%s'; -$lang->project->menu->delete = array('link' => '删除|project|delete|projectID=%s', 'target' => 'hiddenwin'); -$lang->project->menu->create = array('link' => '新增项目|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => '所有项目|project|index|locate=false', 'float' => 'right'); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA视图菜单设置。*/ -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); -$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); -$lang->bug->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); - -$lang->testcase->menu->product = '%s'; -$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); -$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); - -$lang->testtask->menu->product = '%s'; -$lang->testtask->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); -$lang->testtask->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s'); -$lang->testtask->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -/* 文档视图菜单设置。*/ -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => '文档列表|doc|browse|libID=%s'); -$lang->doc->menu->edit = '编辑文档库|doc|editLib|libID=%s'; -$lang->doc->menu->module = '维护模块|tree|browse|libID=%s&viewType=doc'; -$lang->doc->menu->delete = array('link' => '删除文档库|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); -$lang->doc->menu->create = array('link' => '新增文档库|doc|createLib', 'float' => 'right'); - -/* 组织结构视图菜单设置。*/ -$lang->company->menu->name = '%s' . $lang->arrow; -$lang->company->menu->browseUser = array('link' => '用户列表|company|browse', 'subModule' => 'user'); -$lang->company->menu->dept = array('link' => '部门维护|dept|browse', 'subModule' => 'dept'); -$lang->company->menu->browseGroup = array('link' => '权限分组|group|browse', 'subModule' => 'group'); -$lang->company->menu->edit = array('link' => '公司管理|company|edit'); -$lang->company->menu->dynamic = '组织动态|company|dynamic|'; -$lang->company->menu->addGroup = array('link' => '添加分组|group|create', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => '添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; - -/* 用户信息菜单设置。*/ -$lang->user->menu->account = '%s' . $lang->arrow; -$lang->user->menu->todo = array('link' => 'TODO列表|user|todo|account=%s', 'subModule' => 'todo'); -$lang->user->menu->task = '任务列表|user|task|account=%s'; -$lang->user->menu->bug = 'Bug列表|user|bug|account=%s'; -$lang->user->menu->dynamic = '用户动态|user|dynamic|type=today&account=%s'; -$lang->user->menu->projectList = '项目列表|user|project|account=%s'; -$lang->user->menu->profile = array('link' => '用户信息|user|profile|account=%s', 'alias' => 'edit'); -$lang->user->menu->browse = array('link' => '用户管理|company|browse|', 'float' => 'right'); - -/* 后台管理菜单设置。*/ -$lang->admin->menu->extension = array('link' => '插件管理|extension|browse', 'subModule' => 'extension'); -$lang->admin->menu->editor = array('link' => '扩展编辑器|editor|index', 'subModule' => 'editor'); -$lang->admin->menu->mail = array('link' => 'Email配置|mail|set', 'subModule' => 'mail'); -$lang->admin->menu->convert = array('link' => '从其他系统导入|convert|index', 'subModule' => 'convert'); -$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); -$lang->convert->menu = $lang->admin->menu; -$lang->upgrade->menu = $lang->admin->menu; -$lang->action->menu = $lang->admin->menu; -$lang->extension->menu = $lang->admin->menu; -$lang->editor->menu = $lang->admin->menu; -$lang->mail->menu = $lang->admin->menu; - -/*菜单设置:分组设置。*/ -$lang->menugroup->release = 'product'; -$lang->menugroup->story = 'product'; -$lang->menugroup->productplan = 'product'; -$lang->menugroup->task = 'project'; -$lang->menugroup->build = 'project'; -$lang->menugroup->convert = 'admin'; -$lang->menugroup->upgrade = 'admin'; -$lang->menugroup->user = 'company'; -$lang->menugroup->group = 'company'; -$lang->menugroup->bug = 'qa'; -$lang->menugroup->testcase = 'qa'; -$lang->menugroup->testtask = 'qa'; -$lang->menugroup->people = 'company'; -$lang->menugroup->dept = 'company'; -$lang->menugroup->todo = 'my'; -$lang->menugroup->action = 'admin'; -$lang->menugroup->extension = 'admin'; -$lang->menugroup->editor = 'admin'; -$lang->menugroup->mail = 'admin'; - -/* 错误提示信息。*/ -$lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。"; -$lang->error->length = array("『%s』长度错误,应当为『%s』", "『%s』长度应当不超过『%s』,且不小于『%s』。"); -$lang->error->reg = "『%s』不符合格式,应当为:『%s』。"; -$lang->error->unique = "『%s』已经有『%s』这条记录了。"; -$lang->error->gt = "『%s』应当大于『%s』。"; -$lang->error->notempty = "『%s』不能为空。"; -$lang->error->empty = "『%s』必须为空。"; -$lang->error->equal = "『%s』必须为『%s』。"; -$lang->error->int = array("『%s』应当是数字。", "『%s』应当介于『%s-%s』之间。"); -$lang->error->float = "『%s』应当是数字,可以是小数。"; -$lang->error->email = "『%s』应当为合法的EMAIL。"; -$lang->error->date = "『%s』应当为合法的日期。"; -$lang->error->account = "『%s』应当为合法的用户名。"; -$lang->error->passwordsame = "两次密码应当相等。"; -$lang->error->passwordrule = "密码应该符合规则,长度至少为六位。"; -$lang->error->accessDenied = '您没有访问权限'; - -/* 分页信息。*/ -$lang->pager->noRecord = "暂时没有记录"; -$lang->pager->digest = "共%s条记录,每页 %s条,页面:%s/%s "; -$lang->pager->first = "首页"; -$lang->pager->pre = "上页"; -$lang->pager->next = "下页"; -$lang->pager->last = "末页"; -$lang->pager->locate = "GO!"; - -$lang->zentaoSite = "官方网站"; -$lang->chinaScrum = "Scrum社区 "; -$lang->agileTraining = "培训 "; -$lang->donate = "捐助禅道 "; -$lang->zentaoKeywords = "开源项目管理软件,项目管理,项目管理软件,pmp,pms,php框架,国产php框架,scrum工具,scrum管理工具,scrum管理软件,敏捷项目管理,禅道"; -$lang->zentaoDESC = "禅道项目管理软件(ZenTaoPMS)是一款国产的,基于LGPL协议,开源免费的项目管理软件(工具、系统),同时也是一款scrum管理工具。 - 它集产品管理、项目管理、测试管理于一体,同时还包含了事务管理、组织管理等诸多功能,是中小型企业项目管理的首选。禅道项目管理软件使用PHP + MySQL开发, -基于自主的PHP开发框架──ZenTaoPHP而成。第三方开发者或者企业可以非常方便的开发插件或者进行定制。禅道在手,项目无忧!"; - -/* 时间格式设置。*/ -define('DT_DATETIME1', 'Y-m-d H:i:s'); -define('DT_DATETIME2', 'y-m-d H:i'); -define('DT_MONTHTIME1', 'n/d H:i'); -define('DT_MONTHTIME2', 'n月d日 H:i'); -define('DT_DATE1', 'Y-m-d'); -define('DT_DATE2', 'Ymd'); -define('DT_DATE3', 'Y年m月d日'); -define('DT_DATE4', 'n月j日'); -define('DT_TIME1', 'H:i:s'); -define('DT_TIME2', 'H:i'); + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->arrow = ' » '; +$lang->colon = '::'; +$lang->comma = ','; +$lang->dot = '。'; +$lang->at = ' 于 '; +$lang->downArrow = '↓'; + +$lang->ZenTaoPMS = '禅道管理'; +$lang->welcome = "欢迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}"; +$lang->myControl = "我的地盘"; +$lang->currentPos = '当前位置:'; +$lang->logout = '退出'; +$lang->login = '登录'; +$lang->aboutZenTao = '关于'; +$lang->todayIs = '今天是%s,'; +$lang->runInfo = "
时间: %s 毫秒, 内存: %s KB, 查询: %s.
"; + +$lang->reset = '重填'; +$lang->edit = '编辑'; +$lang->copy = '复制'; +$lang->delete = '删除'; +$lang->close = '关闭'; +$lang->link = '关联'; +$lang->unlink = '移除'; +$lang->import = '导入'; +$lang->export = '导出'; +$lang->setFileName = '文件名:'; +$lang->activate = '激活'; +$lang->submitting = '稍候...'; +$lang->save = '保存'; +$lang->confirm = '确认'; +$lang->preview = '查看'; +$lang->goback = '返回'; +$lang->go = 'GO'; +$lang->more = '更多'; + +$lang->actions = '操作'; +$lang->comment = '备注'; +$lang->history = '历史记录'; +$lang->attatch = '附件'; +$lang->reverse = '[切换顺序]'; +$lang->switchDisplay= '[切换显示]'; +$lang->switchHelp = '切换帮助'; +$lang->addFiles = '上传了附件 '; +$lang->files = '附件 '; +$lang->unfold = '+'; +$lang->fold = '-'; + +$lang->selectAll = '全选'; +$lang->notFound = '抱歉,您访问的对象并不存在!'; +$lang->showAll = '++ 全部显示 ++'; +$lang->hideClosed = '-- 隐藏已结束 --'; + +$lang->future = '未来'; +$lang->year = '年'; +$lang->workingHour = '工时'; + +$lang->idAB = 'ID'; +$lang->priAB = 'P'; +$lang->statusAB = '状态'; +$lang->openedByAB = '创建'; +$lang->assignedToAB = '指派'; +$lang->typeAB = '类型'; + +$lang->common->common = '公有模块'; + +/* 主导航菜单。*/ +$lang->menu->my = '我的地盘|my|index'; +$lang->menu->product = '产品视图|product|index'; +$lang->menu->project = '项目视图|project|index'; +$lang->menu->qa = '测试视图|qa|index'; +$lang->menu->doc = '文档视图|doc|index'; +$lang->menu->company = '组织视图|company|index'; +$lang->menu->admin = '后台管理|admin|index'; + +/* 查询条中可以选择的对象列表。*/ +$lang->searchObjects['bug'] = 'B:Bug'; +$lang->searchObjects['story'] = 'S:需求'; +$lang->searchObjects['task'] = 'T:任务'; +$lang->searchObjects['testcase'] = 'C:用例'; +$lang->searchObjects['project'] = 'P:项目'; +$lang->searchObjects['product'] = 'P:产品'; +$lang->searchObjects['user'] = 'U:用户'; +$lang->searchObjects['build'] = 'B:Build'; +$lang->searchObjects['release'] = 'R:发布'; +$lang->searchObjects['productplan'] = 'P:产品计划'; +$lang->searchObjects['testtask'] = 'T:测试任务'; +$lang->searchObjects['doc'] = 'D:文档'; +$lang->searchTips = '输入编号'; + +/* 导出文件的类型列表。*/ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +/* 风格列表。*/ +$lang->themes['default'] = '默认'; +$lang->themes['green'] = '绿色'; +$lang->themes['red'] = '红色'; +$lang->themes['classblue'] = '经典蓝'; + +/* 首页菜单设置。*/ +$lang->index->menu->product = '浏览产品|product|browse'; +$lang->index->menu->project = '浏览项目|project|browse'; + +/* 我的地盘菜单设置。*/ +$lang->my->menu->account = '%s' . $lang->arrow; +$lang->my->menu->index = '首页|my|index'; +$lang->my->menu->todo = array('link' => '我的TODO|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->task = '我的任务|my|task|'; +$lang->my->menu->bug = '我的Bug|my|bug|'; +$lang->my->menu->testtask = '我的测试|my|testtask|'; +$lang->my->menu->story = '我的需求|my|story|'; +$lang->my->menu->myProject = '我的项目|my|project|'; +$lang->my->menu->dynamic = '我的动态|my|dynamic|'; +$lang->my->menu->profile = array('link' => '我的档案|my|profile|', 'alias' => 'editprofile'); +$lang->todo->menu = $lang->my->menu; + +/* 产品视图设置。*/ +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'subModule' => 'story'); +$lang->product->menu->dynamic = '动态|product|dynamic|productID=%s'; +$lang->product->menu->plan = array('link' => '计划|productplan|browse|productID=%s', 'subModule' => 'productplan'); +$lang->product->menu->release = array('link' => '发布|release|browse|productID=%s', 'subModule' => 'release'); +$lang->product->menu->roadmap = '路线图|product|roadmap|productID=%s'; +$lang->product->menu->doc = array('link' => '文档|product|doc|productID=%s', 'subModule' => 'doc'); +$lang->product->menu->view = '概况|product|view|productID=%s'; +$lang->product->menu->edit = '编辑|product|edit|productID=%s'; +$lang->product->menu->delete = array('link' => '删除|product|delete|productID=%s', 'target' => 'hiddenwin'); +$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; +$lang->product->menu->create = array('link' => '新增产品|product|create', 'float' => 'right'); +$lang->product->menu->project = array('link' => '项目列表|product|project|status=all&productID=%s', 'float' => 'right'); +$lang->product->menu->all = array('link' => '所有产品|product|index|locate=false', 'float' => 'right'); +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* 项目视图菜单设置。*/ +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = '测试任务|project|testtask|projectID=%s'; +$lang->project->menu->burn = '燃尽图|project|burn|projectID=%s'; +$lang->project->menu->team = array('link' => '团队|project|team|projectID=%s', 'alias' => 'managemembers'); +$lang->project->menu->doc = array('link' => '文档|project|doc|porjectID=%s', 'subModule' => 'doc'); +$lang->project->menu->product = '产品|project|manageproducts|projectID=%s'; +$lang->project->menu->linkstory = array('link' => '关联需求|project|linkstory|projectID=%s'); +$lang->project->menu->view = '概况|project|view|projectID=%s'; +$lang->project->menu->edit = '编辑|project|edit|projectID=%s'; +$lang->project->menu->delete = array('link' => '删除|project|delete|projectID=%s', 'target' => 'hiddenwin'); +$lang->project->menu->create = array('link' => '新增项目|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => '所有项目|project|index|locate=false', 'float' => 'right'); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA视图菜单设置。*/ +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); +$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); +$lang->bug->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); + +$lang->testcase->menu->product = '%s'; +$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); +$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s'); + +$lang->testtask->menu->product = '%s'; +$lang->testtask->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); +$lang->testtask->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s'); +$lang->testtask->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +/* 文档视图菜单设置。*/ +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => '文档列表|doc|browse|libID=%s'); +$lang->doc->menu->edit = '编辑文档库|doc|editLib|libID=%s'; +$lang->doc->menu->module = '维护模块|tree|browse|libID=%s&viewType=doc'; +$lang->doc->menu->delete = array('link' => '删除文档库|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); +$lang->doc->menu->create = array('link' => '新增文档库|doc|createLib', 'float' => 'right'); + +/* 组织结构视图菜单设置。*/ +$lang->company->menu->name = '%s' . $lang->arrow; +$lang->company->menu->browseUser = array('link' => '用户列表|company|browse', 'subModule' => 'user'); +$lang->company->menu->dept = array('link' => '部门维护|dept|browse', 'subModule' => 'dept'); +$lang->company->menu->browseGroup = array('link' => '权限分组|group|browse', 'subModule' => 'group'); +$lang->company->menu->edit = array('link' => '公司管理|company|edit'); +$lang->company->menu->dynamic = '组织动态|company|dynamic|'; +$lang->company->menu->addGroup = array('link' => '添加分组|group|create', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => '添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; + +/* 用户信息菜单设置。*/ +$lang->user->menu->account = '%s' . $lang->arrow; +$lang->user->menu->todo = array('link' => 'TODO列表|user|todo|account=%s', 'subModule' => 'todo'); +$lang->user->menu->task = '任务列表|user|task|account=%s'; +$lang->user->menu->bug = 'Bug列表|user|bug|account=%s'; +$lang->user->menu->dynamic = '用户动态|user|dynamic|type=today&account=%s'; +$lang->user->menu->projectList = '项目列表|user|project|account=%s'; +$lang->user->menu->profile = array('link' => '用户信息|user|profile|account=%s', 'alias' => 'edit'); +$lang->user->menu->browse = array('link' => '用户管理|company|browse|', 'float' => 'right'); + +/* 后台管理菜单设置。*/ +$lang->admin->menu->extension = array('link' => '插件管理|extension|browse', 'subModule' => 'extension'); +$lang->admin->menu->editor = array('link' => '扩展编辑器|editor|index', 'subModule' => 'editor'); +$lang->admin->menu->mail = array('link' => 'Email配置|mail|set', 'subModule' => 'mail'); +$lang->admin->menu->convert = array('link' => '从其他系统导入|convert|index', 'subModule' => 'convert'); +$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); +$lang->convert->menu = $lang->admin->menu; +$lang->upgrade->menu = $lang->admin->menu; +$lang->action->menu = $lang->admin->menu; +$lang->extension->menu = $lang->admin->menu; +$lang->editor->menu = $lang->admin->menu; +$lang->mail->menu = $lang->admin->menu; + +/*菜单设置:分组设置。*/ +$lang->menugroup->release = 'product'; +$lang->menugroup->story = 'product'; +$lang->menugroup->productplan = 'product'; +$lang->menugroup->task = 'project'; +$lang->menugroup->build = 'project'; +$lang->menugroup->convert = 'admin'; +$lang->menugroup->upgrade = 'admin'; +$lang->menugroup->user = 'company'; +$lang->menugroup->group = 'company'; +$lang->menugroup->bug = 'qa'; +$lang->menugroup->testcase = 'qa'; +$lang->menugroup->testtask = 'qa'; +$lang->menugroup->people = 'company'; +$lang->menugroup->dept = 'company'; +$lang->menugroup->todo = 'my'; +$lang->menugroup->action = 'admin'; +$lang->menugroup->extension = 'admin'; +$lang->menugroup->editor = 'admin'; +$lang->menugroup->mail = 'admin'; + +/* 错误提示信息。*/ +$lang->error->companyNotFound = "您访问的域名 %s 没有对应的公司。"; +$lang->error->length = array("『%s』长度错误,应当为『%s』", "『%s』长度应当不超过『%s』,且不小于『%s』。"); +$lang->error->reg = "『%s』不符合格式,应当为:『%s』。"; +$lang->error->unique = "『%s』已经有『%s』这条记录了。"; +$lang->error->gt = "『%s』应当大于『%s』。"; +$lang->error->notempty = "『%s』不能为空。"; +$lang->error->empty = "『%s』必须为空。"; +$lang->error->equal = "『%s』必须为『%s』。"; +$lang->error->int = array("『%s』应当是数字。", "『%s』应当介于『%s-%s』之间。"); +$lang->error->float = "『%s』应当是数字,可以是小数。"; +$lang->error->email = "『%s』应当为合法的EMAIL。"; +$lang->error->date = "『%s』应当为合法的日期。"; +$lang->error->account = "『%s』应当为合法的用户名。"; +$lang->error->passwordsame = "两次密码应当相等。"; +$lang->error->passwordrule = "密码应该符合规则,长度至少为六位。"; +$lang->error->accessDenied = '您没有访问权限'; + +/* 分页信息。*/ +$lang->pager->noRecord = "暂时没有记录"; +$lang->pager->digest = "共%s条记录,每页 %s条,页面:%s/%s "; +$lang->pager->first = "首页"; +$lang->pager->pre = "上页"; +$lang->pager->next = "下页"; +$lang->pager->last = "末页"; +$lang->pager->locate = "GO!"; + +$lang->zentaoSite = "官方网站"; +$lang->chinaScrum = "Scrum社区 "; +$lang->agileTraining = "培训 "; +$lang->donate = "捐助禅道 "; +$lang->zentaoKeywords = "开源项目管理软件,项目管理,项目管理软件,pmp,pms,php框架,国产php框架,scrum工具,scrum管理工具,scrum管理软件,敏捷项目管理,禅道"; +$lang->zentaoDESC = "禅道项目管理软件(ZenTaoPMS)是一款国产的,基于LGPL协议,开源免费的项目管理软件(工具、系统),同时也是一款scrum管理工具。 + 它集产品管理、项目管理、测试管理于一体,同时还包含了事务管理、组织管理等诸多功能,是中小型企业项目管理的首选。禅道项目管理软件使用PHP + MySQL开发, +基于自主的PHP开发框架──ZenTaoPHP而成。第三方开发者或者企业可以非常方便的开发插件或者进行定制。禅道在手,项目无忧!"; + +/* 时间格式设置。*/ +define('DT_DATETIME1', 'Y-m-d H:i:s'); +define('DT_DATETIME2', 'y-m-d H:i'); +define('DT_MONTHTIME1', 'n/d H:i'); +define('DT_MONTHTIME2', 'n月d日 H:i'); +define('DT_DATE1', 'Y-m-d'); +define('DT_DATE2', 'Ymd'); +define('DT_DATE3', 'Y年m月d日'); +define('DT_DATE4', 'n月j日'); +define('DT_TIME1', 'H:i:s'); +define('DT_TIME2', 'H:i'); diff --git a/module/common/lang/zh-tw.php b/module/common/lang/zh-tw.php index 2466e64183..ea46db0f5a 100644 --- a/module/common/lang/zh-tw.php +++ b/module/common/lang/zh-tw.php @@ -1,296 +1,296 @@ - - * @package ZenTaoPMS - * @version $Id: zh-tw.php 2538 2012-01-04 07:25:59Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->arrow = ' » '; -$lang->colon = '::'; -$lang->comma = ','; -$lang->dot = '。'; -$lang->at = ' 于 '; -$lang->downArrow = '↓'; - -$lang->ZenTaoPMS = '禪道管理'; -$lang->welcome = "歡迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}"; -$lang->myControl = "我的地盤"; -$lang->currentPos = '當前位置:'; -$lang->logout = '退出'; -$lang->login = '登錄'; -$lang->aboutZenTao = '關於'; -$lang->todayIs = '今天是%s,'; -$lang->runInfo = "
時間: %s 毫秒, 內存: %s KB, 查詢: %s.
"; - -$lang->reset = '重填'; -$lang->edit = '編輯'; -$lang->copy = '複製'; -$lang->delete = '刪除'; -$lang->close = '關閉'; -$lang->link = '關聯'; -$lang->unlink = '移除'; -$lang->import = '導入'; -$lang->export = '導出'; -$lang->setFileName = '檔案名:'; -$lang->activate = '激活'; -$lang->submitting = '稍候...'; -$lang->save = '保存'; -$lang->confirm = '確認'; -$lang->preview = '查看'; -$lang->goback = '返回'; -$lang->go = 'GO'; -$lang->more = '更多'; - -$lang->actions = '操作'; -$lang->comment = '備註'; -$lang->history = '歷史記錄'; -$lang->attatch = '附件'; -$lang->reverse = '[切換順序]'; -$lang->switchDisplay= '[切換顯示]'; -$lang->switchHelp = '切換幫助'; -$lang->addFiles = '上傳了附件 '; -$lang->files = '附件 '; -$lang->unfold = '+'; -$lang->fold = '-'; - -$lang->selectAll = '全選'; -$lang->notFound = '抱歉,您訪問的對象並不存在!'; -$lang->showAll = '++ 全部顯示 ++'; -$lang->hideClosed = '-- 隱藏已結束 --'; - -$lang->feature = '未來'; -$lang->year = '年'; -$lang->workingHour = '工時'; - -$lang->idAB = 'ID'; -$lang->priAB = 'P'; -$lang->statusAB = '狀態'; -$lang->openedByAB = '創建'; -$lang->assignedToAB = '指派'; -$lang->typeAB = '類型'; - -$lang->common->common = '公有模組'; - -/* 主導航菜單。*/ -$lang->menu->my = '我的地盤|my|index'; -$lang->menu->product = '產品視圖|product|index'; -$lang->menu->project = '項目視圖|project|index'; -$lang->menu->qa = '測試視圖|qa|index'; -$lang->menu->doc = '文檔視圖|doc|index'; -$lang->menu->company = '組織視圖|company|index'; -$lang->menu->admin = '後台管理|admin|index'; - -/* 查詢條中可以選擇的對象列表。*/ -$lang->searchObjects['bug'] = 'B:Bug'; -$lang->searchObjects['story'] = 'S:需求'; -$lang->searchObjects['task'] = 'T:任務'; -$lang->searchObjects['testcase'] = 'C:用例'; -$lang->searchObjects['project'] = 'P:項目'; -$lang->searchObjects['product'] = 'P:產品'; -$lang->searchObjects['user'] = 'U:用戶'; -$lang->searchObjects['build'] = 'B:Build'; -$lang->searchObjects['release'] = 'R:發佈'; -$lang->searchObjects['productplan'] = 'P:產品計劃'; -$lang->searchObjects['testtask'] = 'T:測試任務'; -$lang->searchObjects['doc'] = 'D:文檔'; -$lang->searchTips = '輸入編號'; - -/* 導出檔案的類型列表。*/ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -/* 風格列表。*/ -$lang->themes['default'] = '預設'; -$lang->themes['green'] = '綠色'; -$lang->themes['red'] = '紅色'; -$lang->themes['classblue'] = '經典藍'; - -/* 首頁菜單設置。*/ -$lang->index->menu->product = '瀏覽產品|product|browse'; -$lang->index->menu->project = '瀏覽項目|project|browse'; - -/* 我的地盤菜單設置。*/ -$lang->my->menu->account = '%s' . $lang->arrow; -$lang->my->menu->index = '首頁|my|index'; -$lang->my->menu->todo = array('link' => '我的TODO|my|todo|', 'subModule' => 'todo'); -$lang->my->menu->task = '我的任務|my|task|'; -$lang->my->menu->bug = '我的Bug|my|bug|'; -$lang->my->menu->testtask = '我的測試|my|testtask|'; -$lang->my->menu->story = '我的需求|my|story|'; -$lang->my->menu->myProject = '我的項目|my|project|'; -$lang->my->menu->dynamic = '我的動態|my|dynamic|'; -$lang->my->menu->profile = array('link' => '我的檔案|my|profile|', 'alias' => 'editprofile'); -$lang->todo->menu = $lang->my->menu; - -/* 產品視圖設置。*/ -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'subModule' => 'story'); -$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s'; -$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan'); -$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release'); -$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s'; -$lang->product->menu->doc = array('link' => '文檔|product|doc|productID=%s', 'subModule' => 'doc'); -$lang->product->menu->view = '概況|product|view|productID=%s'; -$lang->product->menu->edit = '編輯|product|edit|productID=%s'; -$lang->product->menu->delete = array('link' => '刪除|product|delete|productID=%s', 'target' => 'hiddenwin'); -$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; -$lang->product->menu->create = array('link' => '新增產品|product|create', 'float' => 'right'); -$lang->product->menu->project = array('link' => '項目列表|product|project|status=all&productID=%s', 'float' => 'right'); -$lang->product->menu->all = array('link' => '所有產品|product|index|locate=false', 'float' => 'right'); -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* 項目視圖菜單設置。*/ -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = '測試任務|project|testtask|projectID=%s'; -$lang->project->menu->burn = '燃盡圖|project|burn|projectID=%s'; -$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers'); -$lang->project->menu->doc = array('link' => '文檔|project|doc|porjectID=%s', 'subModule' => 'doc'); -$lang->project->menu->product = '產品|project|manageproducts|projectID=%s'; -$lang->project->menu->linkstory = array('link' => '關聯需求|project|linkstory|projectID=%s'); -$lang->project->menu->view = '概況|project|view|projectID=%s'; -$lang->project->menu->edit = '編輯|project|edit|projectID=%s'; -$lang->project->menu->delete = array('link' => '刪除|project|delete|projectID=%s', 'target' => 'hiddenwin'); -$lang->project->menu->create = array('link' => '新增項目|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => '所有項目|project|index|locate=false', 'float' => 'right'); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA視圖菜單設置。*/ -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); -$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); -$lang->bug->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s'); - -$lang->testcase->menu->product = '%s'; -$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); -$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s'); - -$lang->testtask->menu->product = '%s'; -$lang->testtask->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); -$lang->testtask->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s'); -$lang->testtask->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -/* 文檔視圖菜單設置。*/ -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s'); -$lang->doc->menu->edit = '編輯文檔庫|doc|editLib|libID=%s'; -$lang->doc->menu->module = '維護模組|tree|browse|libID=%s&viewType=doc'; -$lang->doc->menu->delete = array('link' => '刪除文檔庫|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); -$lang->doc->menu->create = array('link' => '新增文檔庫|doc|createLib', 'float' => 'right'); - -/* 組織結構視圖菜單設置。*/ -$lang->company->menu->name = '%s' . $lang->arrow; -$lang->company->menu->browseUser = array('link' => '用戶列表|company|browse', 'subModule' => 'user'); -$lang->company->menu->dept = array('link' => '部門維護|dept|browse', 'subModule' => 'dept'); -$lang->company->menu->browseGroup = array('link' => '權限分組|group|browse', 'subModule' => 'group'); -$lang->company->menu->edit = array('link' => '公司管理|company|edit'); -$lang->company->menu->dynamic = '組織動態|company|dynamic|'; -$lang->company->menu->addGroup = array('link' => '添加分組|group|create', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => '添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; - -/* 用戶信息菜單設置。*/ -$lang->user->menu->account = '%s' . $lang->arrow; -$lang->user->menu->todo = array('link' => 'TODO列表|user|todo|account=%s', 'subModule' => 'todo'); -$lang->user->menu->task = '任務列表|user|task|account=%s'; -$lang->user->menu->bug = 'Bug列表|user|bug|account=%s'; -$lang->user->menu->dynamic = '用戶動態|user|dynamic|type=today&account=%s'; -$lang->user->menu->projectList = '項目列表|user|project|account=%s'; -$lang->user->menu->profile = array('link' => '用戶信息|user|profile|account=%s', 'alias' => 'edit'); -$lang->user->menu->browse = array('link' => '用戶管理|company|browse|', 'float' => 'right'); - -/* 後台管理菜單設置。*/ -$lang->admin->menu->extension = array('link' => '插件管理|extension|browse', 'subModule' => 'extension'); -$lang->admin->menu->editor = array('link' => '擴展編輯器|editor|index', 'subModule' => 'editor'); -$lang->admin->menu->mail = array('link' => 'Email配置|mail|set', 'subModule' => 'mail'); -$lang->admin->menu->convert = array('link' => '從其他系統導入|convert|index', 'subModule' => 'convert'); -$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action'); -$lang->convert->menu = $lang->admin->menu; -$lang->upgrade->menu = $lang->admin->menu; -$lang->action->menu = $lang->admin->menu; -$lang->extension->menu = $lang->admin->menu; -$lang->editor->menu = $lang->admin->menu; -$lang->mail->menu = $lang->admin->menu; - -/*菜單設置:分組設置。*/ -$lang->menugroup->release = 'product'; -$lang->menugroup->story = 'product'; -$lang->menugroup->productplan = 'product'; -$lang->menugroup->task = 'project'; -$lang->menugroup->build = 'project'; -$lang->menugroup->convert = 'admin'; -$lang->menugroup->upgrade = 'admin'; -$lang->menugroup->user = 'company'; -$lang->menugroup->group = 'company'; -$lang->menugroup->bug = 'qa'; -$lang->menugroup->testcase = 'qa'; -$lang->menugroup->testtask = 'qa'; -$lang->menugroup->people = 'company'; -$lang->menugroup->dept = 'company'; -$lang->menugroup->todo = 'my'; -$lang->menugroup->action = 'admin'; -$lang->menugroup->extension = 'admin'; -$lang->menugroup->editor = 'admin'; -$lang->menugroup->mail = 'admin'; - -/* 錯誤提示信息。*/ -$lang->error->companyNotFound = "您訪問的域名 %s 沒有對應的公司。"; -$lang->error->length = array("『%s』長度錯誤,應當為『%s』", "『%s』長度應當不超過『%s』,且不小於『%s』。"); -$lang->error->reg = "『%s』不符合格式,應當為:『%s』。"; -$lang->error->unique = "『%s』已經有『%s』這條記錄了。"; -$lang->error->gt = "『%s』應當大於『%s』。"; -$lang->error->notempty = "『%s』不能為空。"; -$lang->error->empty = "『%s』必須為空。"; -$lang->error->equal = "『%s』必須為『%s』。"; -$lang->error->int = array("『%s』應當是數字。", "『%s』應當介於『%s-%s』之間。"); -$lang->error->float = "『%s』應當是數字,可以是小數。"; -$lang->error->email = "『%s』應當為合法的EMAIL。"; -$lang->error->date = "『%s』應當為合法的日期。"; -$lang->error->account = "『%s』應當為合法的用戶名。"; -$lang->error->passwordsame = "兩次密碼應當相等。"; -$lang->error->passwordrule = "密碼應該符合規則,長度至少為六位。"; -$lang->error->accessDenied = '您沒有訪問權限'; - -/* 分頁信息。*/ -$lang->pager->noRecord = "暫時沒有記錄"; -$lang->pager->digest = "共%s條記錄,每頁 %s條,頁面:%s/%s "; -$lang->pager->first = "首頁"; -$lang->pager->pre = "上頁"; -$lang->pager->next = "下頁"; -$lang->pager->last = "末頁"; -$lang->pager->locate = "GO!"; - -$lang->zentaoSite = "官方網站"; -$lang->chinaScrum = "Scrum社區 "; -$lang->agileTraining = "培訓 "; -$lang->donate = "捐助禪道 "; -$lang->zentaoKeywords = "開源項目管理軟件,項目管理,項目管理軟件,pmp,pms,php框架,國產php框架,scrum工具,scrum管理工具,scrum管理軟件,敏捷項目管理,禪道"; -$lang->zentaoDESC = "禪道項目管理軟件(ZenTaoPMS)是一款國產的,基于LGPL協議,開源免費的項目管理軟件(工具、系統),同時也是一款scrum管理工具。 - 它集產品管理、項目管理、測試管理於一體,同時還包含了事務管理、組織管理等諸多功能,是中小型企業項目管理的首選。禪道項目管理軟件使用PHP + MySQL開發, -基于自主的PHP開發框架──ZenTaoPHP而成。第三方開發者或者企業可以非常方便的開發插件或者進行定製。禪道在手,項目無憂!"; - -/* 時間格式設置。*/ -define('DT_DATETIME1', 'Y-m-d H:i:s'); -define('DT_DATETIME2', 'y-m-d H:i'); -define('DT_MONTHTIME1', 'n/d H:i'); -define('DT_MONTHTIME2', 'n月d日 H:i'); -define('DT_DATE1', 'Y-m-d'); -define('DT_DATE2', 'Ymd'); -define('DT_DATE3', 'Y年m月d日'); -define('DT_DATE4', 'n月j日'); -define('DT_TIME1', 'H:i:s'); -define('DT_TIME2', 'H:i'); + + * @package ZenTaoPMS + * @version $Id: zh-tw.php 2538 2012-01-04 07:25:59Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->arrow = ' » '; +$lang->colon = '::'; +$lang->comma = ','; +$lang->dot = '。'; +$lang->at = ' 于 '; +$lang->downArrow = '↓'; + +$lang->ZenTaoPMS = '禪道管理'; +$lang->welcome = "歡迎使用『%s』{$lang->colon} {$lang->ZenTaoPMS}"; +$lang->myControl = "我的地盤"; +$lang->currentPos = '當前位置:'; +$lang->logout = '退出'; +$lang->login = '登錄'; +$lang->aboutZenTao = '關於'; +$lang->todayIs = '今天是%s,'; +$lang->runInfo = "
時間: %s 毫秒, 內存: %s KB, 查詢: %s.
"; + +$lang->reset = '重填'; +$lang->edit = '編輯'; +$lang->copy = '複製'; +$lang->delete = '刪除'; +$lang->close = '關閉'; +$lang->link = '關聯'; +$lang->unlink = '移除'; +$lang->import = '導入'; +$lang->export = '導出'; +$lang->setFileName = '檔案名:'; +$lang->activate = '激活'; +$lang->submitting = '稍候...'; +$lang->save = '保存'; +$lang->confirm = '確認'; +$lang->preview = '查看'; +$lang->goback = '返回'; +$lang->go = 'GO'; +$lang->more = '更多'; + +$lang->actions = '操作'; +$lang->comment = '備註'; +$lang->history = '歷史記錄'; +$lang->attatch = '附件'; +$lang->reverse = '[切換順序]'; +$lang->switchDisplay= '[切換顯示]'; +$lang->switchHelp = '切換幫助'; +$lang->addFiles = '上傳了附件 '; +$lang->files = '附件 '; +$lang->unfold = '+'; +$lang->fold = '-'; + +$lang->selectAll = '全選'; +$lang->notFound = '抱歉,您訪問的對象並不存在!'; +$lang->showAll = '++ 全部顯示 ++'; +$lang->hideClosed = '-- 隱藏已結束 --'; + +$lang->feature = '未來'; +$lang->year = '年'; +$lang->workingHour = '工時'; + +$lang->idAB = 'ID'; +$lang->priAB = 'P'; +$lang->statusAB = '狀態'; +$lang->openedByAB = '創建'; +$lang->assignedToAB = '指派'; +$lang->typeAB = '類型'; + +$lang->common->common = '公有模組'; + +/* 主導航菜單。*/ +$lang->menu->my = '我的地盤|my|index'; +$lang->menu->product = '產品視圖|product|index'; +$lang->menu->project = '項目視圖|project|index'; +$lang->menu->qa = '測試視圖|qa|index'; +$lang->menu->doc = '文檔視圖|doc|index'; +$lang->menu->company = '組織視圖|company|index'; +$lang->menu->admin = '後台管理|admin|index'; + +/* 查詢條中可以選擇的對象列表。*/ +$lang->searchObjects['bug'] = 'B:Bug'; +$lang->searchObjects['story'] = 'S:需求'; +$lang->searchObjects['task'] = 'T:任務'; +$lang->searchObjects['testcase'] = 'C:用例'; +$lang->searchObjects['project'] = 'P:項目'; +$lang->searchObjects['product'] = 'P:產品'; +$lang->searchObjects['user'] = 'U:用戶'; +$lang->searchObjects['build'] = 'B:Build'; +$lang->searchObjects['release'] = 'R:發佈'; +$lang->searchObjects['productplan'] = 'P:產品計劃'; +$lang->searchObjects['testtask'] = 'T:測試任務'; +$lang->searchObjects['doc'] = 'D:文檔'; +$lang->searchTips = '輸入編號'; + +/* 導出檔案的類型列表。*/ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +/* 風格列表。*/ +$lang->themes['default'] = '預設'; +$lang->themes['green'] = '綠色'; +$lang->themes['red'] = '紅色'; +$lang->themes['classblue'] = '經典藍'; + +/* 首頁菜單設置。*/ +$lang->index->menu->product = '瀏覽產品|product|browse'; +$lang->index->menu->project = '瀏覽項目|project|browse'; + +/* 我的地盤菜單設置。*/ +$lang->my->menu->account = '%s' . $lang->arrow; +$lang->my->menu->index = '首頁|my|index'; +$lang->my->menu->todo = array('link' => '我的TODO|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->task = '我的任務|my|task|'; +$lang->my->menu->bug = '我的Bug|my|bug|'; +$lang->my->menu->testtask = '我的測試|my|testtask|'; +$lang->my->menu->story = '我的需求|my|story|'; +$lang->my->menu->myProject = '我的項目|my|project|'; +$lang->my->menu->dynamic = '我的動態|my|dynamic|'; +$lang->my->menu->profile = array('link' => '我的檔案|my|profile|', 'alias' => 'editprofile'); +$lang->todo->menu = $lang->my->menu; + +/* 產品視圖設置。*/ +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'subModule' => 'story'); +$lang->product->menu->dynamic = '動態|product|dynamic|productID=%s'; +$lang->product->menu->plan = array('link' => '計劃|productplan|browse|productID=%s', 'subModule' => 'productplan'); +$lang->product->menu->release = array('link' => '發佈|release|browse|productID=%s', 'subModule' => 'release'); +$lang->product->menu->roadmap = '路線圖|product|roadmap|productID=%s'; +$lang->product->menu->doc = array('link' => '文檔|product|doc|productID=%s', 'subModule' => 'doc'); +$lang->product->menu->view = '概況|product|view|productID=%s'; +$lang->product->menu->edit = '編輯|product|edit|productID=%s'; +$lang->product->menu->delete = array('link' => '刪除|product|delete|productID=%s', 'target' => 'hiddenwin'); +$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; +$lang->product->menu->create = array('link' => '新增產品|product|create', 'float' => 'right'); +$lang->product->menu->project = array('link' => '項目列表|product|project|status=all&productID=%s', 'float' => 'right'); +$lang->product->menu->all = array('link' => '所有產品|product|index|locate=false', 'float' => 'right'); +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* 項目視圖菜單設置。*/ +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => 'Build|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = '測試任務|project|testtask|projectID=%s'; +$lang->project->menu->burn = '燃盡圖|project|burn|projectID=%s'; +$lang->project->menu->team = array('link' => '團隊|project|team|projectID=%s', 'alias' => 'managemembers'); +$lang->project->menu->doc = array('link' => '文檔|project|doc|porjectID=%s', 'subModule' => 'doc'); +$lang->project->menu->product = '產品|project|manageproducts|projectID=%s'; +$lang->project->menu->linkstory = array('link' => '關聯需求|project|linkstory|projectID=%s'); +$lang->project->menu->view = '概況|project|view|projectID=%s'; +$lang->project->menu->edit = '編輯|project|edit|projectID=%s'; +$lang->project->menu->delete = array('link' => '刪除|project|delete|projectID=%s', 'target' => 'hiddenwin'); +$lang->project->menu->create = array('link' => '新增項目|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => '所有項目|project|index|locate=false', 'float' => 'right'); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA視圖菜單設置。*/ +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report', 'subModule' => 'tree'); +$lang->bug->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,edit'); +$lang->bug->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s'); + +$lang->testcase->menu->product = '%s'; +$lang->testcase->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); +$lang->testcase->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s'); + +$lang->testtask->menu->product = '%s'; +$lang->testtask->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s'); +$lang->testtask->menu->testcase = array('link' => '用例管理|testcase|browse|productID=%s'); +$lang->testtask->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +/* 文檔視圖菜單設置。*/ +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s'); +$lang->doc->menu->edit = '編輯文檔庫|doc|editLib|libID=%s'; +$lang->doc->menu->module = '維護模組|tree|browse|libID=%s&viewType=doc'; +$lang->doc->menu->delete = array('link' => '刪除文檔庫|doc|deleteLib|libID=%s', 'target' => 'hiddenwin'); +$lang->doc->menu->create = array('link' => '新增文檔庫|doc|createLib', 'float' => 'right'); + +/* 組織結構視圖菜單設置。*/ +$lang->company->menu->name = '%s' . $lang->arrow; +$lang->company->menu->browseUser = array('link' => '用戶列表|company|browse', 'subModule' => 'user'); +$lang->company->menu->dept = array('link' => '部門維護|dept|browse', 'subModule' => 'dept'); +$lang->company->menu->browseGroup = array('link' => '權限分組|group|browse', 'subModule' => 'group'); +$lang->company->menu->edit = array('link' => '公司管理|company|edit'); +$lang->company->menu->dynamic = '組織動態|company|dynamic|'; +$lang->company->menu->addGroup = array('link' => '添加分組|group|create', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => '添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; + +/* 用戶信息菜單設置。*/ +$lang->user->menu->account = '%s' . $lang->arrow; +$lang->user->menu->todo = array('link' => 'TODO列表|user|todo|account=%s', 'subModule' => 'todo'); +$lang->user->menu->task = '任務列表|user|task|account=%s'; +$lang->user->menu->bug = 'Bug列表|user|bug|account=%s'; +$lang->user->menu->dynamic = '用戶動態|user|dynamic|type=today&account=%s'; +$lang->user->menu->projectList = '項目列表|user|project|account=%s'; +$lang->user->menu->profile = array('link' => '用戶信息|user|profile|account=%s', 'alias' => 'edit'); +$lang->user->menu->browse = array('link' => '用戶管理|company|browse|', 'float' => 'right'); + +/* 後台管理菜單設置。*/ +$lang->admin->menu->extension = array('link' => '插件管理|extension|browse', 'subModule' => 'extension'); +$lang->admin->menu->editor = array('link' => '擴展編輯器|editor|index', 'subModule' => 'editor'); +$lang->admin->menu->mail = array('link' => 'Email配置|mail|set', 'subModule' => 'mail'); +$lang->admin->menu->convert = array('link' => '從其他系統導入|convert|index', 'subModule' => 'convert'); +$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action'); +$lang->convert->menu = $lang->admin->menu; +$lang->upgrade->menu = $lang->admin->menu; +$lang->action->menu = $lang->admin->menu; +$lang->extension->menu = $lang->admin->menu; +$lang->editor->menu = $lang->admin->menu; +$lang->mail->menu = $lang->admin->menu; + +/*菜單設置:分組設置。*/ +$lang->menugroup->release = 'product'; +$lang->menugroup->story = 'product'; +$lang->menugroup->productplan = 'product'; +$lang->menugroup->task = 'project'; +$lang->menugroup->build = 'project'; +$lang->menugroup->convert = 'admin'; +$lang->menugroup->upgrade = 'admin'; +$lang->menugroup->user = 'company'; +$lang->menugroup->group = 'company'; +$lang->menugroup->bug = 'qa'; +$lang->menugroup->testcase = 'qa'; +$lang->menugroup->testtask = 'qa'; +$lang->menugroup->people = 'company'; +$lang->menugroup->dept = 'company'; +$lang->menugroup->todo = 'my'; +$lang->menugroup->action = 'admin'; +$lang->menugroup->extension = 'admin'; +$lang->menugroup->editor = 'admin'; +$lang->menugroup->mail = 'admin'; + +/* 錯誤提示信息。*/ +$lang->error->companyNotFound = "您訪問的域名 %s 沒有對應的公司。"; +$lang->error->length = array("『%s』長度錯誤,應當為『%s』", "『%s』長度應當不超過『%s』,且不小於『%s』。"); +$lang->error->reg = "『%s』不符合格式,應當為:『%s』。"; +$lang->error->unique = "『%s』已經有『%s』這條記錄了。"; +$lang->error->gt = "『%s』應當大於『%s』。"; +$lang->error->notempty = "『%s』不能為空。"; +$lang->error->empty = "『%s』必須為空。"; +$lang->error->equal = "『%s』必須為『%s』。"; +$lang->error->int = array("『%s』應當是數字。", "『%s』應當介於『%s-%s』之間。"); +$lang->error->float = "『%s』應當是數字,可以是小數。"; +$lang->error->email = "『%s』應當為合法的EMAIL。"; +$lang->error->date = "『%s』應當為合法的日期。"; +$lang->error->account = "『%s』應當為合法的用戶名。"; +$lang->error->passwordsame = "兩次密碼應當相等。"; +$lang->error->passwordrule = "密碼應該符合規則,長度至少為六位。"; +$lang->error->accessDenied = '您沒有訪問權限'; + +/* 分頁信息。*/ +$lang->pager->noRecord = "暫時沒有記錄"; +$lang->pager->digest = "共%s條記錄,每頁 %s條,頁面:%s/%s "; +$lang->pager->first = "首頁"; +$lang->pager->pre = "上頁"; +$lang->pager->next = "下頁"; +$lang->pager->last = "末頁"; +$lang->pager->locate = "GO!"; + +$lang->zentaoSite = "官方網站"; +$lang->chinaScrum = "Scrum社區 "; +$lang->agileTraining = "培訓 "; +$lang->donate = "捐助禪道 "; +$lang->zentaoKeywords = "開源項目管理軟件,項目管理,項目管理軟件,pmp,pms,php框架,國產php框架,scrum工具,scrum管理工具,scrum管理軟件,敏捷項目管理,禪道"; +$lang->zentaoDESC = "禪道項目管理軟件(ZenTaoPMS)是一款國產的,基于LGPL協議,開源免費的項目管理軟件(工具、系統),同時也是一款scrum管理工具。 + 它集產品管理、項目管理、測試管理於一體,同時還包含了事務管理、組織管理等諸多功能,是中小型企業項目管理的首選。禪道項目管理軟件使用PHP + MySQL開發, +基于自主的PHP開發框架──ZenTaoPHP而成。第三方開發者或者企業可以非常方便的開發插件或者進行定製。禪道在手,項目無憂!"; + +/* 時間格式設置。*/ +define('DT_DATETIME1', 'Y-m-d H:i:s'); +define('DT_DATETIME2', 'y-m-d H:i'); +define('DT_MONTHTIME1', 'n/d H:i'); +define('DT_MONTHTIME2', 'n月d日 H:i'); +define('DT_DATE1', 'Y-m-d'); +define('DT_DATE2', 'Ymd'); +define('DT_DATE3', 'Y年m月d日'); +define('DT_DATE4', 'n月j日'); +define('DT_TIME1', 'H:i:s'); +define('DT_TIME2', 'H:i'); diff --git a/module/common/model.php b/module/common/model.php index 10140ec0e8..d2a72b5751 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1,366 +1,366 @@ - - * @package common - * @version $Id$ - * @link http://www.zentao.net - */ -class commonModel extends model -{ - /** - * Start the session. - * - * @access public - * @return void - */ - public function startSession() - { - session_name($this->config->sessionVar); - if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]); - session_start(); - } - - /** - * Set the header info. - * - * @access public - * @return void - */ - public function sendHeader() - { - header("Content-Type: text/html; Language={$this->config->encoding}"); - header("Cache-control: private"); - } - - /** - * Set the commpany. - * - * First, search company by the http host. If not found, search by the default domain. Last, use the first as the default. - * After get the company, save it to session. - * @access public - * @return void - */ - public function setCompany() - { - $httpHost = $this->server->http_host; - if(strpos($httpHost, ":")) - { - $httpHost = explode(":", $httpHost); - $httpHost = $httpHost[0]; - } - - if($this->session->company and $this->session->company->pms == $httpHost) - { - $this->app->company = $this->session->company; - } - else - { - $company = $this->loadModel('company')->getByDomain(); - if(!$company and isset($this->config->default->domain)) $company = $this->company->getByDomain($this->config->default->domain); - if(!$company) $company = $this->company->getFirst(); - if(!$company) $this->app->error(sprintf($this->lang->error->companyNotFound, $httpHost), __FILE__, __LINE__, $exit = true); - $this->session->set('company', $company); - $this->app->company = $company; - } - } - - /** - * Set the user info. - * - * @access public - * @return void - */ - public function setUser() - { - if($this->session->user) - { - $this->app->user = $this->session->user; - } - elseif($this->app->company->guest) - { - $user = new stdClass(); - $user->id = 0; - $user->account = 'guest'; - $user->realname = 'guest'; - $user->rights = $this->loadModel('user')->authorize('guest'); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - } - } - - /** - * Juage a method of one module is open or not? - * - * @param string $module - * @param string $method - * @access public - * @return bool - */ - public function isOpenMethod($module, $method) - { - if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true; - if($module == 'api' and $method == 'getsessionid') return true; - if($module == 'misc' and $method == 'about') return true; - if($module == 'help' and $method == 'field') return true; - return false; - } - - /** - * Deny access. - * - * @access public - * @return void - */ - public function deny($module, $method) - { - $vars = "module=$module&method=$method"; - if(isset($this->server->http_referer)) - { - $referer = helper::safe64Encode($this->server->http_referer); - $vars .= "&referer=$referer"; - } - $denyLink = helper::createLink('user', 'deny', $vars); - - /* Fix the bug of IE: use js locate, can't get the referer. */ - if(strpos($this->server->http_user_agent, 'MSIE') !== false) - { - echo ""; - echo ""; - } - else - { - echo js::locate($denyLink); - } - exit; - } - - /** - * Get the run info. - * - * @param mixed $startTime the start time of this execution - * @access public - * @return array the run info array. - */ - public function getRunInfo($startTime) - { - $info['timeUsed'] = round(getTime() - $startTime, 4) * 1000; - $info['memory'] = round(memory_get_peak_usage() / 1024, 1); - $info['querys'] = count(dao::$querys); - return $info; - } - - /** - * Print top bar. - * - * @static - * @access public - * @return void - */ - public static function printTopBar() - { - global $lang, $app; - - printf($lang->todayIs, date(DT_DATE3)); - if(isset($app->user)) echo $app->user->realname . ' '; - if(isset($app->user) and $app->user->account != 'guest') - { - echo html::a(helper::createLink('my', 'index'), $lang->myControl); - echo html::a(helper::createLink('user', 'logout'), $lang->logout); - } - else - { - echo html::a(helper::createLink('user', 'login'), $lang->login); - } - echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'"); - echo $lang->agileTraining; - echo $lang->donate; - } - - /** - * Print the main menu. - * - * @param string $moduleName - * @static - * @access public - * @return void - */ - public static function printMainmenu($moduleName) - { - global $app, $lang; - echo "
    \n"; - - /* Set the main main menu. */ - $mainMenu = $moduleName; - if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName; - - /* Print all main menus. */ - foreach($lang->menu as $menuKey => $menu) - { - $active = $menuKey == $mainMenu ? "class='active'" : ''; - list($menuLabel, $module, $method) = explode('|', $menu); - - if(common::hasPriv($module, $method)) - { - $link = helper::createLink($module, $method); - echo "
  • $menuLabel
  • \n"; - } - } - - } - - /** - * Print the search box. - * - * @static - * @access public - * @return void - */ - public static function printSearchBox() - { - global $app, $lang; - $moduleName = $app->getModuleName(); - $methodName = $app->getMethodName(); - $searchObject = $moduleName; - - if($moduleName == 'product') - { - if($methodName == 'browse') $searchObject = 'story'; - } - elseif($moduleName == 'project') - { - if(strpos('task|story|bug|build', $methodName) !== false) $searchObject = $methodName; - } - elseif($moduleName == 'my' or $moduleName == 'user') - { - $searchObject = $methodName; - } - - echo ""; - echo "
\n"; - } - - /** - * Print the module menu. - * - * @param string $moduleName - * @static - * @access public - * @return void - */ - public static function printModuleMenu($moduleName) - { - global $lang, $app; - - if(!isset($lang->$moduleName->menu)) {echo "
    "; return;} - - /* Get the sub menus of the module, and get current module and method. */ - $submenus = $lang->$moduleName->menu; - $currentModule = $app->getModuleName(); - $currentMethod = $app->getMethodName(); - - /* The beginning of the menu. */ - echo "
      \n"; - - /* Cycling to print every sub menus. */ - foreach($submenus as $subMenuKey => $submenu) - { - /* Init the these vars. */ - $link = $submenu; - $subModule = ''; - $alias = ''; - $float = ''; - $active = ''; - $target = ''; - - if(is_array($submenu)) extract($submenu); // If the sub menu is an array, extract it. - - /* Print the menu. */ - if(strpos($link, '|') === false) - { - echo "
    • $link
    • \n"; - } - else - { - $link = explode('|', $link); - list($label, $module, $method) = $link; - $vars = isset($link[3]) ? $link[3] : ''; - if(common::hasPriv($module, $method)) - { - /* Is the currentModule active? */ - if($currentModule == $subModule) $active = 'active'; - if($module == $currentModule and ($method == $currentMethod or strpos($alias, $currentMethod) !== false)) $active = 'active'; - echo "
    • " . html::a(helper::createLink($module, $method, $vars), $label, $target, "id=submenu$subMenuKey") . "
    • \n"; - } - } - } - echo "
    \n"; - } - - /** - * Print the bread menu. - * - * @param string $moduleName - * @param string $position - * @static - * @access public - * @return void - */ - public static function printBreadMenu($moduleName, $position) - { - global $lang; - $mainMenu = $moduleName; - if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName; - echo html::a(helper::createLink('my', 'index'), $lang->ZenTaoPMS) . $lang->arrow; - if($moduleName != 'index') - { - list($menuLabel, $module, $method) = explode('|', $lang->menu->$mainMenu); - echo html::a(helper::createLink($module, $method), $menuLabel); - } - else - { - echo $lang->index->common; - } - if(empty($position)) return; - echo $lang->arrow; - foreach($position as $key => $link) - { - echo $link; - if(isset($position[$key + 1])) echo $lang->arrow; - } - } - - - /** - * Diff two string. (see phpt) - * - * @param string $text1 - * @param string $text2 - * @static - * @access public - * @return string - */ - public static function diff($text1, $text2) - { - $text1 = str_replace(' ', '', trim($text1)); - $text2 = str_replace(' ', '', trim($text2)); - $w = explode("\n", $text1); - $o = explode("\n", $text2); - $w1 = array_diff_assoc($w,$o); - $o1 = array_diff_assoc($o,$w); - $w2 = array(); - $o2 = array(); - foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1) . "" . trim($val) . ""; - foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1) . "" . trim($val) . ""; - $diff = array_merge($w2, $o2); - ksort($diff); - return implode("\n", $diff); - } -} + + * @package common + * @version $Id$ + * @link http://www.zentao.net + */ +class commonModel extends model +{ + /** + * Start the session. + * + * @access public + * @return void + */ + public function startSession() + { + session_name($this->config->sessionVar); + if(isset($_GET[$this->config->sessionVar])) session_id($_GET[$this->config->sessionVar]); + session_start(); + } + + /** + * Set the header info. + * + * @access public + * @return void + */ + public function sendHeader() + { + header("Content-Type: text/html; Language={$this->config->encoding}"); + header("Cache-control: private"); + } + + /** + * Set the commpany. + * + * First, search company by the http host. If not found, search by the default domain. Last, use the first as the default. + * After get the company, save it to session. + * @access public + * @return void + */ + public function setCompany() + { + $httpHost = $this->server->http_host; + if(strpos($httpHost, ":")) + { + $httpHost = explode(":", $httpHost); + $httpHost = $httpHost[0]; + } + + if($this->session->company and $this->session->company->pms == $httpHost) + { + $this->app->company = $this->session->company; + } + else + { + $company = $this->loadModel('company')->getByDomain(); + if(!$company and isset($this->config->default->domain)) $company = $this->company->getByDomain($this->config->default->domain); + if(!$company) $company = $this->company->getFirst(); + if(!$company) $this->app->error(sprintf($this->lang->error->companyNotFound, $httpHost), __FILE__, __LINE__, $exit = true); + $this->session->set('company', $company); + $this->app->company = $company; + } + } + + /** + * Set the user info. + * + * @access public + * @return void + */ + public function setUser() + { + if($this->session->user) + { + $this->app->user = $this->session->user; + } + elseif($this->app->company->guest) + { + $user = new stdClass(); + $user->id = 0; + $user->account = 'guest'; + $user->realname = 'guest'; + $user->rights = $this->loadModel('user')->authorize('guest'); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + } + } + + /** + * Juage a method of one module is open or not? + * + * @param string $module + * @param string $method + * @access public + * @return bool + */ + public function isOpenMethod($module, $method) + { + if($module == 'user' and strpos('login|logout|deny', $method) !== false) return true; + if($module == 'api' and $method == 'getsessionid') return true; + if($module == 'misc' and $method == 'about') return true; + if($module == 'help' and $method == 'field') return true; + return false; + } + + /** + * Deny access. + * + * @access public + * @return void + */ + public function deny($module, $method) + { + $vars = "module=$module&method=$method"; + if(isset($this->server->http_referer)) + { + $referer = helper::safe64Encode($this->server->http_referer); + $vars .= "&referer=$referer"; + } + $denyLink = helper::createLink('user', 'deny', $vars); + + /* Fix the bug of IE: use js locate, can't get the referer. */ + if(strpos($this->server->http_user_agent, 'MSIE') !== false) + { + echo ""; + echo ""; + } + else + { + echo js::locate($denyLink); + } + exit; + } + + /** + * Get the run info. + * + * @param mixed $startTime the start time of this execution + * @access public + * @return array the run info array. + */ + public function getRunInfo($startTime) + { + $info['timeUsed'] = round(getTime() - $startTime, 4) * 1000; + $info['memory'] = round(memory_get_peak_usage() / 1024, 1); + $info['querys'] = count(dao::$querys); + return $info; + } + + /** + * Print top bar. + * + * @static + * @access public + * @return void + */ + public static function printTopBar() + { + global $lang, $app; + + printf($lang->todayIs, date(DT_DATE3)); + if(isset($app->user)) echo $app->user->realname . ' '; + if(isset($app->user) and $app->user->account != 'guest') + { + echo html::a(helper::createLink('my', 'index'), $lang->myControl); + echo html::a(helper::createLink('user', 'logout'), $lang->logout); + } + else + { + echo html::a(helper::createLink('user', 'login'), $lang->login); + } + echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'"); + echo $lang->agileTraining; + echo $lang->donate; + } + + /** + * Print the main menu. + * + * @param string $moduleName + * @static + * @access public + * @return void + */ + public static function printMainmenu($moduleName) + { + global $app, $lang; + echo "
      \n"; + + /* Set the main main menu. */ + $mainMenu = $moduleName; + if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName; + + /* Print all main menus. */ + foreach($lang->menu as $menuKey => $menu) + { + $active = $menuKey == $mainMenu ? "class='active'" : ''; + list($menuLabel, $module, $method) = explode('|', $menu); + + if(common::hasPriv($module, $method)) + { + $link = helper::createLink($module, $method); + echo "
    • $menuLabel
    • \n"; + } + } + + } + + /** + * Print the search box. + * + * @static + * @access public + * @return void + */ + public static function printSearchBox() + { + global $app, $lang; + $moduleName = $app->getModuleName(); + $methodName = $app->getMethodName(); + $searchObject = $moduleName; + + if($moduleName == 'product') + { + if($methodName == 'browse') $searchObject = 'story'; + } + elseif($moduleName == 'project') + { + if(strpos('task|story|bug|build', $methodName) !== false) $searchObject = $methodName; + } + elseif($moduleName == 'my' or $moduleName == 'user') + { + $searchObject = $methodName; + } + + echo ""; + echo "
    \n"; + } + + /** + * Print the module menu. + * + * @param string $moduleName + * @static + * @access public + * @return void + */ + public static function printModuleMenu($moduleName) + { + global $lang, $app; + + if(!isset($lang->$moduleName->menu)) {echo "
      "; return;} + + /* Get the sub menus of the module, and get current module and method. */ + $submenus = $lang->$moduleName->menu; + $currentModule = $app->getModuleName(); + $currentMethod = $app->getMethodName(); + + /* The beginning of the menu. */ + echo "
        \n"; + + /* Cycling to print every sub menus. */ + foreach($submenus as $subMenuKey => $submenu) + { + /* Init the these vars. */ + $link = $submenu; + $subModule = ''; + $alias = ''; + $float = ''; + $active = ''; + $target = ''; + + if(is_array($submenu)) extract($submenu); // If the sub menu is an array, extract it. + + /* Print the menu. */ + if(strpos($link, '|') === false) + { + echo "
      • $link
      • \n"; + } + else + { + $link = explode('|', $link); + list($label, $module, $method) = $link; + $vars = isset($link[3]) ? $link[3] : ''; + if(common::hasPriv($module, $method)) + { + /* Is the currentModule active? */ + if($currentModule == $subModule) $active = 'active'; + if($module == $currentModule and ($method == $currentMethod or strpos($alias, $currentMethod) !== false)) $active = 'active'; + echo "
      • " . html::a(helper::createLink($module, $method, $vars), $label, $target, "id=submenu$subMenuKey") . "
      • \n"; + } + } + } + echo "
      \n"; + } + + /** + * Print the bread menu. + * + * @param string $moduleName + * @param string $position + * @static + * @access public + * @return void + */ + public static function printBreadMenu($moduleName, $position) + { + global $lang; + $mainMenu = $moduleName; + if(isset($lang->menugroup->$moduleName)) $mainMenu = $lang->menugroup->$moduleName; + echo html::a(helper::createLink('my', 'index'), $lang->ZenTaoPMS) . $lang->arrow; + if($moduleName != 'index') + { + list($menuLabel, $module, $method) = explode('|', $lang->menu->$mainMenu); + echo html::a(helper::createLink($module, $method), $menuLabel); + } + else + { + echo $lang->index->common; + } + if(empty($position)) return; + echo $lang->arrow; + foreach($position as $key => $link) + { + echo $link; + if(isset($position[$key + 1])) echo $lang->arrow; + } + } + + + /** + * Diff two string. (see phpt) + * + * @param string $text1 + * @param string $text2 + * @static + * @access public + * @return string + */ + public static function diff($text1, $text2) + { + $text1 = str_replace(' ', '', trim($text1)); + $text2 = str_replace(' ', '', trim($text2)); + $w = explode("\n", $text1); + $o = explode("\n", $text2); + $w1 = array_diff_assoc($w,$o); + $o1 = array_diff_assoc($o,$w); + $w2 = array(); + $o2 = array(); + foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1) . "" . trim($val) . ""; + foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1) . "" . trim($val) . ""; + $diff = array_merge($w2, $o2); + ksort($diff); + return implode("\n", $diff); + } +} diff --git a/module/company/control.php b/module/company/control.php index b06dbf33f0..95a21cc407 100644 --- a/module/company/control.php +++ b/module/company/control.php @@ -1,236 +1,236 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -class company extends control -{ - /** - * Construct function, load dept and user models auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('dept'); - $this->app->loadLang('user'); - $this->company->setMenu(); - } - - /** - * Index page, header to browse. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('company', 'browse')); - } - - /** - * Browse departments and users of a company. - * - * @param int $deptID - * @access public - * @return void - */ - public function browse($deptID = 0) - { - $this->lang->set('menugroup.company', 'company'); - $childDeptIds = $this->dept->getAllChildID($deptID); - - $this->company->setMenu($deptID); - - $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common; - $position[] = $this->lang->dept->common; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->users = $this->dept->getUsers($childDeptIds); - $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink')); - $this->view->parentDepts = $this->dept->getParents($deptID); - $this->view->deptID = $deptID; - - $this->display(); - } - - /** - * Create a company. - * - * @access public - * @return void - */ - public function create() - { - if(!empty($_POST)) - { - $this->company->create(); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('admin', 'browsecompany'), 'parent')); - } - - $this->lang->set('menugroup.company', 'admin'); - $this->lang->company->menu = $this->lang->admin->menu; - - $header['title'] = $this->lang->admin->common . $this->lang->colon . $this->lang->company->create; - $position[] = html::a($this->createLink('admin', 'browsecompany'), $this->lang->admin->company); - $position[] = $this->lang->company->create; - $this->view->header = $header; - $this->view->position = $position; - - $this->display(); - } - - /** - * Edit a company. - * - * @access public - * @return void - */ - public function edit() - { - if(!empty($_POST)) - { - $this->company->update(); - if(dao::isError()) die(js::error(dao::getError())); - die(js::alert($this->lang->company->successSaved)); - } - - $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->company->edit; - $position[] = $this->lang->company->edit; - $this->view->header = $header; - $this->view->position = $position; - $this->view->company = $this->company->getById($this->app->company->id); - - $this->display(); - } - - /** - * Delete a company. - * - * @param int $companyID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($companyID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->company->confirmDelete, $this->createLink('company', 'delete', "companyID=$companyID&confirm=yes")); - exit; - } - else - { - $this->company->delete($companyID); - echo js::locate($this->createLink('admin', 'browseCompany'), 'parent'); - exit; - } - } - - /** - * Company dynamic. - * - * @param string $browseType - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function dynamic($browseType = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->app->loadLang('user'); - $this->app->loadLang('project'); - $this->loadModel('action'); - - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('productList', $uri); - $this->session->set('productPlanList', $uri); - $this->session->set('releaseList', $uri); - $this->session->set('storyList', $uri); - $this->session->set('projectList', $uri); - $this->session->set('taskList', $uri); - $this->session->set('buildList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('caseList', $uri); - $this->session->set('testtaskList', $uri); - - /* Set the pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - /* Set the user and type. */ - $account = $browseType == 'account' ? $param : 'all'; - $product = $browseType == 'product' ? $param : 'all'; - $project = $browseType == 'project' ? $param : 'all'; - $period = ($browseType == 'account' or $browseType == 'product' or $browseType == 'project') ? 'all' : $browseType; - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Get products' list.*/ - $products = $this->loadModel('product')->getPairs(); - $products = array($this->lang->product->select) + $products; - $this->view->products = $products; - - /* Get projects' list.*/ - $projects = $this->loadModel('project')->getPairs(); - $projects = array($this->lang->project->select) + $projects; - $this->view->projects = $projects; - - /* Get users.*/ - $users = $this->loadModel('user')->getPairs('nodeleted|noletter|noclosed'); - $users[''] = $this->lang->user->select; - $this->view->users = $users; - - /* The header and position. */ - $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic; - $this->view->position[] = $this->lang->company->dynamic; - - /* Get actions. */ - if($browseType != 'bysearch') - { - $actions = $this->action->getDynamic($account, $period, $orderBy, $pager, $product, $project); - } - else - { - $actions = $this->action->getDynamicBySearch($products, $projects, $queryID, $orderBy, $pager); - } - - /* Build search form. */ - $projects[0] = ''; - $products[0] = ''; - $users[''] = ''; - ksort($projects); - ksort($products); - $projects['all'] = $this->lang->project->allProject; - $products['all'] = $this->lang->product->allProduct; - $this->config->company->dynamic->search['actionURL'] = $this->createLink('company', 'dynamic', "browseType=bysearch¶m=myQueryID"); - $this->config->company->dynamic->search['queryID'] = $queryID; - $this->config->company->dynamic->search['params']['project']['values'] = $projects; - $this->config->company->dynamic->search['params']['product']['values'] = $products; - $this->config->company->dynamic->search['params']['actor']['values'] = $users; - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->dynamic->search); - - /* Assign. */ - $this->view->browseType = $browseType; - $this->view->account = $account; - $this->view->product = $product; - $this->view->project = $project; - $this->view->queryID = $queryID; - $this->view->actions = $actions; - $this->display(); - } -} + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +class company extends control +{ + /** + * Construct function, load dept and user models auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('dept'); + $this->app->loadLang('user'); + $this->company->setMenu(); + } + + /** + * Index page, header to browse. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('company', 'browse')); + } + + /** + * Browse departments and users of a company. + * + * @param int $deptID + * @access public + * @return void + */ + public function browse($deptID = 0) + { + $this->lang->set('menugroup.company', 'company'); + $childDeptIds = $this->dept->getAllChildID($deptID); + + $this->company->setMenu($deptID); + + $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common; + $position[] = $this->lang->dept->common; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->users = $this->dept->getUsers($childDeptIds); + $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink')); + $this->view->parentDepts = $this->dept->getParents($deptID); + $this->view->deptID = $deptID; + + $this->display(); + } + + /** + * Create a company. + * + * @access public + * @return void + */ + public function create() + { + if(!empty($_POST)) + { + $this->company->create(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('admin', 'browsecompany'), 'parent')); + } + + $this->lang->set('menugroup.company', 'admin'); + $this->lang->company->menu = $this->lang->admin->menu; + + $header['title'] = $this->lang->admin->common . $this->lang->colon . $this->lang->company->create; + $position[] = html::a($this->createLink('admin', 'browsecompany'), $this->lang->admin->company); + $position[] = $this->lang->company->create; + $this->view->header = $header; + $this->view->position = $position; + + $this->display(); + } + + /** + * Edit a company. + * + * @access public + * @return void + */ + public function edit() + { + if(!empty($_POST)) + { + $this->company->update(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::alert($this->lang->company->successSaved)); + } + + $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->company->edit; + $position[] = $this->lang->company->edit; + $this->view->header = $header; + $this->view->position = $position; + $this->view->company = $this->company->getById($this->app->company->id); + + $this->display(); + } + + /** + * Delete a company. + * + * @param int $companyID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($companyID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->company->confirmDelete, $this->createLink('company', 'delete', "companyID=$companyID&confirm=yes")); + exit; + } + else + { + $this->company->delete($companyID); + echo js::locate($this->createLink('admin', 'browseCompany'), 'parent'); + exit; + } + } + + /** + * Company dynamic. + * + * @param string $browseType + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function dynamic($browseType = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->app->loadLang('user'); + $this->app->loadLang('project'); + $this->loadModel('action'); + + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('productList', $uri); + $this->session->set('productPlanList', $uri); + $this->session->set('releaseList', $uri); + $this->session->set('storyList', $uri); + $this->session->set('projectList', $uri); + $this->session->set('taskList', $uri); + $this->session->set('buildList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('caseList', $uri); + $this->session->set('testtaskList', $uri); + + /* Set the pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + /* Set the user and type. */ + $account = $browseType == 'account' ? $param : 'all'; + $product = $browseType == 'product' ? $param : 'all'; + $project = $browseType == 'project' ? $param : 'all'; + $period = ($browseType == 'account' or $browseType == 'product' or $browseType == 'project') ? 'all' : $browseType; + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Get products' list.*/ + $products = $this->loadModel('product')->getPairs(); + $products = array($this->lang->product->select) + $products; + $this->view->products = $products; + + /* Get projects' list.*/ + $projects = $this->loadModel('project')->getPairs(); + $projects = array($this->lang->project->select) + $projects; + $this->view->projects = $projects; + + /* Get users.*/ + $users = $this->loadModel('user')->getPairs('nodeleted|noletter|noclosed'); + $users[''] = $this->lang->user->select; + $this->view->users = $users; + + /* The header and position. */ + $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic; + $this->view->position[] = $this->lang->company->dynamic; + + /* Get actions. */ + if($browseType != 'bysearch') + { + $actions = $this->action->getDynamic($account, $period, $orderBy, $pager, $product, $project); + } + else + { + $actions = $this->action->getDynamicBySearch($products, $projects, $queryID, $orderBy, $pager); + } + + /* Build search form. */ + $projects[0] = ''; + $products[0] = ''; + $users[''] = ''; + ksort($projects); + ksort($products); + $projects['all'] = $this->lang->project->allProject; + $products['all'] = $this->lang->product->allProduct; + $this->config->company->dynamic->search['actionURL'] = $this->createLink('company', 'dynamic', "browseType=bysearch¶m=myQueryID"); + $this->config->company->dynamic->search['queryID'] = $queryID; + $this->config->company->dynamic->search['params']['project']['values'] = $projects; + $this->config->company->dynamic->search['params']['product']['values'] = $products; + $this->config->company->dynamic->search['params']['actor']['values'] = $users; + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->dynamic->search); + + /* Assign. */ + $this->view->browseType = $browseType; + $this->view->account = $account; + $this->view->product = $product; + $this->view->project = $project; + $this->view->queryID = $queryID; + $this->view->actions = $actions; + $this->display(); + } +} diff --git a/module/company/lang/en.php b/module/company/lang/en.php index c6c9c03433..8f06fc3b8f 100644 --- a/module/company/lang/en.php +++ b/module/company/lang/en.php @@ -1,39 +1,39 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->company->common = 'Company'; -$lang->company->index = "Index"; -$lang->company->create = "Create"; -$lang->company->edit = "Edit"; -$lang->company->read = "Info"; -$lang->company->update = "Update"; -$lang->company->delete = "Delete"; -$lang->company->browse = "User"; -$lang->company->dynamic = "Dynamic"; -$lang->company->depts = "Dept"; -$lang->company->orgView = 'Company'; - -$lang->company->confirmDelete = "Are you sure to delete this company?"; -$lang->company->successSaved = "Success saved"; - -$lang->company->id = 'ID'; -$lang->company->name = 'Name'; -$lang->company->phone = 'Phone'; -$lang->company->fax = 'Fax'; -$lang->company->address = 'Address'; -$lang->company->zipcode = 'Zipcode'; -$lang->company->website = 'Web site'; -$lang->company->backyard = 'Internal Site'; -$lang->company->pms = 'ZenTaoPMS Site'; -$lang->company->guest = 'Guest visit'; - -$lang->company->guestList[0] = 'Deny'; -$lang->company->guestList[1] = 'Allow'; + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->company->common = 'Company'; +$lang->company->index = "Index"; +$lang->company->create = "Create"; +$lang->company->edit = "Edit"; +$lang->company->read = "Info"; +$lang->company->update = "Update"; +$lang->company->delete = "Delete"; +$lang->company->browse = "User"; +$lang->company->dynamic = "Dynamic"; +$lang->company->depts = "Dept"; +$lang->company->orgView = 'Company'; + +$lang->company->confirmDelete = "Are you sure to delete this company?"; +$lang->company->successSaved = "Success saved"; + +$lang->company->id = 'ID'; +$lang->company->name = 'Name'; +$lang->company->phone = 'Phone'; +$lang->company->fax = 'Fax'; +$lang->company->address = 'Address'; +$lang->company->zipcode = 'Zipcode'; +$lang->company->website = 'Web site'; +$lang->company->backyard = 'Internal Site'; +$lang->company->pms = 'ZenTaoPMS Site'; +$lang->company->guest = 'Guest visit'; + +$lang->company->guestList[0] = 'Deny'; +$lang->company->guestList[1] = 'Allow'; diff --git a/module/company/lang/zh-cn.php b/module/company/lang/zh-cn.php index ae937f1c60..19e2b7c517 100644 --- a/module/company/lang/zh-cn.php +++ b/module/company/lang/zh-cn.php @@ -1,39 +1,39 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->company->common = '组织视图'; -$lang->company->index = "组织视图首页"; -$lang->company->create = "新增公司"; -$lang->company->edit = "编辑公司"; -$lang->company->read = "公司信息"; -$lang->company->update = "更新公司"; -$lang->company->delete = "删除公司"; -$lang->company->browse = "用户列表"; -$lang->company->dynamic = "组织动态"; -$lang->company->depts = "部门列表"; -$lang->company->orgView = '组织视图'; - -$lang->company->confirmDelete = "您确定删除该公司吗?"; -$lang->company->successSaved = "成功保存"; - -$lang->company->id = '编号'; -$lang->company->name = '公司名称'; -$lang->company->phone = '联系电话'; -$lang->company->fax = '传真'; -$lang->company->address = '通讯地址'; -$lang->company->zipcode = '邮政编码'; -$lang->company->website = '公司网站'; -$lang->company->backyard = '公司内网'; -$lang->company->pms = 'PMS网站'; -$lang->company->guest = '匿名登录'; - -$lang->company->guestList[0] = '不允许'; -$lang->company->guestList[1] = '允许'; + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->company->common = '组织视图'; +$lang->company->index = "组织视图首页"; +$lang->company->create = "新增公司"; +$lang->company->edit = "编辑公司"; +$lang->company->read = "公司信息"; +$lang->company->update = "更新公司"; +$lang->company->delete = "删除公司"; +$lang->company->browse = "用户列表"; +$lang->company->dynamic = "组织动态"; +$lang->company->depts = "部门列表"; +$lang->company->orgView = '组织视图'; + +$lang->company->confirmDelete = "您确定删除该公司吗?"; +$lang->company->successSaved = "成功保存"; + +$lang->company->id = '编号'; +$lang->company->name = '公司名称'; +$lang->company->phone = '联系电话'; +$lang->company->fax = '传真'; +$lang->company->address = '通讯地址'; +$lang->company->zipcode = '邮政编码'; +$lang->company->website = '公司网站'; +$lang->company->backyard = '公司内网'; +$lang->company->pms = 'PMS网站'; +$lang->company->guest = '匿名登录'; + +$lang->company->guestList[0] = '不允许'; +$lang->company->guestList[1] = '允许'; diff --git a/module/company/lang/zh-tw.php b/module/company/lang/zh-tw.php index 2e378dae39..e9826c8519 100644 --- a/module/company/lang/zh-tw.php +++ b/module/company/lang/zh-tw.php @@ -1,39 +1,39 @@ - - * @package company - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->company->common = '組織視圖'; -$lang->company->index = "組織視圖首頁"; -$lang->company->create = "新增公司"; -$lang->company->edit = "編輯公司"; -$lang->company->read = "公司信息"; -$lang->company->update = "更新公司"; -$lang->company->delete = "刪除公司"; -$lang->company->browse = "用戶列表"; -$lang->company->dynamic = "組織動態"; -$lang->company->depts = "部門列表"; -$lang->company->orgView = '組織視圖'; - -$lang->company->confirmDelete = "您確定刪除該公司嗎?"; -$lang->company->successSaved = "成功保存"; - -$lang->company->id = '編號'; -$lang->company->name = '公司名稱'; -$lang->company->phone = '聯繫電話'; -$lang->company->fax = '傳真'; -$lang->company->address = '通訊地址'; -$lang->company->zipcode = '郵政編碼'; -$lang->company->website = '公司網站'; -$lang->company->backyard = '公司內網'; -$lang->company->pms = 'PMS網站'; -$lang->company->guest = '匿名登錄'; - -$lang->company->guestList[0] = '不允許'; -$lang->company->guestList[1] = '允許'; + + * @package company + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->company->common = '組織視圖'; +$lang->company->index = "組織視圖首頁"; +$lang->company->create = "新增公司"; +$lang->company->edit = "編輯公司"; +$lang->company->read = "公司信息"; +$lang->company->update = "更新公司"; +$lang->company->delete = "刪除公司"; +$lang->company->browse = "用戶列表"; +$lang->company->dynamic = "組織動態"; +$lang->company->depts = "部門列表"; +$lang->company->orgView = '組織視圖'; + +$lang->company->confirmDelete = "您確定刪除該公司嗎?"; +$lang->company->successSaved = "成功保存"; + +$lang->company->id = '編號'; +$lang->company->name = '公司名稱'; +$lang->company->phone = '聯繫電話'; +$lang->company->fax = '傳真'; +$lang->company->address = '通訊地址'; +$lang->company->zipcode = '郵政編碼'; +$lang->company->website = '公司網站'; +$lang->company->backyard = '公司內網'; +$lang->company->pms = 'PMS網站'; +$lang->company->guest = '匿名登錄'; + +$lang->company->guestList[0] = '不允許'; +$lang->company->guestList[1] = '允許'; diff --git a/module/company/model.php b/module/company/model.php index 16e668886b..edb774aa87 100644 --- a/module/company/model.php +++ b/module/company/model.php @@ -1,123 +1,123 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -?> -lang->company->menu, 'name', array($this->app->company->name)); - common::setMenuVars($this->lang->company->menu, 'addUser', array($dept)); - } - - /** - * Get company list. - * - * @access public - * @return void - */ - public function getList() - { - return $this->dao->select('*')->from(TABLE_COMPANY)->fetchAll(); - } - - /** - * Get the first company. - * - * @access public - * @return void - */ - public function getFirst() - { - return $this->dao->select('*')->from(TABLE_COMPANY)->orderBy('id')->limit(1)->fetch(); - } - - /** - * get company by domain. - * - * @param string $domain if empty, use current HTTP_HOST. - * @access public - * @return object - */ - public function getByDomain($domain = '') - { - if(empty($domain)) $domain = $this->server->http_host; - return $this->dao->findByPMS($domain)->from(TABLE_COMPANY)->fetch(); - } - - /** - * Get company info by id. - * - * @param int $companyID - * @access public - * @return object - */ - public function getByID($companyID = '') - { - return $this->dao->findById((int)$companyID)->from(TABLE_COMPANY)->fetch(); - } - - /** - * Create a company. - * - * @access public - * @return void - */ - public function create() - { - $company = fixer::input('post')->get(); - $this->dao->insert(TABLE_COMPANY) - ->data($company) - ->autoCheck() - ->batchCheck($this->config->company->create->requiredFields, 'notempty') - ->batchCheck('name,pms', 'unique') - ->exec(); - } - - /** - * Update a company. - * - * @access public - * @return void - */ - public function update() - { - $company = fixer::input('post')->stripTags('name')->get(); - $companyID = $this->app->company->id; - $this->dao->update(TABLE_COMPANY) - ->data($company) - ->autoCheck() - ->batchCheck($this->config->company->edit->requiredFields, 'notempty') - ->batchCheck('name,pms', 'unique', "id != '$companyID'") - ->where('id')->eq($companyID) - ->exec(); - } - - /** - * Delete a company. - * - * @param int $companyID - * @access public - * @return void - */ - public function delete($companyID) - { - return $this->dao->delete()->from(TABLE_COMPANY)->where('id')->eq((int)$companyID)->limit(1)->exec(); - } -} + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +?> +lang->company->menu, 'name', array($this->app->company->name)); + common::setMenuVars($this->lang->company->menu, 'addUser', array($dept)); + } + + /** + * Get company list. + * + * @access public + * @return void + */ + public function getList() + { + return $this->dao->select('*')->from(TABLE_COMPANY)->fetchAll(); + } + + /** + * Get the first company. + * + * @access public + * @return void + */ + public function getFirst() + { + return $this->dao->select('*')->from(TABLE_COMPANY)->orderBy('id')->limit(1)->fetch(); + } + + /** + * get company by domain. + * + * @param string $domain if empty, use current HTTP_HOST. + * @access public + * @return object + */ + public function getByDomain($domain = '') + { + if(empty($domain)) $domain = $this->server->http_host; + return $this->dao->findByPMS($domain)->from(TABLE_COMPANY)->fetch(); + } + + /** + * Get company info by id. + * + * @param int $companyID + * @access public + * @return object + */ + public function getByID($companyID = '') + { + return $this->dao->findById((int)$companyID)->from(TABLE_COMPANY)->fetch(); + } + + /** + * Create a company. + * + * @access public + * @return void + */ + public function create() + { + $company = fixer::input('post')->get(); + $this->dao->insert(TABLE_COMPANY) + ->data($company) + ->autoCheck() + ->batchCheck($this->config->company->create->requiredFields, 'notempty') + ->batchCheck('name,pms', 'unique') + ->exec(); + } + + /** + * Update a company. + * + * @access public + * @return void + */ + public function update() + { + $company = fixer::input('post')->stripTags('name')->get(); + $companyID = $this->app->company->id; + $this->dao->update(TABLE_COMPANY) + ->data($company) + ->autoCheck() + ->batchCheck($this->config->company->edit->requiredFields, 'notempty') + ->batchCheck('name,pms', 'unique', "id != '$companyID'") + ->where('id')->eq($companyID) + ->exec(); + } + + /** + * Delete a company. + * + * @param int $companyID + * @access public + * @return void + */ + public function delete($companyID) + { + return $this->dao->delete()->from(TABLE_COMPANY)->where('id')->eq((int)$companyID)->limit(1)->exec(); + } +} diff --git a/module/company/view/browse.html.php b/module/company/view/browse.html.php index 6a721cffdd..7598007955 100644 --- a/module/company/view/browse.html.php +++ b/module/company/view/browse.html.php @@ -1,78 +1,78 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
      -
      dept->common;?>
      -
      - -
      - user->create);echo '
      '; - common::printLink('company', 'browse', '', $lang->user->allUsers); echo '
      '; - common::printLink('dept', 'browse', '', $lang->dept->manage); - ?> -
      -
      -
      - - - - - - - user->nickname;?> - - - - - - - - - - - - - - - - nickname;?> - - - - - - - - - - -
      idAB;?>user->realname;?>user->account;?>user->email;?>user->gender;?>user->phone;?>user->join;?>user->last;?>user->visits;?>actions;?>
      id;?>account", $user->realname)) echo $user->realname;?>account;?>email);?>user->genderList->{$user->gender})) echo $lang->user->genderList->{$user->gender};?>phone;?>join;?>last);?>visits;?> - id&from=company", $lang->edit); - common::printLink('user', 'delete', "userID=$user->id", $lang->delete, "hiddenwin"); - ?> -
      -
      - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
      +
      dept->common;?>
      +
      + +
      + user->create);echo '
      '; + common::printLink('company', 'browse', '', $lang->user->allUsers); echo '
      '; + common::printLink('dept', 'browse', '', $lang->dept->manage); + ?> +
      +
      +
      + + + + + + + user->nickname;?> + + + + + + + + + + + + + + + + nickname;?> + + + + + + + + + + +
      idAB;?>user->realname;?>user->account;?>user->email;?>user->gender;?>user->phone;?>user->join;?>user->last;?>user->visits;?>actions;?>
      id;?>account", $user->realname)) echo $user->realname;?>account;?>email);?>user->genderList->{$user->gender})) echo $lang->user->genderList->{$user->gender};?>phone;?>join;?>last);?>visits;?> + id&from=company", $lang->edit); + common::printLink('user', 'delete', "userID=$user->id", $lang->delete, "hiddenwin"); + ?> +
      +
      + + diff --git a/module/company/view/create.html.php b/module/company/view/create.html.php index 6ed0a65c04..148be8dbac 100644 --- a/module/company/view/create.html.php +++ b/module/company/view/create.html.php @@ -1,56 +1,56 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      company->create;?>
      company->name;?>
      company->phone;?>
      company->fax;?>
      company->address;?>
      company->zipcode;?>
      company->website;?>
      company->backyard;?>
      company->pms;?>
      company->guest;?>company->guestList);?>
      -
      - + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      company->create;?>
      company->name;?>
      company->phone;?>
      company->fax;?>
      company->address;?>
      company->zipcode;?>
      company->website;?>
      company->backyard;?>
      company->pms;?>
      company->guest;?>company->guestList);?>
      +
      + diff --git a/module/company/view/dynamic.html.php b/module/company/view/dynamic.html.php index 59fb4f5d94..357b684648 100644 --- a/module/company/view/dynamic.html.php +++ b/module/company/view/dynamic.html.php @@ -1,62 +1,62 @@ -dynamic view file of dashboard module of ZenTaoPMS. - * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) - * @license LGPL (http://www.gnu.org/licenses/lgpl.html) - * @author Chunsheng Wang - * @package dashboard - * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ - * @link http://www.zentao.net - */ -?> - - - -
      - ' . html::a(inlink('dynamic', "browseType=today"), $lang->action->dynamic->today) . ''; - echo '' . html::a(inlink('dynamic', "browseType=yesterday"), $lang->action->dynamic->yesterday) . ''; - echo '' . html::a(inlink('dynamic', "browseType=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; - echo '' . html::a(inlink('dynamic', "browseType=thisweek"), $lang->action->dynamic->thisWeek) . ''; - echo '' . html::a(inlink('dynamic', "browseType=lastweek"), $lang->action->dynamic->lastWeek) . ''; - echo '' . html::a(inlink('dynamic', "browseType=thismonth"), $lang->action->dynamic->thisMonth) . ''; - echo '' . html::a(inlink('dynamic', "browseType=lastmonth"), $lang->action->dynamic->lastMonth) . ''; - echo '' . html::a(inlink('dynamic', "browseType=all"), $lang->action->dynamic->all) . ''; - echo "" . html::select('account', $users, $account, 'onchange=changeUser(this.value)') . ''; - echo "" . html::select('product', $products, $product, 'onchange=changeProduct(this.value)') . ''; - echo "" . html::select('project', $projects, $project, 'onchange=changeProject(this.value)') . ''; - echo "" . html::a('#', $lang->action->dynamic->search) . ""; - ?> -
      -
      '>
      - - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - -
      action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
      date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
      show();?>
      - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @license LGPL (http://www.gnu.org/licenses/lgpl.html) + * @author Chunsheng Wang + * @package dashboard + * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ + * @link http://www.zentao.net + */ +?> + + + +
      + ' . html::a(inlink('dynamic', "browseType=today"), $lang->action->dynamic->today) . ''; + echo '' . html::a(inlink('dynamic', "browseType=yesterday"), $lang->action->dynamic->yesterday) . ''; + echo '' . html::a(inlink('dynamic', "browseType=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; + echo '' . html::a(inlink('dynamic', "browseType=thisweek"), $lang->action->dynamic->thisWeek) . ''; + echo '' . html::a(inlink('dynamic', "browseType=lastweek"), $lang->action->dynamic->lastWeek) . ''; + echo '' . html::a(inlink('dynamic', "browseType=thismonth"), $lang->action->dynamic->thisMonth) . ''; + echo '' . html::a(inlink('dynamic', "browseType=lastmonth"), $lang->action->dynamic->lastMonth) . ''; + echo '' . html::a(inlink('dynamic', "browseType=all"), $lang->action->dynamic->all) . ''; + echo "" . html::select('account', $users, $account, 'onchange=changeUser(this.value)') . ''; + echo "" . html::select('product', $products, $product, 'onchange=changeProduct(this.value)') . ''; + echo "" . html::select('project', $projects, $project, 'onchange=changeProject(this.value)') . ''; + echo "" . html::a('#', $lang->action->dynamic->search) . ""; + ?> +
      +
      '>
      + + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + +
      action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
      date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
      show();?>
      + + diff --git a/module/company/view/edit.html.php b/module/company/view/edit.html.php index 882bc29160..34ccc07bd6 100644 --- a/module/company/view/edit.html.php +++ b/module/company/view/edit.html.php @@ -1,56 +1,56 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      company->edit;?>
      company->name;?>name, "class='text-1'");?>
      company->phone;?>phone, "class='text-1'");?>
      company->fax;?>fax, "class='text-1'");?>
      company->address;?>address, "class='text-1'");?>
      company->zipcode;?>zipcode, "class='text-1'");?>
      company->website;?>website, "class='text-1'");?>
      company->backyard;?>backyard, "class='text-1'");?>
      company->pms;?>pms, "class='text-1'");?>
      company->guest;?>company->guestList, $company->guest);?>
      -
      - + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      company->edit;?>
      company->name;?>name, "class='text-1'");?>
      company->phone;?>phone, "class='text-1'");?>
      company->fax;?>fax, "class='text-1'");?>
      company->address;?>address, "class='text-1'");?>
      company->zipcode;?>zipcode, "class='text-1'");?>
      company->website;?>website, "class='text-1'");?>
      company->backyard;?>backyard, "class='text-1'");?>
      company->pms;?>pms, "class='text-1'");?>
      company->guest;?>company->guestList, $company->guest);?>
      +
      + diff --git a/module/convert/control.php b/module/convert/control.php index f75a298720..af46236284 100644 --- a/module/convert/control.php +++ b/module/convert/control.php @@ -1,240 +1,240 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -class convert extends control -{ - /** - * Index page of convert. - * - * @access public - * @return void - */ - public function index() - { - $this->convert->saveState(); - $this->view->header->title = $this->lang->convert->common; - $this->display(); - } - - /** - * Select the source system. - * - * @access public - * @return void - */ - public function selectSource() - { - $this->view->header->title = $this->lang->convert->common . $this->lang->colon; - $this->display(); - } - - /** - * Set configs of converter. - * - * This is the extrance of every system. It will call the set function of corresponding module. - * - * @access public - * @return void - */ - public function setConfig() - { - if(!$this->post->source) - { - echo js::alert($this->lang->convert->mustSelectSource); - die(js::locate('back')); - } - list($sourceName, $version) = explode('_', $this->post->source); - $setFunc = "set$sourceName"; - $this->view->header->title = $this->lang->convert->setting; - $this->view->source = $sourceName; - $this->view->version = $version; - $this->view->setting = $this->fetch('convert', $setFunc, "version=$version"); - $this->display(); - } - - /** - * The setting page of bugfree. - * - * @param string $version - * @access public - * @return void - */ - public function setBugFree($version) - { - $this->view->source = 'BugFree'; - $this->view->version = $version; - $this->view->tablePrefix = $version > 1 ? 'bf_' : ''; - $this->view->dbName = $version > 1 ? 'bugfree2' : 'BugFree'; - $this->view->dbCharset = 'utf8'; - $this->display(); - } - - /** - * The setting page of Redmine. - * - * @param string $version - * @access public - * @return void - */ - public function setRedmine($version) - { - $this->view->source = 'Redmine'; - $this->view->version = $version; - $this->view->dbName = 'redmine'; - $this->view->dbCharset = 'utf8'; - $this->display(); - } - - /** - * Check config. Same as setConfig. - * - * @access public - * @return void - */ - public function checkConfig() - { - $checkFunc = 'check' . $this->post->source; - $this->view->header->title = $this->lang->convert->checkConfig; - $this->view->source = $this->post->source; - $this->view->checkResult = $this->fetch('convert', $checkFunc, "version={$this->post->version}"); - $this->display(); - } - - /** - * Check settings of bugfree. - * - * @param int $version - * @access public - * @return void - */ - public function checkBugFree($version) - { - helper::import('./converter/bugfree.php'); - $converter = new bugfreeConvertModel(); - - /* Check it. */ - $checkInfo['db'] = $converter->connectDB(); - //if(is_object($checkInfo['db'])) $checkInfo['table'] = $converter->checkTables(); - $checkInfo['path'] = $converter->checkPath(); - - /* Compute the checking result. */ - $result = 'pass'; - if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail'; - - /* Assign. */ - $this->view->version = $version; - $this->view->source = 'bugfree'; - $this->view->result = $result; - $this->view->checkInfo = $checkInfo; - $this->display(); - } - - /** - * Check settings of Redmine. - * - * @param int $version - * @access public - * @return void - */ - public function checkRedmine($version) - { - helper::import('./converter/redmine.php'); - $converter = new redmineConvertModel(); - - /* Check it. */ - $checkInfo['db'] = $converter->connectDB(); - $checkInfo['path'] = $converter->checkPath(); - - $this->view->trackers = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('trackers')->fetchAll('id', $autoCompany = false); - $this->view->statuses = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('issue_statuses')->fetchAll('id', $autoCompany = false); - $this->view->pries = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('enumerations')->where('type')->eq('IssuePriority')->fetchAll('id', $autoCompany = false); - /* Compute the checking result. */ - $result = 'pass'; - if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail'; - - $this->app->loadLang('bug'); - $this->app->loadLang('story'); - $this->app->loadLang('task'); - $this->view->aimTypeList['bug'] = 'bug'; - $this->view->aimTypeList['task'] = 'task'; - $this->view->aimTypeList['story'] = 'story'; - - /* Assign. */ - $this->view->version = $version; - $this->view->source = 'Redmine'; - $this->view->result = $result; - $this->view->checkInfo = $checkInfo; - $this->display(); - } - - /** - * Execute the converting. - * - * @access public - * @return void - */ - public function execute() - { - $convertFunc = 'convert' . $this->post->source; - $this->view->header->title = $this->lang->convert->execute; - $this->view->source = $this->post->source; - $this->view->version = $this->post->version; - - $this->view->executeResult = $this->fetch('convert', $convertFunc, "version={$this->post->version}"); - $this->display(); - } - - /** - * Convert bugfree. - * - * @param int $version - * @access public - * @return void - */ - public function convertBugFree($version) - { - helper::import('./converter/bugfree.php'); - helper::import("./converter/bugfree$version.php"); - $className = "bugfree{$version}ConvertModel"; - $converter = new $className(); - $this->view->version = $version; - $this->view->result = $converter->execute($version); - $this->view->info = bugfreeConvertModel::$info; - $this->display(); - } - - /** - * convert redmine - * - * @param int $version - * @access public - * @return void - */ - public function convertRedmine($version) - { - helper::import('./converter/redmine.php'); - helper::import("./converter/redmine$version.php"); - $className = "redmine11ConvertModel"; - $redmine->aimTypes = $this->post->aimTypes; - $redmine->statusTypes['bug'] = $this->post->statusTypesOfBug; - $redmine->statusTypes['story'] = $this->post->statusTypesOfStory; - $redmine->statusTypes['task'] = $this->post->statusTypesOfTask; - $redmine->priTypes['bug'] = $this->post->priTypesOfBug; - $redmine->priTypes['story'] = $this->post->priTypesOfStory; - $redmine->priTypes['task'] = $this->post->priTypesOfTask; - - $converter = new $className($redmine); - $this->view->version = $version; - $this->view->result = $converter->execute($version); - $this->view->info = redmineConvertModel::$info; - $this->display(); - } -} + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +class convert extends control +{ + /** + * Index page of convert. + * + * @access public + * @return void + */ + public function index() + { + $this->convert->saveState(); + $this->view->header->title = $this->lang->convert->common; + $this->display(); + } + + /** + * Select the source system. + * + * @access public + * @return void + */ + public function selectSource() + { + $this->view->header->title = $this->lang->convert->common . $this->lang->colon; + $this->display(); + } + + /** + * Set configs of converter. + * + * This is the extrance of every system. It will call the set function of corresponding module. + * + * @access public + * @return void + */ + public function setConfig() + { + if(!$this->post->source) + { + echo js::alert($this->lang->convert->mustSelectSource); + die(js::locate('back')); + } + list($sourceName, $version) = explode('_', $this->post->source); + $setFunc = "set$sourceName"; + $this->view->header->title = $this->lang->convert->setting; + $this->view->source = $sourceName; + $this->view->version = $version; + $this->view->setting = $this->fetch('convert', $setFunc, "version=$version"); + $this->display(); + } + + /** + * The setting page of bugfree. + * + * @param string $version + * @access public + * @return void + */ + public function setBugFree($version) + { + $this->view->source = 'BugFree'; + $this->view->version = $version; + $this->view->tablePrefix = $version > 1 ? 'bf_' : ''; + $this->view->dbName = $version > 1 ? 'bugfree2' : 'BugFree'; + $this->view->dbCharset = 'utf8'; + $this->display(); + } + + /** + * The setting page of Redmine. + * + * @param string $version + * @access public + * @return void + */ + public function setRedmine($version) + { + $this->view->source = 'Redmine'; + $this->view->version = $version; + $this->view->dbName = 'redmine'; + $this->view->dbCharset = 'utf8'; + $this->display(); + } + + /** + * Check config. Same as setConfig. + * + * @access public + * @return void + */ + public function checkConfig() + { + $checkFunc = 'check' . $this->post->source; + $this->view->header->title = $this->lang->convert->checkConfig; + $this->view->source = $this->post->source; + $this->view->checkResult = $this->fetch('convert', $checkFunc, "version={$this->post->version}"); + $this->display(); + } + + /** + * Check settings of bugfree. + * + * @param int $version + * @access public + * @return void + */ + public function checkBugFree($version) + { + helper::import('./converter/bugfree.php'); + $converter = new bugfreeConvertModel(); + + /* Check it. */ + $checkInfo['db'] = $converter->connectDB(); + //if(is_object($checkInfo['db'])) $checkInfo['table'] = $converter->checkTables(); + $checkInfo['path'] = $converter->checkPath(); + + /* Compute the checking result. */ + $result = 'pass'; + if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail'; + + /* Assign. */ + $this->view->version = $version; + $this->view->source = 'bugfree'; + $this->view->result = $result; + $this->view->checkInfo = $checkInfo; + $this->display(); + } + + /** + * Check settings of Redmine. + * + * @param int $version + * @access public + * @return void + */ + public function checkRedmine($version) + { + helper::import('./converter/redmine.php'); + $converter = new redmineConvertModel(); + + /* Check it. */ + $checkInfo['db'] = $converter->connectDB(); + $checkInfo['path'] = $converter->checkPath(); + + $this->view->trackers = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('trackers')->fetchAll('id', $autoCompany = false); + $this->view->statuses = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('issue_statuses')->fetchAll('id', $autoCompany = false); + $this->view->pries = $this->dao->dbh($converter->sourceDBH)->select('id, name')->from('enumerations')->where('type')->eq('IssuePriority')->fetchAll('id', $autoCompany = false); + /* Compute the checking result. */ + $result = 'pass'; + if(!is_object($checkInfo['db']) or !$checkInfo['path']) $result = 'fail'; + + $this->app->loadLang('bug'); + $this->app->loadLang('story'); + $this->app->loadLang('task'); + $this->view->aimTypeList['bug'] = 'bug'; + $this->view->aimTypeList['task'] = 'task'; + $this->view->aimTypeList['story'] = 'story'; + + /* Assign. */ + $this->view->version = $version; + $this->view->source = 'Redmine'; + $this->view->result = $result; + $this->view->checkInfo = $checkInfo; + $this->display(); + } + + /** + * Execute the converting. + * + * @access public + * @return void + */ + public function execute() + { + $convertFunc = 'convert' . $this->post->source; + $this->view->header->title = $this->lang->convert->execute; + $this->view->source = $this->post->source; + $this->view->version = $this->post->version; + + $this->view->executeResult = $this->fetch('convert', $convertFunc, "version={$this->post->version}"); + $this->display(); + } + + /** + * Convert bugfree. + * + * @param int $version + * @access public + * @return void + */ + public function convertBugFree($version) + { + helper::import('./converter/bugfree.php'); + helper::import("./converter/bugfree$version.php"); + $className = "bugfree{$version}ConvertModel"; + $converter = new $className(); + $this->view->version = $version; + $this->view->result = $converter->execute($version); + $this->view->info = bugfreeConvertModel::$info; + $this->display(); + } + + /** + * convert redmine + * + * @param int $version + * @access public + * @return void + */ + public function convertRedmine($version) + { + helper::import('./converter/redmine.php'); + helper::import("./converter/redmine$version.php"); + $className = "redmine11ConvertModel"; + $redmine->aimTypes = $this->post->aimTypes; + $redmine->statusTypes['bug'] = $this->post->statusTypesOfBug; + $redmine->statusTypes['story'] = $this->post->statusTypesOfStory; + $redmine->statusTypes['task'] = $this->post->statusTypesOfTask; + $redmine->priTypes['bug'] = $this->post->priTypesOfBug; + $redmine->priTypes['story'] = $this->post->priTypesOfStory; + $redmine->priTypes['task'] = $this->post->priTypesOfTask; + + $converter = new $className($redmine); + $this->view->version = $version; + $this->view->result = $converter->execute($version); + $this->view->info = redmineConvertModel::$info; + $this->display(); + } +} diff --git a/module/convert/converter/bugfree.php b/module/convert/converter/bugfree.php index 3de191f906..8d520dbc3c 100644 --- a/module/convert/converter/bugfree.php +++ b/module/convert/converter/bugfree.php @@ -1,88 +1,88 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -class bugfreeConvertModel extends convertModel -{ - public $map = array(); - public $filePath = ''; - static public $info = array(); - - /** - * Connect to db auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - parent::connectDB(); - } - - /** - * Check table. - * - * @access public - * @return bool - */ - public function checkTables() - { - return true; - } - - /** - * Check the install path. - * - * @access public - * @return bool - */ - public function checkPath() - { - $this->setPath(); - return file_exists($this->filePath); - } - - /** - * Set the path of attachments. - * - * @access public - * @return bool - */ - public function setPath() - { - $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'BugFile' . $this->app->getPathFix(); - } - - /** - * Excute the convert. - * - * @param int $version - * @access public - * @return void - */ - public function execute($version) - { - } - - /** - * Clear rows added in converting. - * - * @access public - * @return void - */ - public function clear() - { - foreach($this->session->state as $table => $maxID) - { - $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); - } - } -} + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +class bugfreeConvertModel extends convertModel +{ + public $map = array(); + public $filePath = ''; + static public $info = array(); + + /** + * Connect to db auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + parent::connectDB(); + } + + /** + * Check table. + * + * @access public + * @return bool + */ + public function checkTables() + { + return true; + } + + /** + * Check the install path. + * + * @access public + * @return bool + */ + public function checkPath() + { + $this->setPath(); + return file_exists($this->filePath); + } + + /** + * Set the path of attachments. + * + * @access public + * @return bool + */ + public function setPath() + { + $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'BugFile' . $this->app->getPathFix(); + } + + /** + * Excute the convert. + * + * @param int $version + * @access public + * @return void + */ + public function execute($version) + { + } + + /** + * Clear rows added in converting. + * + * @access public + * @return void + */ + public function clear() + { + foreach($this->session->state as $table => $maxID) + { + $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); + } + } +} diff --git a/module/convert/converter/bugfree1.php b/module/convert/converter/bugfree1.php index 3aa8a53d4f..33e47d16b1 100644 --- a/module/convert/converter/bugfree1.php +++ b/module/convert/converter/bugfree1.php @@ -1,318 +1,318 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -class bugfree1ConvertModel extends bugfreeConvertModel -{ - /** - * Execute the convert. - * - * @access public - * @return array - */ - public function execute() - { - $this->clear(); - $this->convertGroup(); - $result['users'] = $this->convertUser(); - $result['projects'] = $this->convertProject(); - $result['modules'] = $this->convertModule(); - $result['bugs'] = $this->convertBug(); - $result['actions'] = $this->convertAction(); - $result['files'] = $this->convertFile(); - $this->dao->dbh($this->dbh); - $this->loadModel('tree')->fixModulePath(); - return $result; - } - - /** - * Convert groups. - * - * @access public - * @return void - */ - public function convertGroup() - { - $groups = $this->dao->dbh($this->sourceDBH) - ->select("groupID AS id, groupName AS name, groupUser AS users") - ->from('BugGroup') - ->fetchAll('id', $autoCompany = false); - foreach($groups as $groupID => $group) - { - /* Explode into array. */ - $groupUsers = explode(',', $group->users); - unset($group->id); - unset($group->users); - - /* Insert the group. */ - $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec(); - $zentaoGroupID = $this->dao->lastInsertId(); - - /* Insert account. */ - foreach($groupUsers as $account) - { - if(empty($account)) continue; - $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->set('`group`')->eq($zentaoGroupID)->set('account')->eq($account)->exec(); - } - } - } - - /** - * Convert user. - * - * @access public - * @return int converted user count - */ - public function convertUser() - { - /* Get users exist in the system. */ - $activeUsers = $this->dao - ->dbh($this->sourceDBH) - ->select("username AS account, userpassword AS password, realname, email") - ->from('BugUser') - ->orderBy('userID ASC') - ->fetchAll('account', $autoCompany = false); - - /* Get users in histories. */ - $allUsers = $this->dao->select("distinct(username) AS account")->from('BugHistory')->fetchPairs('', '', $autoCompany = false); - - /* Merge them. */ - foreach($allUsers as $key => $account) - { - if(isset($activeUsers[$account])) - { - $allUsers[$key] = $activeUsers[$account]; - } - else - { - $allUsers[$key] = array('account' => $account, 'realname' => $account, 'deleted' => '1'); - } - } - foreach($activeUsers as $account => $user) if(!isset($allUsers[$account])) $allUsers[$account] = $user; - - /* Insert into zentao. */ - $convertCount = 0; - foreach($allUsers as $account => $user) - { - if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account')) - { - $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); - $convertCount ++; - } - else - { - self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account); - } - } - return $convertCount; - } - - /** - * Convert project in bugfree to product in zentao. - * - * @access public - * @return int converted project count - */ - public function convertProject() - { - $projects = $this->dao->dbh($this->sourceDBH)->select("projectID AS id, projectName AS name")->from('BugProject')->fetchAll('id', $autoCompany = false); - foreach($projects as $projectID => $project) - { - unset($project->id); - $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec(); - $this->map['product'][$projectID] = $this->dao->lastInsertID(); - } - return count($projects); - } - - /** - * Convert modules. - * - * @access public - * @return int converted modules count - */ - public function convertModule() - { - $this->map['module'][0] = 0; - $modules = $this->dao - ->dbh($this->sourceDBH) - ->select( - 'moduleID AS id, - projectID AS root, - moduleName AS name, - moduleGrade AS grade, - parentID AS parent, - "bug" AS type') - ->from('BugModule') - ->orderBy('id ASC') - ->fetchAll('id', $autoCompany = false); - foreach($modules as $moduleID => $module) - { - $module->root = $this->map['product'][$module->root]; - unset($module->id); - $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec(); - $this->map['module'][$moduleID] = $this->dao->lastInsertID(); - } - - /* Update parents. */ - foreach($modules as $oldModuleID => $module) - { - $newModuleID = $this->map['module'][$oldModuleID]; - $newParentID = $this->map['module'][$module->parent]; - $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec(); - } - return count($modules); - } - - /** - * Convert bugs. - * - * @access public - * @return int converted bugs count. - */ - public function convertBug() - { - $bugs = $this->dao - ->dbh($this->sourceDBH) - ->select(' - bugID AS id, - projectID AS product, - moduleID AS module, - bugTitle AS title, - bugSeverity AS severity, - bugType AS type, - bugOS AS os, - bugStatus AS status, - mailto, - openedBy, openedDate, openedBuild, - assignedTo, assignedDate, - resolvedBy, resolution, resolvedBuild, resolvedDate, - closedBy, closedDate, - lastEditedBy, lastEditedDate, - linkID as duplicateBug - ') - ->from('BugInfo') - ->orderBy('bugID') - ->fetchAll('id', $autoCompany = false); - foreach($bugs as $bugID => $bug) - { - /* Adjust some fields of bug. */ - $bugID = (int)$bugID; - unset($bug->id); - if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed'; - $bug->type = strtolower($bug->type); - $bug->os = strtolower($bug->os); - $bug->browser = 'all'; - $bug->resolution = str_replace(' ','', strtolower($bug->resolution)); - $bug->product = $this->map['product'][$bug->product]; - $bug->module = $this->map['module'][$bug->module]; - $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); - $this->map['bug'][$bugID] = $this->dao->lastInsertID(); - } - - /* Update duplicated bugs. */ - foreach($this->map['bug'] as $oldBugID => $newBugID) - { - $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec(); - } - return count($bugs); - } - - /** - * Convert actions. - * - * @access public - * @return int converted actions count. - */ - public function convertAction() - { - $actions = $this->dao - ->dbh($this->sourceDBH) - ->select(" - 'bug' AS objectType, - bugID AS objectID, - userName AS actor, - action, - fullInfo AS comment, - actionDate AS date") - ->from('BugHistory') - ->orderBy('bugID, historyID') - ->fetchGroup('objectID', '', $autoCompany = false); - $convertCount = 0; - foreach($actions as $bugID => $bugActions) - { - /* Get the related bugID. */ - $bugID = (int)$bugID; - $zentaoBugID = $this->map['bug'][$bugID]; - - /* Process actions. */ - foreach($bugActions as $key => $action) - { - $action->objectID = $zentaoBugID; - if($key == 0) - { - $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('steps')->eq(nl2br($action->comment))->where('id')->eq($zentaoBugID)->exec(); - $action->comment = ''; - } - $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); - $convertCount ++; - } - } - return $convertCount; - } - - /** - * Convert files. - * - * @access public - * @return int converted files count. - */ - public function convertFile() - { - $this->setPath(); - $files = $this->dao->dbh($this->sourceDBH) - ->select(" - fileName AS pathname, - fileTitle AS title, - fileType AS extension, - fileSize AS size, - 'bug' AS objectType, - bugID AS objectID, - addUser AS addedBy, - addDate AS addedDate - ") - ->from('BugFile') - ->orderBy('fileID') - ->fetchAll('', $autoCompany = false); - foreach($files as $file) - { - $file->objectID = $this->map['bug'][(int)$file->objectID]; - if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024); - if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024); - $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); - - /* Copy files. */ - $soureFile = $this->filePath . $file->pathname; - if(!file_exists($soureFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); - continue; - } - $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; - $targetPath = dirname($targetFile); - if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); - if(!copy($soureFile, $targetFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); - } - } - return count($files); - } -} + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +class bugfree1ConvertModel extends bugfreeConvertModel +{ + /** + * Execute the convert. + * + * @access public + * @return array + */ + public function execute() + { + $this->clear(); + $this->convertGroup(); + $result['users'] = $this->convertUser(); + $result['projects'] = $this->convertProject(); + $result['modules'] = $this->convertModule(); + $result['bugs'] = $this->convertBug(); + $result['actions'] = $this->convertAction(); + $result['files'] = $this->convertFile(); + $this->dao->dbh($this->dbh); + $this->loadModel('tree')->fixModulePath(); + return $result; + } + + /** + * Convert groups. + * + * @access public + * @return void + */ + public function convertGroup() + { + $groups = $this->dao->dbh($this->sourceDBH) + ->select("groupID AS id, groupName AS name, groupUser AS users") + ->from('BugGroup') + ->fetchAll('id', $autoCompany = false); + foreach($groups as $groupID => $group) + { + /* Explode into array. */ + $groupUsers = explode(',', $group->users); + unset($group->id); + unset($group->users); + + /* Insert the group. */ + $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec(); + $zentaoGroupID = $this->dao->lastInsertId(); + + /* Insert account. */ + foreach($groupUsers as $account) + { + if(empty($account)) continue; + $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->set('`group`')->eq($zentaoGroupID)->set('account')->eq($account)->exec(); + } + } + } + + /** + * Convert user. + * + * @access public + * @return int converted user count + */ + public function convertUser() + { + /* Get users exist in the system. */ + $activeUsers = $this->dao + ->dbh($this->sourceDBH) + ->select("username AS account, userpassword AS password, realname, email") + ->from('BugUser') + ->orderBy('userID ASC') + ->fetchAll('account', $autoCompany = false); + + /* Get users in histories. */ + $allUsers = $this->dao->select("distinct(username) AS account")->from('BugHistory')->fetchPairs('', '', $autoCompany = false); + + /* Merge them. */ + foreach($allUsers as $key => $account) + { + if(isset($activeUsers[$account])) + { + $allUsers[$key] = $activeUsers[$account]; + } + else + { + $allUsers[$key] = array('account' => $account, 'realname' => $account, 'deleted' => '1'); + } + } + foreach($activeUsers as $account => $user) if(!isset($allUsers[$account])) $allUsers[$account] = $user; + + /* Insert into zentao. */ + $convertCount = 0; + foreach($allUsers as $account => $user) + { + if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account')) + { + $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); + $convertCount ++; + } + else + { + self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account); + } + } + return $convertCount; + } + + /** + * Convert project in bugfree to product in zentao. + * + * @access public + * @return int converted project count + */ + public function convertProject() + { + $projects = $this->dao->dbh($this->sourceDBH)->select("projectID AS id, projectName AS name")->from('BugProject')->fetchAll('id', $autoCompany = false); + foreach($projects as $projectID => $project) + { + unset($project->id); + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec(); + $this->map['product'][$projectID] = $this->dao->lastInsertID(); + } + return count($projects); + } + + /** + * Convert modules. + * + * @access public + * @return int converted modules count + */ + public function convertModule() + { + $this->map['module'][0] = 0; + $modules = $this->dao + ->dbh($this->sourceDBH) + ->select( + 'moduleID AS id, + projectID AS root, + moduleName AS name, + moduleGrade AS grade, + parentID AS parent, + "bug" AS type') + ->from('BugModule') + ->orderBy('id ASC') + ->fetchAll('id', $autoCompany = false); + foreach($modules as $moduleID => $module) + { + $module->root = $this->map['product'][$module->root]; + unset($module->id); + $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec(); + $this->map['module'][$moduleID] = $this->dao->lastInsertID(); + } + + /* Update parents. */ + foreach($modules as $oldModuleID => $module) + { + $newModuleID = $this->map['module'][$oldModuleID]; + $newParentID = $this->map['module'][$module->parent]; + $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec(); + } + return count($modules); + } + + /** + * Convert bugs. + * + * @access public + * @return int converted bugs count. + */ + public function convertBug() + { + $bugs = $this->dao + ->dbh($this->sourceDBH) + ->select(' + bugID AS id, + projectID AS product, + moduleID AS module, + bugTitle AS title, + bugSeverity AS severity, + bugType AS type, + bugOS AS os, + bugStatus AS status, + mailto, + openedBy, openedDate, openedBuild, + assignedTo, assignedDate, + resolvedBy, resolution, resolvedBuild, resolvedDate, + closedBy, closedDate, + lastEditedBy, lastEditedDate, + linkID as duplicateBug + ') + ->from('BugInfo') + ->orderBy('bugID') + ->fetchAll('id', $autoCompany = false); + foreach($bugs as $bugID => $bug) + { + /* Adjust some fields of bug. */ + $bugID = (int)$bugID; + unset($bug->id); + if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed'; + $bug->type = strtolower($bug->type); + $bug->os = strtolower($bug->os); + $bug->browser = 'all'; + $bug->resolution = str_replace(' ','', strtolower($bug->resolution)); + $bug->product = $this->map['product'][$bug->product]; + $bug->module = $this->map['module'][$bug->module]; + $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); + $this->map['bug'][$bugID] = $this->dao->lastInsertID(); + } + + /* Update duplicated bugs. */ + foreach($this->map['bug'] as $oldBugID => $newBugID) + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec(); + } + return count($bugs); + } + + /** + * Convert actions. + * + * @access public + * @return int converted actions count. + */ + public function convertAction() + { + $actions = $this->dao + ->dbh($this->sourceDBH) + ->select(" + 'bug' AS objectType, + bugID AS objectID, + userName AS actor, + action, + fullInfo AS comment, + actionDate AS date") + ->from('BugHistory') + ->orderBy('bugID, historyID') + ->fetchGroup('objectID', '', $autoCompany = false); + $convertCount = 0; + foreach($actions as $bugID => $bugActions) + { + /* Get the related bugID. */ + $bugID = (int)$bugID; + $zentaoBugID = $this->map['bug'][$bugID]; + + /* Process actions. */ + foreach($bugActions as $key => $action) + { + $action->objectID = $zentaoBugID; + if($key == 0) + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('steps')->eq(nl2br($action->comment))->where('id')->eq($zentaoBugID)->exec(); + $action->comment = ''; + } + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + $convertCount ++; + } + } + return $convertCount; + } + + /** + * Convert files. + * + * @access public + * @return int converted files count. + */ + public function convertFile() + { + $this->setPath(); + $files = $this->dao->dbh($this->sourceDBH) + ->select(" + fileName AS pathname, + fileTitle AS title, + fileType AS extension, + fileSize AS size, + 'bug' AS objectType, + bugID AS objectID, + addUser AS addedBy, + addDate AS addedDate + ") + ->from('BugFile') + ->orderBy('fileID') + ->fetchAll('', $autoCompany = false); + foreach($files as $file) + { + $file->objectID = $this->map['bug'][(int)$file->objectID]; + if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024); + if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024); + $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); + + /* Copy files. */ + $soureFile = $this->filePath . $file->pathname; + if(!file_exists($soureFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); + continue; + } + $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; + $targetPath = dirname($targetFile); + if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); + if(!copy($soureFile, $targetFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); + } + } + return count($files); + } +} diff --git a/module/convert/converter/bugfree2.php b/module/convert/converter/bugfree2.php index efe2641c75..f436b7a7bc 100644 --- a/module/convert/converter/bugfree2.php +++ b/module/convert/converter/bugfree2.php @@ -1,530 +1,530 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -class bugfree2ConvertModel extends bugfreeConvertModel -{ - /** - * Execute the converter. - * - * @access public - * @return array - */ - public function execute() - { - $this->clear(); - $this->setTable(); - $this->convertGroup(); - $result['users'] = $this->convertUser(); - $result['projects'] = $this->convertProject(); - $result['modules'] = $this->convertModule(); - $result['bugs'] = $this->convertBug(); - $result['cases'] = $this->convertCase(); - $result['results'] = $this->convertResult(); - $result['actions'] = $this->convertAction(); - $result['files'] = $this->convertFile(); - $this->dao->dbh($this->dbh); - $this->loadModel('tree')->fixModulePath(); - return $result; - } - - /** - * Set table names. - * - * @access public - * @return void - */ - public function setTable() - { - $dbPrefix = $this->post->dbPrefix; - define('BUGFREE_TABLE_OPTION', $dbPrefix . 'TestOptions'); - define('BUGFREE_TABLE_USER', $dbPrefix . 'TestUser'); - define('BUGFREE_TABLE_PROJECT', $dbPrefix . 'TestProject'); - define('BUGFREE_TABLE_MODULE', $dbPrefix . 'TestModule'); - define('BUGFREE_TABLE_BUGINFO', $dbPrefix . 'BugInfo'); - define('BUGFREE_TABLE_CASEINFO', $dbPrefix . 'CaseInfo'); - define('BUGFREE_TABLE_RESULTINFO', $dbPrefix . 'ResultInfo'); - define('BUGFREE_TABLE_ACTION', $dbPrefix . 'TestAction'); - define('BUGFREE_TABLE_FILE', $dbPrefix . 'TestFile'); - define('BUGFREE_TABLE_HISTORY', $dbPrefix . 'TestHistory'); - define('BUGFREE_TABLE_GROUP', $dbPrefix . 'TestGroup'); - } - - /** - * Get the version of bugfree2.x. - * - * @access public - * @return int - */ - public function getBugFreeVersion() - { - return $this->dao->dbh($this->sourceDBH) - ->select("optionValue as version")->from(BUGFREE_TABLE_OPTION) - ->where('OptionName')->eq('dbVersion') - ->fetch('version', $autoCompany = false); - - } - - /** - * Convert user. - * - * @access public - * @return int converted user count - */ - public function convertUser() - { - /* Get all user list. */ - $users = $this->dao - ->dbh($this->sourceDBH) - ->select("username AS account, userpassword AS password, realname, email, isDroped AS deleted") - ->from(BUGFREE_TABLE_USER) - ->orderBy('userID ASC') - ->fetchAll('account', $autoCompany = false); - - /* Insert into zentao. */ - $convertCount = 0; - foreach($users as $account => $user) - { - if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account')) - { - $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); - $convertCount ++; - } - else - { - self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account); - } - } - return $convertCount; - } - - /** - * Convert groups. - * - * @access public - * @return void converted group count. - */ - public function convertGroup() - { - if(!$this->tableExists(BUGFREE_TABLE_GROUP)) return false; - $groups = $this->dao->dbh($this->sourceDBH) - ->select("groupID AS id, groupName AS name, groupUser AS users") - ->from(BUGFREE_TABLE_GROUP) - ->fetchAll('id', $autoCompany = false); - foreach($groups as $groupID => $group) - { - /* Fix the group data. */ - if($group->name == '[All Users]') continue; - $groupUsers = explode(',', $group->users); - unset($group->id); - unset($group->users); - - /* Insert into zentao's group table. */ - $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec(); - $zentaoGroupID = $this->dao->lastInsertId(); - - /* Insert into zentao's usergroup table. */ - foreach($groupUsers as $account) - { - if(empty($account)) continue; - $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP) - ->set('`group`')->eq($zentaoGroupID) - ->set('account')->eq($account) - ->exec(); - } - } - } - - /** - * Convert projects. - * - * @access public - * @return int converted projects count. - */ - public function convertProject() - { - $projects = $this->dao->dbh($this->sourceDBH) - ->select("projectID AS id, projectName AS name, isDroped AS deleted") - ->from(BUGFREE_TABLE_PROJECT) - ->fetchAll('id', $autoComapny = false); - foreach($projects as $projectID => $project) - { - unset($project->id); - $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec(); - $this->map['product'][$projectID] = $this->dao->lastInsertID(); - } - return count($projects); - } - - /** - * Convert modules. - * - * @access public - * @return int converted modules count. - */ - public function convertModule() - { - $this->map['module'][0] = 0; - $modules = $this->dao - ->dbh($this->sourceDBH) - ->select( - 'moduleID AS id, - moduleType as type, - projectID AS root, - moduleName AS name, - moduleGrade AS grade, - parentID AS parent, - displayOrder AS `order`') - ->from(BUGFREE_TABLE_MODULE) - ->orderBy('id ASC') - ->fetchAll('id', $autoCompany = false); - foreach($modules as $moduleID => $module) - { - $module->root = $this->map['product'][$module->root]; - $module->type = strtolower($module->type); - unset($module->id); - $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec(); - $this->map['module'][$moduleID] = $this->dao->lastInsertID(); - } - - /* Update parent. */ - foreach($modules as $oldModuleID => $module) - { - $newModuleID = $this->map['module'][$oldModuleID]; - $newParentID = $this->map['module'][$module->parent]; - $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec(); - } - return count($modules); - } - - /** - * Convert bugs. - * - * @access public - * @return int converted bugs count. - */ - public function convertBug() - { - $bugs = $this->dao - ->dbh($this->sourceDBH) - ->select(' - bugID AS id, - projectID AS product, - moduleID AS module, - bugTitle AS title, - bugSeverity AS severity, - bugPriority AS pri, - bugType AS type, - bugOS AS os, - bugBrowser AS browser, - bugMachine AS hardware, - howFound AS found, - reproSteps AS steps, - bugStatus AS status, - linkID AS linkBug, - duplicateID AS duplicateBug, - caseID AS `case`, - 1 AS caseVersion, - resultID AS result, - mailto, - openedBy, openedDate, openedBuild, - assignedTo, assignedDate, - resolvedBy, resolution, resolvedBuild, resolvedDate, - closedBy, closedDate, - lastEditedBy, lastEditedDate, - bugKeyword AS keywords - ') - ->from(BUGFREE_TABLE_BUGINFO) - ->where('isDroped')->eq(0) - ->orderBy('bugID') - ->fetchAll('id', $autoCompany = false); - foreach($bugs as $bugID => $bug) - { - /* Fix some fileds of bug. */ - $bugID = (int)$bugID; - unset($bug->id); - - if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed'; - if($bug->assignedTo == 'Active') $bug->assignedTo = ''; - - $bug->type = strtolower($bug->type); - $bug->found = strtolower($bug->found); - $bug->status = strtolower($bug->status); - $bug->os = strtolower($bug->os); - $bug->browser= strtolower($bug->browser); - $bug->steps = nl2br($bug->steps); - - if($bug->os == 'winvista') $bug->os = 'vista'; - if($bug->browser == 'firefox3.0') $bug->browser = 'firefox3'; - if($bug->browser == 'firefox2.0') $bug->browser = 'firefox2'; - if($bug->openedBuild == 'N/A') $bug->openedBuild = ''; - if(!$bug->case) $bug->caseVersion = 0; - - $bug->resolution = str_replace(' ', '', strtolower($bug->resolution)); - $bug->product = $this->map['product'][$bug->product]; - $bug->module = $this->map['module'][$bug->module]; - $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); - $this->map['bug'][$bugID] = $this->dao->lastInsertID(); - } - - /* Update duplicated bugs. */ - foreach($this->map['bug'] as $oldBugID => $newBugID) - { - $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec(); - } - return count($bugs); - } - - /** - * Convert cases. - * - * @access public - * @return int converted cases count. - */ - public function convertCase() - { - $cases = $this->dao - ->dbh($this->sourceDBH) - ->select(' - caseID AS id, - projectID AS product, - moduleID AS module, - caseTitle AS title, - caseSteps AS step, - casePriority AS pri, - caseType AS type, - caseStatus AS status, - caseMethod AS howRun, - casePlan AS stage, - openedBy, openedDate, - lastEditedBy, lastEditedDate, - scriptedBy, scriptedDate, scriptStatus, scriptLocation, - linkID AS linkCase, - casekeyword AS keywords, - 1 AS version, - bugID - ') - ->from(BUGFREE_TABLE_CASEINFO) - ->where('isDroped')->eq(0) - ->orderBy('caseID') - ->fetchAll('id', $autoCompany = false); - foreach($cases as $caseID => $case) - { - /* Fix fields of case. */ - $caseID = (int)$caseID; - $step = $case->step; - $bugs = explode(',', $case->bugID); - unset($case->id); - unset($case->step); - unset($case->bugID); - - $case->type = strtolower($case->type); - $case->status = strtolower($case->status); - $case->howRun = strtolower($case->howRun); - $case->stage = strtolower($case->stage); - - if($case->type == 'configuration') $case->type = 'config'; - if($case->type == 'setup') $case->type = 'install'; - if($case->type == 'functional') $case->type = 'feature'; - if($case->status == 'active') $case->status = 'normal'; - - /* Change product and module by zentao's product and module. */ - $case->product = $this->map['product'][$case->product]; - $case->module = $this->map['module'][$case->module]; - - /* Insert into case table. */ - $this->dao->dbh($this->dbh)->insert(TABLE_CASE)->data($case)->exec(); - $zentaoCaseID = $this->dao->lastInsertID(); - $this->map['case'][$caseID] = $zentaoCaseID; - - /* Insert into case step table. */ - $caseStep->case = $zentaoCaseID; - $caseStep->version = 1; - $caseStep->desc = $step; - $this->dao->dbh($this->dbh)->insert(TABLE_CASESTEP)->data($caseStep)->exec(); - - /* Update related bugs. */ - foreach($bugs as $bugID) - { - if(!isset($this->map['bug'][$bugID])) continue; - $zentaoBugID = $this->map['bug'][$bugID]; - $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('`case`')->eq($zentaoCaseID)->where('id')->eq($zentaoBugID)->limit(1)->exec(); - } - } - return count($cases); - } - - /** - * Convert results. - * - * @access public - * @return int converted results count. - */ - public function convertResult() - { - $results = $this->dao->dbh($this->sourceDBH) - ->select(' - resultID AS id, - caseID AS `case`, - resultValue AS caseResult, - 1 AS version, - openedDate as date, - bugID - ') - ->from(BUGFREE_TABLE_RESULTINFO) - ->orderBy('id') - ->fetchAll('id', $autoCompany = false); - foreach($results as $resultID => $result) - { - unset($result->id); - - /* The bug id of zentao. */ - $bugID = (int)$result->bugID; - $zentaoBugID = $this->map['bug'][$bugID]; - unset($result->bugID); - - /* Insert into test result table. */ - $this->dao->dbh($this->dbh)->insert(TABLE_TESTRESULT)->data($result)->exec(); - $zentaoResultID = $this->dao->lastInsertId(); - $this->map['result'][$resultID] = $zentaoResultID; - - /* Update result table. */ - $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('result')->eq($zentaoResultID)->where('id')->eq($zentaoBugID)->limit(1)->exec(); - } - return count($results); - } - - /** - * Convert actions. - * - * @access public - * @return int converted actions count. - */ - public function convertAction() - { - $actions = $this->dao - ->dbh($this->sourceDBH) - ->select("actionID AS id, - actionTarget AS objectType, - idValue AS objectID, - actionUser AS actor, - actionType AS action, - actionDate AS date, - actionNote AS comment - ") - ->from(BUGFREE_TABLE_ACTION) - ->where('actionTarget' != 'Result') - ->orderBy('actionID') - ->fetchAll('id', $autoComapny = false); - - foreach($actions as $actionID => $action) - { - $actionID = (int)$action->id; - unset($action->id); - $action->objectType = strtolower($action->objectType); - $action->action = strtolower($action->action); - $action->objectID = $this->map[$action->objectType][$action->objectID]; - - $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); - $this->map['action'][$actionID] = $this->dao->lastInsertID(); - } - return count($actions); - } - - /** - * Convert histories. - * - * @access public - * @return int the converted histories count. - */ - public function convertHistory() - { - $histories = $this->dao->dbh($this->sourceDBH) - ->select('actioID, actionField AS field, oldValue AS old, newValue AS new') - ->from(BUGFREE_TABLE_HISTORY) - ->orderBy('historyID') - ->fetchAll('', $autoCompany = false); - foreach($histories as $history) - { - $history->actionID = $this->map['action'][$history->actionID]; - $this->dao->dbh($this->dbh)->insert(TABLE_HISTORY)->data($history)->exec(); - } - } - - /** - * Convert attachments. - * - * @access public - * @return int the converted files count. - */ - public function convertFile() - { - $this->setPath(); - $files = $this->dao->dbh($this->sourceDBH) - ->select(" - actionID, - fileName AS pathname, - fileTitle AS title, - fileType AS extension, - fileSize AS size - ") - ->from(BUGFREE_TABLE_FILE) - ->orderBy('fileID') - ->fetchAll('', $autoCompany = false); - foreach($files as $file) - { - /* Get the actionID in zentao, to get file info. */ - $zentaoActionID = $this->map['action'][$file->actionID]; - $zentaoAction = $this->dao->dbh($this->dbh)->findById($zentaoActionID)->from(TABLE_ACTION)->fetch(); - $file->objectType = $zentaoAction->objectType; - $file->objectID = $zentaoAction->objectID; - $file->addedBy = $zentaoAction->actor; - $file->addedDate = $zentaoAction->date; - unset($file->actionID); - - /* Compute the file size. */ - if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024); - if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024); - - /* Insert into database. */ - $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); - - /* Copy file. */ - $soureFile = $this->filePath . $file->pathname; - if(!file_exists($soureFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); - continue; - } - $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; - $targetPath = dirname($targetFile); - if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); - if(!copy($soureFile, $targetFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); - } - } - return count($files); - } - - /** - * Clear the converted records. - * - * @access public - * @return void - */ - public function clear() - { - foreach($this->session->state as $table => $maxID) - { - $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); - } - } -} + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +class bugfree2ConvertModel extends bugfreeConvertModel +{ + /** + * Execute the converter. + * + * @access public + * @return array + */ + public function execute() + { + $this->clear(); + $this->setTable(); + $this->convertGroup(); + $result['users'] = $this->convertUser(); + $result['projects'] = $this->convertProject(); + $result['modules'] = $this->convertModule(); + $result['bugs'] = $this->convertBug(); + $result['cases'] = $this->convertCase(); + $result['results'] = $this->convertResult(); + $result['actions'] = $this->convertAction(); + $result['files'] = $this->convertFile(); + $this->dao->dbh($this->dbh); + $this->loadModel('tree')->fixModulePath(); + return $result; + } + + /** + * Set table names. + * + * @access public + * @return void + */ + public function setTable() + { + $dbPrefix = $this->post->dbPrefix; + define('BUGFREE_TABLE_OPTION', $dbPrefix . 'TestOptions'); + define('BUGFREE_TABLE_USER', $dbPrefix . 'TestUser'); + define('BUGFREE_TABLE_PROJECT', $dbPrefix . 'TestProject'); + define('BUGFREE_TABLE_MODULE', $dbPrefix . 'TestModule'); + define('BUGFREE_TABLE_BUGINFO', $dbPrefix . 'BugInfo'); + define('BUGFREE_TABLE_CASEINFO', $dbPrefix . 'CaseInfo'); + define('BUGFREE_TABLE_RESULTINFO', $dbPrefix . 'ResultInfo'); + define('BUGFREE_TABLE_ACTION', $dbPrefix . 'TestAction'); + define('BUGFREE_TABLE_FILE', $dbPrefix . 'TestFile'); + define('BUGFREE_TABLE_HISTORY', $dbPrefix . 'TestHistory'); + define('BUGFREE_TABLE_GROUP', $dbPrefix . 'TestGroup'); + } + + /** + * Get the version of bugfree2.x. + * + * @access public + * @return int + */ + public function getBugFreeVersion() + { + return $this->dao->dbh($this->sourceDBH) + ->select("optionValue as version")->from(BUGFREE_TABLE_OPTION) + ->where('OptionName')->eq('dbVersion') + ->fetch('version', $autoCompany = false); + + } + + /** + * Convert user. + * + * @access public + * @return int converted user count + */ + public function convertUser() + { + /* Get all user list. */ + $users = $this->dao + ->dbh($this->sourceDBH) + ->select("username AS account, userpassword AS password, realname, email, isDroped AS deleted") + ->from(BUGFREE_TABLE_USER) + ->orderBy('userID ASC') + ->fetchAll('account', $autoCompany = false); + + /* Insert into zentao. */ + $convertCount = 0; + foreach($users as $account => $user) + { + if(!$this->dao->dbh($this->dbh)->findByAccount($account)->from(TABLE_USER)->fetch('account')) + { + $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); + $convertCount ++; + } + else + { + self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $account); + } + } + return $convertCount; + } + + /** + * Convert groups. + * + * @access public + * @return void converted group count. + */ + public function convertGroup() + { + if(!$this->tableExists(BUGFREE_TABLE_GROUP)) return false; + $groups = $this->dao->dbh($this->sourceDBH) + ->select("groupID AS id, groupName AS name, groupUser AS users") + ->from(BUGFREE_TABLE_GROUP) + ->fetchAll('id', $autoCompany = false); + foreach($groups as $groupID => $group) + { + /* Fix the group data. */ + if($group->name == '[All Users]') continue; + $groupUsers = explode(',', $group->users); + unset($group->id); + unset($group->users); + + /* Insert into zentao's group table. */ + $this->dao->dbh($this->dbh)->insert(TABLE_GROUP)->data($group)->exec(); + $zentaoGroupID = $this->dao->lastInsertId(); + + /* Insert into zentao's usergroup table. */ + foreach($groupUsers as $account) + { + if(empty($account)) continue; + $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP) + ->set('`group`')->eq($zentaoGroupID) + ->set('account')->eq($account) + ->exec(); + } + } + } + + /** + * Convert projects. + * + * @access public + * @return int converted projects count. + */ + public function convertProject() + { + $projects = $this->dao->dbh($this->sourceDBH) + ->select("projectID AS id, projectName AS name, isDroped AS deleted") + ->from(BUGFREE_TABLE_PROJECT) + ->fetchAll('id', $autoComapny = false); + foreach($projects as $projectID => $project) + { + unset($project->id); + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($project)->exec(); + $this->map['product'][$projectID] = $this->dao->lastInsertID(); + } + return count($projects); + } + + /** + * Convert modules. + * + * @access public + * @return int converted modules count. + */ + public function convertModule() + { + $this->map['module'][0] = 0; + $modules = $this->dao + ->dbh($this->sourceDBH) + ->select( + 'moduleID AS id, + moduleType as type, + projectID AS root, + moduleName AS name, + moduleGrade AS grade, + parentID AS parent, + displayOrder AS `order`') + ->from(BUGFREE_TABLE_MODULE) + ->orderBy('id ASC') + ->fetchAll('id', $autoCompany = false); + foreach($modules as $moduleID => $module) + { + $module->root = $this->map['product'][$module->root]; + $module->type = strtolower($module->type); + unset($module->id); + $this->dao->dbh($this->dbh)->insert(TABLE_MODULE)->data($module)->exec(); + $this->map['module'][$moduleID] = $this->dao->lastInsertID(); + } + + /* Update parent. */ + foreach($modules as $oldModuleID => $module) + { + $newModuleID = $this->map['module'][$oldModuleID]; + $newParentID = $this->map['module'][$module->parent]; + $this->dao->dbh($this->dbh)->update(TABLE_MODULE)->set('parent')->eq($newParentID)->where('id')->eq($newModuleID)->exec(); + } + return count($modules); + } + + /** + * Convert bugs. + * + * @access public + * @return int converted bugs count. + */ + public function convertBug() + { + $bugs = $this->dao + ->dbh($this->sourceDBH) + ->select(' + bugID AS id, + projectID AS product, + moduleID AS module, + bugTitle AS title, + bugSeverity AS severity, + bugPriority AS pri, + bugType AS type, + bugOS AS os, + bugBrowser AS browser, + bugMachine AS hardware, + howFound AS found, + reproSteps AS steps, + bugStatus AS status, + linkID AS linkBug, + duplicateID AS duplicateBug, + caseID AS `case`, + 1 AS caseVersion, + resultID AS result, + mailto, + openedBy, openedDate, openedBuild, + assignedTo, assignedDate, + resolvedBy, resolution, resolvedBuild, resolvedDate, + closedBy, closedDate, + lastEditedBy, lastEditedDate, + bugKeyword AS keywords + ') + ->from(BUGFREE_TABLE_BUGINFO) + ->where('isDroped')->eq(0) + ->orderBy('bugID') + ->fetchAll('id', $autoCompany = false); + foreach($bugs as $bugID => $bug) + { + /* Fix some fileds of bug. */ + $bugID = (int)$bugID; + unset($bug->id); + + if($bug->assignedTo == 'Closed') $bug->assignedTo = 'closed'; + if($bug->assignedTo == 'Active') $bug->assignedTo = ''; + + $bug->type = strtolower($bug->type); + $bug->found = strtolower($bug->found); + $bug->status = strtolower($bug->status); + $bug->os = strtolower($bug->os); + $bug->browser= strtolower($bug->browser); + $bug->steps = nl2br($bug->steps); + + if($bug->os == 'winvista') $bug->os = 'vista'; + if($bug->browser == 'firefox3.0') $bug->browser = 'firefox3'; + if($bug->browser == 'firefox2.0') $bug->browser = 'firefox2'; + if($bug->openedBuild == 'N/A') $bug->openedBuild = ''; + if(!$bug->case) $bug->caseVersion = 0; + + $bug->resolution = str_replace(' ', '', strtolower($bug->resolution)); + $bug->product = $this->map['product'][$bug->product]; + $bug->module = $this->map['module'][$bug->module]; + $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); + $this->map['bug'][$bugID] = $this->dao->lastInsertID(); + } + + /* Update duplicated bugs. */ + foreach($this->map['bug'] as $oldBugID => $newBugID) + { + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('duplicateBug')->eq($newBugID)->where('duplicateBug')->eq($oldBugID)->exec(); + } + return count($bugs); + } + + /** + * Convert cases. + * + * @access public + * @return int converted cases count. + */ + public function convertCase() + { + $cases = $this->dao + ->dbh($this->sourceDBH) + ->select(' + caseID AS id, + projectID AS product, + moduleID AS module, + caseTitle AS title, + caseSteps AS step, + casePriority AS pri, + caseType AS type, + caseStatus AS status, + caseMethod AS howRun, + casePlan AS stage, + openedBy, openedDate, + lastEditedBy, lastEditedDate, + scriptedBy, scriptedDate, scriptStatus, scriptLocation, + linkID AS linkCase, + casekeyword AS keywords, + 1 AS version, + bugID + ') + ->from(BUGFREE_TABLE_CASEINFO) + ->where('isDroped')->eq(0) + ->orderBy('caseID') + ->fetchAll('id', $autoCompany = false); + foreach($cases as $caseID => $case) + { + /* Fix fields of case. */ + $caseID = (int)$caseID; + $step = $case->step; + $bugs = explode(',', $case->bugID); + unset($case->id); + unset($case->step); + unset($case->bugID); + + $case->type = strtolower($case->type); + $case->status = strtolower($case->status); + $case->howRun = strtolower($case->howRun); + $case->stage = strtolower($case->stage); + + if($case->type == 'configuration') $case->type = 'config'; + if($case->type == 'setup') $case->type = 'install'; + if($case->type == 'functional') $case->type = 'feature'; + if($case->status == 'active') $case->status = 'normal'; + + /* Change product and module by zentao's product and module. */ + $case->product = $this->map['product'][$case->product]; + $case->module = $this->map['module'][$case->module]; + + /* Insert into case table. */ + $this->dao->dbh($this->dbh)->insert(TABLE_CASE)->data($case)->exec(); + $zentaoCaseID = $this->dao->lastInsertID(); + $this->map['case'][$caseID] = $zentaoCaseID; + + /* Insert into case step table. */ + $caseStep->case = $zentaoCaseID; + $caseStep->version = 1; + $caseStep->desc = $step; + $this->dao->dbh($this->dbh)->insert(TABLE_CASESTEP)->data($caseStep)->exec(); + + /* Update related bugs. */ + foreach($bugs as $bugID) + { + if(!isset($this->map['bug'][$bugID])) continue; + $zentaoBugID = $this->map['bug'][$bugID]; + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('`case`')->eq($zentaoCaseID)->where('id')->eq($zentaoBugID)->limit(1)->exec(); + } + } + return count($cases); + } + + /** + * Convert results. + * + * @access public + * @return int converted results count. + */ + public function convertResult() + { + $results = $this->dao->dbh($this->sourceDBH) + ->select(' + resultID AS id, + caseID AS `case`, + resultValue AS caseResult, + 1 AS version, + openedDate as date, + bugID + ') + ->from(BUGFREE_TABLE_RESULTINFO) + ->orderBy('id') + ->fetchAll('id', $autoCompany = false); + foreach($results as $resultID => $result) + { + unset($result->id); + + /* The bug id of zentao. */ + $bugID = (int)$result->bugID; + $zentaoBugID = $this->map['bug'][$bugID]; + unset($result->bugID); + + /* Insert into test result table. */ + $this->dao->dbh($this->dbh)->insert(TABLE_TESTRESULT)->data($result)->exec(); + $zentaoResultID = $this->dao->lastInsertId(); + $this->map['result'][$resultID] = $zentaoResultID; + + /* Update result table. */ + $this->dao->dbh($this->dbh)->update(TABLE_BUG)->set('result')->eq($zentaoResultID)->where('id')->eq($zentaoBugID)->limit(1)->exec(); + } + return count($results); + } + + /** + * Convert actions. + * + * @access public + * @return int converted actions count. + */ + public function convertAction() + { + $actions = $this->dao + ->dbh($this->sourceDBH) + ->select("actionID AS id, + actionTarget AS objectType, + idValue AS objectID, + actionUser AS actor, + actionType AS action, + actionDate AS date, + actionNote AS comment + ") + ->from(BUGFREE_TABLE_ACTION) + ->where('actionTarget' != 'Result') + ->orderBy('actionID') + ->fetchAll('id', $autoComapny = false); + + foreach($actions as $actionID => $action) + { + $actionID = (int)$action->id; + unset($action->id); + $action->objectType = strtolower($action->objectType); + $action->action = strtolower($action->action); + $action->objectID = $this->map[$action->objectType][$action->objectID]; + + $this->dao->dbh($this->dbh)->insert(TABLE_ACTION)->data($action)->exec(); + $this->map['action'][$actionID] = $this->dao->lastInsertID(); + } + return count($actions); + } + + /** + * Convert histories. + * + * @access public + * @return int the converted histories count. + */ + public function convertHistory() + { + $histories = $this->dao->dbh($this->sourceDBH) + ->select('actioID, actionField AS field, oldValue AS old, newValue AS new') + ->from(BUGFREE_TABLE_HISTORY) + ->orderBy('historyID') + ->fetchAll('', $autoCompany = false); + foreach($histories as $history) + { + $history->actionID = $this->map['action'][$history->actionID]; + $this->dao->dbh($this->dbh)->insert(TABLE_HISTORY)->data($history)->exec(); + } + } + + /** + * Convert attachments. + * + * @access public + * @return int the converted files count. + */ + public function convertFile() + { + $this->setPath(); + $files = $this->dao->dbh($this->sourceDBH) + ->select(" + actionID, + fileName AS pathname, + fileTitle AS title, + fileType AS extension, + fileSize AS size + ") + ->from(BUGFREE_TABLE_FILE) + ->orderBy('fileID') + ->fetchAll('', $autoCompany = false); + foreach($files as $file) + { + /* Get the actionID in zentao, to get file info. */ + $zentaoActionID = $this->map['action'][$file->actionID]; + $zentaoAction = $this->dao->dbh($this->dbh)->findById($zentaoActionID)->from(TABLE_ACTION)->fetch(); + $file->objectType = $zentaoAction->objectType; + $file->objectID = $zentaoAction->objectID; + $file->addedBy = $zentaoAction->actor; + $file->addedDate = $zentaoAction->date; + unset($file->actionID); + + /* Compute the file size. */ + if(strpos($file->size, 'KB')) $file->size = (int)(str_replace('KB', '', $file->size) * 1024); + if(strpos($file->size, 'MB')) $file->size = (int)(str_replace('MB', '', $file->size) * 1024 * 1024); + + /* Insert into database. */ + $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); + + /* Copy file. */ + $soureFile = $this->filePath . $file->pathname; + if(!file_exists($soureFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); + continue; + } + $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; + $targetPath = dirname($targetFile); + if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); + if(!copy($soureFile, $targetFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); + } + } + return count($files); + } + + /** + * Clear the converted records. + * + * @access public + * @return void + */ + public function clear() + { + foreach($this->session->state as $table => $maxID) + { + $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); + } + } +} diff --git a/module/convert/converter/redmine.php b/module/convert/converter/redmine.php index d5a44ce51a..464b6edfcb 100644 --- a/module/convert/converter/redmine.php +++ b/module/convert/converter/redmine.php @@ -1,88 +1,88 @@ - - * @package convert - * @version $Id $ - * @link http://www.zentao.net - */ -class redmineConvertModel extends convertModel -{ - public $map = array(); - public $filePath = ''; - static public $info = array(); - - /** - * Connect to db auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - parent::connectDB(); - } - - /** - * Check table. - * - * @access public - * @return bool - */ - public function checkTables() - { - return true; - } - - /** - * Check the install path. - * - * @access public - * @return bool - */ - public function checkPath() - { - $this->setPath(); - return file_exists($this->filePath); - } - - /** - * Set the path of attachments. - * - * @access public - * @return bool - */ - public function setPath() - { - $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'files' . $this->app->getPathFix(); - } - - /** - * Excute the convert. - * - * @param int $version - * @access public - * @return void - */ - public function execute($version) - { - } - - /** - * Clear rows added in converting. - * - * @access public - * @return void - */ - public function clear() - { - foreach($this->session->state as $table => $maxID) - { - $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); - } - } -} + + * @package convert + * @version $Id $ + * @link http://www.zentao.net + */ +class redmineConvertModel extends convertModel +{ + public $map = array(); + public $filePath = ''; + static public $info = array(); + + /** + * Connect to db auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + parent::connectDB(); + } + + /** + * Check table. + * + * @access public + * @return bool + */ + public function checkTables() + { + return true; + } + + /** + * Check the install path. + * + * @access public + * @return bool + */ + public function checkPath() + { + $this->setPath(); + return file_exists($this->filePath); + } + + /** + * Set the path of attachments. + * + * @access public + * @return bool + */ + public function setPath() + { + $this->filePath = realpath($this->post->installPath) . $this->app->getPathFix() . 'files' . $this->app->getPathFix(); + } + + /** + * Excute the convert. + * + * @param int $version + * @access public + * @return void + */ + public function execute($version) + { + } + + /** + * Clear rows added in converting. + * + * @access public + * @return void + */ + public function clear() + { + foreach($this->session->state as $table => $maxID) + { + $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); + } + } +} diff --git a/module/convert/converter/redmine1.1.php b/module/convert/converter/redmine1.1.php index b018c8d905..8ab99848c8 100644 --- a/module/convert/converter/redmine1.1.php +++ b/module/convert/converter/redmine1.1.php @@ -1,822 +1,822 @@ - - * @package convert - * @version $Id $ - * @link http://www.zentao.net - */ -class redmine11ConvertModel extends redmineConvertModel -{ - static $convertGroupCount = 0; - static $convertUserCount = 0; - static $convertProductCount = 0; - static $convertProjectCount = 0; - static $convertStoryCount = 0; - static $convertTaskCount = 0; - static $convertBugCount = 0; - static $convertProductPlanCount = 0; - static $convertTeamCount = 0; - static $convertReleaseCount = 0; - static $convertBuildCount = 0; - static $convertDocLibCount = 0; - static $convertDocCount = 0; - static $convertFileCount = 0; - public $issueType; - - public function __construct($issueType) - { - parent::__construct(); - $this->issueType = $issueType; - } - /** - * Execute the converter. - * - * @access public - * @return array - */ - public function execute() - { - $this->clear(); - $this->setTable(); - $this->convertGroup(); - $this->convertUser(); - $this->convertUserGroup(); - $this->convertProduct(); - $this->convertProject(); - $this->convertBuildAndRelease(); - $this->convertProductPlan(); - $this->convertProjectProduct(); - $this->convertTeam(); - $this->convertDocLib(); - $this->convertDoc(); - $this->convertNews(); - $this->convertIssue(); - $this->convertFile(); - $this->dao->dbh($this->dbh); - $this->loadModel('tree')->fixModulePath(); - - $result['groups'] = self::$convertGroupCount; - $result['users'] = self::$convertUserCount ; - $result['products'] = self::$convertProductCount ; - $result['projects'] = self::$convertProjectCount ; - $result['stories'] = self::$convertStoryCount; - $result['tasks'] = self::$convertTaskCount ; - $result['bugs'] = self::$convertBugCount ; - $result['productPlans'] = self::$convertProductPlanCount; - $result['teams'] = self::$convertTeamCount; - $result['releases'] = self::$convertReleaseCount; - $result['builds'] = self::$convertBuildCount; - $result['docLibs'] = self::$convertDocLibCount ; - $result['docs'] = self::$convertDocCount; - $result['files'] = self::$convertFileCount; - return $result; - } - - /** - * Set table names. - * - * @access public - * @return void - */ - public function setTable() - { - //$dbPrefix = $this->post->dbPrefix; - $dbPrefix = ''; - define('REDMINE_TABLE_ATTACHMENTS', $dbPrefix . 'attachments'); - define('REDMINE_TABLE_AUTH_SOURCES', $dbPrefix . 'auth_sources'); - define('REDMINE_TABLE_BOARDS', $dbPrefix . 'boards'); - define('REDMINE_TABLE_CHANGES', $dbPrefix . 'changes'); - define('REDMINE_TABLE_CHANGESETS', $dbPrefix . 'changesets'); - define('REDMINE_TABLE_CHANGESETS_ISSUES', $dbPrefix . 'changesets_issues'); - define('REDMINE_TABLE_COMMENTS', $dbPrefix . 'comments'); - define('REDMINE_TABLE_CUSTOM_FIELDS', $dbPrefix . 'custom_fields'); - define('REDMINE_TABLE_CUSTOM_FIELDS_PROJECTS', $dbPrefix . 'custom_fields_projects'); - define('REDMINE_TABLE_CUSTOM_FIELDS_TRACKERS', $dbPrefix . 'custom_fields_trackers'); - define('REDMINE_TABLE_CUSTOM_VALUES', $dbPrefix . 'custom_values'); - define('REDMINE_TABLE_DOCUMENTS', $dbPrefix . 'documents'); - define('REDMINE_TABLE_ENABLED_MODULES', $dbPrefix . 'enabled_modules'); - define('REDMINE_TABLE_ENUMERATIONS', $dbPrefix . 'enumerations'); - define('REDMINE_TABLE_GROUPS_USERS', $dbPrefix . 'groups_users'); - define('REDMINE_TABLE_ISSUES', $dbPrefix . 'issues'); - define('REDMINE_TABLE_ISSUE_CATEGORIES', $dbPrefix . 'issue_categories'); - define('REDMINE_TABLE_ISSUE_RELATIONS', $dbPrefix . 'issue_relations'); - define('REDMINE_TABLE_ISSUE_STATUSES', $dbPrefix . 'issue_statuses'); - define('REDMINE_TABLE_JOURNALS', $dbPrefix . 'journals'); - define('REDMINE_TABLE_JOURNAL_DETAILS', $dbPrefix . 'journal_details'); - define('REDMINE_TABLE_MEMBERS', $dbPrefix . 'members'); - define('REDMINE_TABLE_MEMBER_ROLES', $dbPrefix . 'member_roles'); - define('REDMINE_TABLE_MESSAGES', $dbPrefix . 'messages'); - define('REDMINE_TABLE_NEWS', $dbPrefix . 'news'); - define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_ASSOCIATIONS', $dbPrefix . 'open_id_authentication_associations'); - define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_NONCES', $dbPrefix . 'open_id_authentication_nonces'); - define('REDMINE_TABLE_PROJECTS', $dbPrefix . 'projects'); - define('REDMINE_TABLE_PROJECTS_TRACKERS', $dbPrefix . 'projects_trackers'); - define('REDMINE_TABLE_QUERIES', $dbPrefix . 'queries'); - define('REDMINE_TABLE_REPOSITORIES', $dbPrefix . 'repositories'); - define('REDMINE_TABLE_ROLES', $dbPrefix . 'roles'); - define('REDMINE_TABLE_SCHEMA_MIGRATIONS', $dbPrefix . 'schema_migrations'); - define('REDMINE_TABLE_SETTINGS', $dbPrefix . 'settings'); - define('REDMINE_TABLE_TIME_ENTRIES', $dbPrefix . 'time_entries'); - define('REDMINE_TABLE_TOKENS', $dbPrefix . 'tokens'); - define('REDMINE_TABLE_TRACKERS', $dbPrefix . 'trackers'); - define('REDMINE_TABLE_USERS', $dbPrefix . 'users'); - define('REDMINE_TABLE_USER_PREFERENCES', $dbPrefix . 'user_preferences'); - define('REDMINE_TABLE_VERSIONS', $dbPrefix . 'versions'); - define('REDMINE_TABLE_WATCHERS', $dbPrefix . 'watchers'); - define('REDMINE_TABLE_WIKIS', $dbPrefix . 'wikis'); - define('REDMINE_TABLE_WIKI_CONTENTS', $dbPrefix . 'wiki_contents'); - define('REDMINE_TABLE_WIKI_CONTENT_VERSIONS', $dbPrefix . 'wiki_content_versions'); - define('REDMINE_TABLE_WIKI_PAGES', $dbPrefix . 'wiki_pages'); - define('REDMINE_TABLE_WIKI_REDIRECTS', $dbPrefix . 'wiki_redirects'); - define('REDMINE_TABLE_WORKFLOWS', $dbPrefix . 'workflows'); - } - - /** - * Convert groups. - * - * @access public - * @return void - */ - public function convertGroup() - { - /* Get group list */ - $groups = $this->dao->dbh($this->sourceDBH) - ->select("id, lastName AS name") - ->from(REDMINE_TABLE_USERS) - ->where('type')->eq('Group') - ->fetchAll('id', $autoCompany = false); - - $zentaoGroupNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_GROUP)->fetchPairs(); - $zentaoGroupIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_GROUP)->fetchPairs(); - - /* Insert into zentao */ - $convertCount = 0; - foreach($groups as $groupID =>$group) - { - unset($group->id); - if(in_array("$group->name", $zentaoGroupNames)) - { - self::$info['groups'][] = sprintf($this->lang->convert->errorGroupExists, $group->name); - $this->map['groups'][$groupID] = $zentaoGroupIDs[$group->name]; - } - else - { - $this->dao->dbh($this->dbh)->insert(TABLE_GROUP) - ->data($group)->exec(); - $this->map['groups'][$groupID] = $this->dao->lastInsertID(); - $convertCount ++; - } - } - self::$convertGroupCount += $convertCount; - } - - /** - * Convert users. - * - * @access public - * @return void - */ - public function convertUser() - { - /* Get user list. */ - $users = $this->dao->dbh($this->sourceDBH) - ->select("id, login AS account, firstname, lastname, mail as email") - ->from(REDMINE_TABLE_USERS) - ->where('type')->eq('User') - ->fetchAll('id', $autoCompany = false); - - $zentaoUserNames = $this->dao->dbh($this->dbh)->select('id, account')->from(TABLE_USER)->fetchPairs(); - $zentaoUserIDs = $this->dao->dbh($this->dbh)->select('account, id')->from(TABLE_USER)->fetchPairs(); - - /* Insert into zentao. */ - $convertCount = 0; - foreach($users as $id => $user) - { - if(in_array("$user->account", $zentaoUserNames)) - { - self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $user->account); - $this->map['users'][$id] = $zentaoUserIDs[$user->account]; - } - else - { - $user->password = md5('123456'); - $user->realname = $user->lastname . $user->firstname; - unset($user->id); - unset($user->lastname); - unset($user->firstname); - $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); - $this->map['users'][$id] = $this->dao->lastInsertID(); - $convertCount ++; - } - } - self::$convertUserCount += $convertCount; - } - - /** - * convert relationship between user and group. - * - * @access public - * @return void - */ - public function convertUserGroup() - { - $this->map['groups'][0] = 0; - /* Get relation between user and group list. */ - $userGroups = $this->dao->dbh($this->sourceDBH) - ->select("t1.group_id, t2.login as account") - ->from(REDMINE_TABLE_GROUPS_USERS)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id') - ->fetchAll('', $autoCompany = false); - - $zentaoUserGroups = $this->dao->dbh($this->dbh)->select('*')->from(TABLE_USERGROUP)->fetchAll(); - - /* Insert into zentao. */ - $userGroupExist = false; - foreach($userGroups as $userGroup) - { - $userGroup->group = $this->map['groups'][$userGroup->group_id]; - unset($userGroup->group_id); - foreach($zentaoUserGroups as $zentaoUserGroup) - { - if($userGroup->group == $zentaoUserGroup->group and $userGroup->account == $zentaoUserGroup->account) - { - $userGroupExist = true; - } - } - if($userGroupExist == false) - { - $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->data($userGroup)->exec(); - } - } - } - - /** - * convert products. - * - * @access public - * @return void - */ - public function convertProduct() - { - /* Get product list */ - $products = $this->dao->dbh($this->sourceDBH) - ->select("id, name, description as `desc`, created_on as createdDate") - ->from(REDMINE_TABLE_PROJECTS) - ->fetchAll('id', $autoComapny = false); - - /* Insert into zentao */ - foreach($products as $productID => $product) - { - unset($product->id); - $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($product)->exec(); - $this->map['products'][$productID] = $this->dao->lastInsertID(); - } - self::$convertProductCount += count($products); - } - - /** - * Convert projects. - * - * @access public - * @return void - */ - public function convertProject() - { - /* Get project list */ - $projects = $this->dao->dbh($this->sourceDBH) - ->select("id, name, project_id, description as `desc`, effective_date AS end") - ->from(REDMINE_TABLE_VERSIONS) - ->fetchAll('id', $autoComapny = false); - - /* Insert into zentao */ - foreach($projects as $projectID => $project) - { - $productID = $project->project_id; - unset($project->id); - unset($project->project_id); - $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec(); - $this->map['projects'][$productID][$projectID] = $this->dao->lastInsertID(); - $this->map['project'][$projectID] = $this->map['projects'][$productID][$projectID]; - } - - /* Create a same name project with product */ - foreach($this->map['products'] as $productID) - { - $project = $this->dao->dbh($this->dbh)->select('name')->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch(); - $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec(); - $this->map['projectOfProduct'][$productID] = $this->dao->lastinsertID(); - } - $convertCount = count($projects) + count($this->map['projectOfProduct']); - self::$convertProjectCount += $convertCount; - } - - /** - * convert builds and releases - * - * @access public - * @return void - */ - public function convertBuildAndRelease() - { - /* Get build list */ - $buildAndReleases = $this->dao->dbh($this->sourceDBH) - ->select("id, name, project_id, description as `desc`, effective_date AS date") - ->from(REDMINE_TABLE_VERSIONS) - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - $convertBuildsCount = 0; - $convertReleasesCount = 0; - $zentaoBuildNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_BUILD)->fetchPairs(); - $zentaoBuildIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_BUILD)->fetchPairs(); - $zentaoReleaseNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_RELEASE)->fetchPairs(); - $zentaoReleaseIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_RELEASE)->fetchPairs(); - foreach($buildAndReleases as $id => $buildAndRelease) - { - $buildAndRelease->project = $this->map['project'][$id]; - $buildAndRelease->product = $this->map['products'][$buildAndRelease->project_id]; - unset($buildAndRelease->id); - unset($buildAndRelease->project_id); - - if(in_array($buildAndRelease->name, $zentaoBuildNames)) - { - self::$info['builds'][] = sprintf($this->lang->convert->errorBuildExists, $buildAndRelease->name); - $buildAndRelease->build = $zentaoBuildIDs[$buildAndRelease->name]; - } - else - { - $this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($buildAndRelease)->exec(); - $buildAndRelease->build = $this->dao->lastInsertID(); - $convertBuildsCount ++; - } - - unset($buildAndRelease->project); - if(in_array($buildAndRelease->name, $zentaoBuildNames)) - { - self::$info['releases'][] = sprintf($this->lang->convert->errorReleaseExists, $buildAndRelease->name); - } - else - { - $this->dao->dbh($this->dbh)->insert(TABLE_RELEASE)->data($buildAndRelease)->exec(); - $convertReleasesCount ++; - } - } - self::$convertBuildCount += $convertBuildsCount; - self::$convertReleaseCount += $convertReleasesCount; - } - - /** - * convert productPlans - * - * @access public - * @return void - */ - public function convertProductPlan() - { - /* Get productPlan list */ - $productPlans = $this->dao->dbh($this->sourceDBH) - ->select("id, name as title, project_id, description as `desc`, effective_date as end, created_on AS begin") - ->from(REDMINE_TABLE_VERSIONS) - ->fetchAll('id', $autoCompany = false); - /* Insert into zentao */ - foreach($productPlans as $id => $productPlan) - { - $productPlan->product = $this->map['products'][$productPlan->project_id]; - unset($productPlan->id); - unset($productPlan->project_id); - $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec(); - } - - /* Create a same plan with product */ - foreach($this->map['products'] as $productID) - { - $productPlan = $this->dao->dbh($this->dbh)->select("name as title, createdDate as begin")->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch(); - $productPlan->product = $productID; - $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec(); - $this->map['planOfProduct'][$productID] = $this->dao->lastinsertID(); - } - $convertCount = count($this->map['products']) + count($productPlans); - self::$convertProductPlanCount += $convertCount; - } - - /** - * convert relationship between project and product. - * - * @access public - * @return void - */ - public function convertProjectProduct() - { - foreach($this->map['projects'] as $productID => $projects) - { - foreach($projects as $projectID => $project) - { - $this->dao->dbh($this->dbh)->insert(TABLE_PROJECTPRODUCT) - ->set('project')->eq($project) - ->set('product')->eq($this->map['products'][$productID]) - ->exec(); - } - } - } - - /** - * convert teams. - * - * @access public - * @return void - */ - public function convertTeam() - { - /* Get team list */ - $teams = $this->dao->dbh($this->sourceDBH) - ->select("t2.login as account, t1.project_id, t1.created_on AS joinDate") - ->from(REDMINE_TABLE_MEMBERS)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id') - ->where('t2.type')->eq('User') - ->fetchAll('', $autoCompany = false); - - /* Insert into zentao */ - foreach($teams as $team) - { - $productID = $team->project_id; - unset($team->project_id); - foreach($this->map['projects'][$productID] as $projectID) - { - $team->project = $projectID; - $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($team)->exec(); - } - } - self::$convertTeamCount += count($teams); - } - - /** - * convert docLibs. - * - * @access public - * @return void - */ - public function convertDocLib() - { - /* Get docLib list */ - $docLibs = $this->dao->dbh($this->sourceDBH) - ->select("id, name")->from(REDMINE_TABLE_ENUMERATIONS) - ->where('type')->eq('DocumentCategory') - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($docLibs as $docLibID => $docLib) - { - unset($docLib->id); - $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($docLib)->exec(); - $this->map['docLibs'][$docLibID] = $this->dao->lastInsertID(); - } - self::$convertDocLibCount += count($docLibs); - } - - /** - * convert docs. - * - * @access public - * @return void - */ - public function convertDoc() - { - /* Get all docs */ - $docs = $this->dao->dbh($this->sourceDBH) - ->select("t1.id, t1.project_id AS product, t2.id AS lib, t1.title, t1.description AS content, t1.created_on AS addedDate") - ->from(REDMINE_TABLE_DOCUMENTS)->alias('t1') - ->leftjoin(REDMINE_TABLE_ENUMERATIONS)->alias('t2')->on('t1.category_id = t2.id') - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($docs as $docID => $doc) - { - unset($doc->id); - $doc->type = 'text'; - $doc->project = 0; - $doc->product = $this->map['products'][$doc->product]; - $doc->lib = $this->map['docLibs'][$doc->lib]; - $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec(); - $this->map['docs'][$docID] = $this->dao->lastInsertID(); - } - self::$convertDocCount += count($docs); - } - - /** - * convert news. - * - * @access public - * @return void - */ - public function convertNews() - { - /* Get news from redmine */ - $news = $this->dao->dbh($this->sourceDBH) - ->select("t1.project_id as product, t1.title, t1.summary as digest, t1.description as content, t2.login as addedBy, t1.created_on as addedDate") - ->from(REDMINE_TABLE_NEWS)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id') - ->fetchAll('', $autoCompany = false); - - /* Create a news docLib */ - $newLib->name = 'news'; - $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($newLib)->exec(); - $this->map['news'] = $this->dao->lastInsertID(); - self::$convertDocLibCount += 1; - - /* Insert into zentao */ - foreach($news as $new) - { - $new->product = $this->map['products'][$new->product]; - $new->project = 0; - $new->lib = $this->map['news']; - $new->type = 'text'; - - $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($new)->exec(); - } - self::$convertDocCount += count($news); - } - - /** - * convert issue - * - * @param array $aimTypes //aimTypes['issueTypeID'] = aimtype eg. aimTypes[1] = 'bug'; - * @param array $statusTypes //statusTypes['task']['statusTypeID'] = statusType eg. statusTypes['task'][1] = 'wait'; - * //statusTypes['bug']['statusTypeID'] = statusType eg. statusTypes['bug'][1] = 'active'; - * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1; - * @access public - * @return void - */ - public function convertIssue() - { - $aimTypes = $this->issueType->aimTypes; - $statusTypes = $this->issueType->statusTypes; - $priTypes = $this->issueType->priTypes; - - foreach($aimTypes as $issueType => $aimType) - { - if('story' == $aimType) - { - $this->convertStory($issueType, $statusTypes, $priTypes); - } - elseif('task' == $aimType) - { - $this->convertTask($issueType, $statusTypes, $priTypes); - } - else - { - $this->convertBug($issueType, $statusTypes, $priTypes); - } - } - } - - /** - * convert story - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes - * @access public - * @return void - */ - public function convertStory($issueType, $statusTypes, $priTypes) - { - /* Get story list*/ - $stories = $this->dao->dbh($this->sourceDBH) - ->select("t1.id, t1.project_id as product, t1.subject as title, t1.description as spec, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate") - ->from(REDMINE_TABLE_ISSUES)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') - ->where('t1.tracker_id')->eq($issueType) - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($stories as $issueID => $story) - { - $storySpec->title = $story->title; - $storySpec->spec = $story->spec; - unset($story->id); - unset($story->spec); - - /* Insert story into table story */ - $story->product = $this->map['products'][$story->product]; - $story->module = 0; - $story->plan = $this->map['planOfProduct'][$story->product]; - $story->fromBug = 0; - $story->pri = $priTypes['story'][$story->pri]; - $story->status = $statusTypes['story'][$story->status]; - $story->toBug = 0; - $story->duplicateStory = 0; - $this->dao->dbh($this->dbh)->insert(TABLE_STORY)->data($story)->exec(); - $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); - $this->map['issueType'][$issueID] = 'story'; - - /* Insert data into table storySpec */ - $storySpec->story = $this->map['issueID'][$issueID]; - $storySpec->version = 1; - $this->dao->dbh($this->dbh)->insert(TABLE_STORYSPEC)->data($storySpec)->exec(); - } - self::$convertStoryCount += count($stories); - } - - /** - * convert task - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes - * @access public - * @return void - */ - public function convertTask($issueType, $statusTypes, $priTypes) - { - /* Get task list */ - $tasks = $this->dao->dbh($this->sourceDBH) - ->select("t1.id, t1.project_id as product, t1.fixed_version_id as project, t1.subject as name, t1.description as `desc`, t1.due_date as deadline, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate") - ->from(REDMINE_TABLE_ISSUES)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') - ->where('t1.tracker_id')->eq($issueType) - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($tasks as $issueID => $task) - { - $task->story = 0; - $task->storyVersion = 0; - $task->type = 'misc'; - $task->pri = $priTypes['task'][$task->pri]; - $task->status = $statusTypes['task'][$task->status]; - if($task->project == 0) - { - $task->project = $this->map['projectOfProduct'][$task->product]; - } - else - { - $task->project = $this->map['project'][$task->project]; - } - unset($task->id); - unset($task->product); - $this->dao->dbh($this->dbh)->insert(TABLE_TASK)->data($task)->exec(); - $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); - $this->map['issueType'][$issueID] = 'task'; - } - self::$convertTaskCount += count($tasks); - } - - /** - * convert bug - * - * @param array $issueType - * @param array $statusTypes - * @param array $priTypes - * @access public - * @return void - */ - public function convertBug($issueType, $statusTypes, $priTypes) - { - /* Get bug list */ - $bugs = $this->dao->dbh($this->sourceDBH) - ->select("t1.id, t1.project_id as product, t1.fixed_version_id project, t1.subject as title, t1.description as steps, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.updated_on as lastEditedDate") - ->from(REDMINE_TABLE_ISSUES)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') - ->where('t1.tracker_id')->eq($issueType) - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($bugs as $issueID => $bug) - { - $bug->product = $this->map['products'][$bug->product]; - $bug->module = 0; - $bug->story = 0; - $bug->storyVersion = 1; - $bug->task = 0; - $bug->severity = 3; - $bug->type = 'others'; - $bug->status = $statusTypes['bug'][$bug->status]; - $bug->openedBuild = 'trunk'; - $bug->duplicateBug = 0; - $bug->case = 0; - $bug->caseVersion = 1; - $bug->result = 0; - if($bug->project == 0) - { - $bug->project = $this->map['projectOfProduct'][$bug->product]; - } - else - { - $bug->project = $this->map['project'][$bug->project]; - } - unset($bug->id); - $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); - $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); - $this->map['issueType'][$issueID] = 'bug'; - } - self::$convertBugCount += count($bugs); - } - - /** - * Convert attachments. - * - * @access public - * @return void - */ - public function convertFile() - { - $this->setPath(); - - /* Get file list */ - $files = $this->dao->dbh($this->sourceDBH) - ->select('t1.id, t1.container_id as objectID, t1.container_type as objectType, t1.filename as title, t1.disk_filename as pathname, t1.filesize as size, t2.login as addedBy, t1.created_on as addedDate, description') - ->from(REDMINE_TABLE_ATTACHMENTS)->alias('t1') - ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id') - ->fetchAll('id', $autoCompany = false); - - /* Insert into zentao */ - foreach($files as $fileID => $file) - { - if($file->description != '') - { - $file->title = $file->description; - unset($file->description); - } - else - { - unset($file->description); - } - - /* Transform objectType and objectID */ - if($file->objectType == 'Issue') - { - $file->objectType = $this->map['issueType'][$file->objectID]; - $file->objectID = $this->map['issueID'][$file->objectID]; - } - elseif($file->objectType == 'Document') - { - $file->objectType = 'doc' ; - $file->objectID = $this->map['docs'][$file->objectID]; - } - elseif($file->objectType == 'WikiPage') - { - continue; - } - elseif($file->objectType == 'Version') - { - $doc->project = $this->map['project'][$file->objectID]; - $doc = $this->dao->dbh($this->dbh)->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($doc->project)->fetch(); - $doc->lib = 'project'; - $doc->module = 0; - $doc->title = $file->title; - $doc->type = 'file'; - $doc->addedBy = $file->addedBy; - $doc->addedDate = $file->addedDate; - $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec(); - self::$convertDocCount += 1; - - $file->objectType = 'doc'; - $file->objectID = $this->dao->lastInsertID(); - } - - $pathname = pathinfo($file->pathname); - $file->extension = $pathname["extension"]; - unset($file->id); - - /* Insert into database. */ - $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); - - /* Copy file. */ - $soureFile = $this->filePath . $file->pathname; - if(!file_exists($soureFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); - continue; - } - $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; - $targetPath = dirname($targetFile); - if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); - if(!copy($soureFile, $targetFile)) - { - self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); - } - } - self::$convertFileCount += count($files); - } - - /** - * Clear the converted records. - * - * @access public - * @return void - */ - public function clear() - { - foreach($this->session->state as $table => $maxID) - { - $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); - } - } -} + + * @package convert + * @version $Id $ + * @link http://www.zentao.net + */ +class redmine11ConvertModel extends redmineConvertModel +{ + static $convertGroupCount = 0; + static $convertUserCount = 0; + static $convertProductCount = 0; + static $convertProjectCount = 0; + static $convertStoryCount = 0; + static $convertTaskCount = 0; + static $convertBugCount = 0; + static $convertProductPlanCount = 0; + static $convertTeamCount = 0; + static $convertReleaseCount = 0; + static $convertBuildCount = 0; + static $convertDocLibCount = 0; + static $convertDocCount = 0; + static $convertFileCount = 0; + public $issueType; + + public function __construct($issueType) + { + parent::__construct(); + $this->issueType = $issueType; + } + /** + * Execute the converter. + * + * @access public + * @return array + */ + public function execute() + { + $this->clear(); + $this->setTable(); + $this->convertGroup(); + $this->convertUser(); + $this->convertUserGroup(); + $this->convertProduct(); + $this->convertProject(); + $this->convertBuildAndRelease(); + $this->convertProductPlan(); + $this->convertProjectProduct(); + $this->convertTeam(); + $this->convertDocLib(); + $this->convertDoc(); + $this->convertNews(); + $this->convertIssue(); + $this->convertFile(); + $this->dao->dbh($this->dbh); + $this->loadModel('tree')->fixModulePath(); + + $result['groups'] = self::$convertGroupCount; + $result['users'] = self::$convertUserCount ; + $result['products'] = self::$convertProductCount ; + $result['projects'] = self::$convertProjectCount ; + $result['stories'] = self::$convertStoryCount; + $result['tasks'] = self::$convertTaskCount ; + $result['bugs'] = self::$convertBugCount ; + $result['productPlans'] = self::$convertProductPlanCount; + $result['teams'] = self::$convertTeamCount; + $result['releases'] = self::$convertReleaseCount; + $result['builds'] = self::$convertBuildCount; + $result['docLibs'] = self::$convertDocLibCount ; + $result['docs'] = self::$convertDocCount; + $result['files'] = self::$convertFileCount; + return $result; + } + + /** + * Set table names. + * + * @access public + * @return void + */ + public function setTable() + { + //$dbPrefix = $this->post->dbPrefix; + $dbPrefix = ''; + define('REDMINE_TABLE_ATTACHMENTS', $dbPrefix . 'attachments'); + define('REDMINE_TABLE_AUTH_SOURCES', $dbPrefix . 'auth_sources'); + define('REDMINE_TABLE_BOARDS', $dbPrefix . 'boards'); + define('REDMINE_TABLE_CHANGES', $dbPrefix . 'changes'); + define('REDMINE_TABLE_CHANGESETS', $dbPrefix . 'changesets'); + define('REDMINE_TABLE_CHANGESETS_ISSUES', $dbPrefix . 'changesets_issues'); + define('REDMINE_TABLE_COMMENTS', $dbPrefix . 'comments'); + define('REDMINE_TABLE_CUSTOM_FIELDS', $dbPrefix . 'custom_fields'); + define('REDMINE_TABLE_CUSTOM_FIELDS_PROJECTS', $dbPrefix . 'custom_fields_projects'); + define('REDMINE_TABLE_CUSTOM_FIELDS_TRACKERS', $dbPrefix . 'custom_fields_trackers'); + define('REDMINE_TABLE_CUSTOM_VALUES', $dbPrefix . 'custom_values'); + define('REDMINE_TABLE_DOCUMENTS', $dbPrefix . 'documents'); + define('REDMINE_TABLE_ENABLED_MODULES', $dbPrefix . 'enabled_modules'); + define('REDMINE_TABLE_ENUMERATIONS', $dbPrefix . 'enumerations'); + define('REDMINE_TABLE_GROUPS_USERS', $dbPrefix . 'groups_users'); + define('REDMINE_TABLE_ISSUES', $dbPrefix . 'issues'); + define('REDMINE_TABLE_ISSUE_CATEGORIES', $dbPrefix . 'issue_categories'); + define('REDMINE_TABLE_ISSUE_RELATIONS', $dbPrefix . 'issue_relations'); + define('REDMINE_TABLE_ISSUE_STATUSES', $dbPrefix . 'issue_statuses'); + define('REDMINE_TABLE_JOURNALS', $dbPrefix . 'journals'); + define('REDMINE_TABLE_JOURNAL_DETAILS', $dbPrefix . 'journal_details'); + define('REDMINE_TABLE_MEMBERS', $dbPrefix . 'members'); + define('REDMINE_TABLE_MEMBER_ROLES', $dbPrefix . 'member_roles'); + define('REDMINE_TABLE_MESSAGES', $dbPrefix . 'messages'); + define('REDMINE_TABLE_NEWS', $dbPrefix . 'news'); + define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_ASSOCIATIONS', $dbPrefix . 'open_id_authentication_associations'); + define('REDMINE_TABLE_OPEN_ID_AUTHENTICATION_NONCES', $dbPrefix . 'open_id_authentication_nonces'); + define('REDMINE_TABLE_PROJECTS', $dbPrefix . 'projects'); + define('REDMINE_TABLE_PROJECTS_TRACKERS', $dbPrefix . 'projects_trackers'); + define('REDMINE_TABLE_QUERIES', $dbPrefix . 'queries'); + define('REDMINE_TABLE_REPOSITORIES', $dbPrefix . 'repositories'); + define('REDMINE_TABLE_ROLES', $dbPrefix . 'roles'); + define('REDMINE_TABLE_SCHEMA_MIGRATIONS', $dbPrefix . 'schema_migrations'); + define('REDMINE_TABLE_SETTINGS', $dbPrefix . 'settings'); + define('REDMINE_TABLE_TIME_ENTRIES', $dbPrefix . 'time_entries'); + define('REDMINE_TABLE_TOKENS', $dbPrefix . 'tokens'); + define('REDMINE_TABLE_TRACKERS', $dbPrefix . 'trackers'); + define('REDMINE_TABLE_USERS', $dbPrefix . 'users'); + define('REDMINE_TABLE_USER_PREFERENCES', $dbPrefix . 'user_preferences'); + define('REDMINE_TABLE_VERSIONS', $dbPrefix . 'versions'); + define('REDMINE_TABLE_WATCHERS', $dbPrefix . 'watchers'); + define('REDMINE_TABLE_WIKIS', $dbPrefix . 'wikis'); + define('REDMINE_TABLE_WIKI_CONTENTS', $dbPrefix . 'wiki_contents'); + define('REDMINE_TABLE_WIKI_CONTENT_VERSIONS', $dbPrefix . 'wiki_content_versions'); + define('REDMINE_TABLE_WIKI_PAGES', $dbPrefix . 'wiki_pages'); + define('REDMINE_TABLE_WIKI_REDIRECTS', $dbPrefix . 'wiki_redirects'); + define('REDMINE_TABLE_WORKFLOWS', $dbPrefix . 'workflows'); + } + + /** + * Convert groups. + * + * @access public + * @return void + */ + public function convertGroup() + { + /* Get group list */ + $groups = $this->dao->dbh($this->sourceDBH) + ->select("id, lastName AS name") + ->from(REDMINE_TABLE_USERS) + ->where('type')->eq('Group') + ->fetchAll('id', $autoCompany = false); + + $zentaoGroupNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_GROUP)->fetchPairs(); + $zentaoGroupIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_GROUP)->fetchPairs(); + + /* Insert into zentao */ + $convertCount = 0; + foreach($groups as $groupID =>$group) + { + unset($group->id); + if(in_array("$group->name", $zentaoGroupNames)) + { + self::$info['groups'][] = sprintf($this->lang->convert->errorGroupExists, $group->name); + $this->map['groups'][$groupID] = $zentaoGroupIDs[$group->name]; + } + else + { + $this->dao->dbh($this->dbh)->insert(TABLE_GROUP) + ->data($group)->exec(); + $this->map['groups'][$groupID] = $this->dao->lastInsertID(); + $convertCount ++; + } + } + self::$convertGroupCount += $convertCount; + } + + /** + * Convert users. + * + * @access public + * @return void + */ + public function convertUser() + { + /* Get user list. */ + $users = $this->dao->dbh($this->sourceDBH) + ->select("id, login AS account, firstname, lastname, mail as email") + ->from(REDMINE_TABLE_USERS) + ->where('type')->eq('User') + ->fetchAll('id', $autoCompany = false); + + $zentaoUserNames = $this->dao->dbh($this->dbh)->select('id, account')->from(TABLE_USER)->fetchPairs(); + $zentaoUserIDs = $this->dao->dbh($this->dbh)->select('account, id')->from(TABLE_USER)->fetchPairs(); + + /* Insert into zentao. */ + $convertCount = 0; + foreach($users as $id => $user) + { + if(in_array("$user->account", $zentaoUserNames)) + { + self::$info['users'][] = sprintf($this->lang->convert->errorUserExists, $user->account); + $this->map['users'][$id] = $zentaoUserIDs[$user->account]; + } + else + { + $user->password = md5('123456'); + $user->realname = $user->lastname . $user->firstname; + unset($user->id); + unset($user->lastname); + unset($user->firstname); + $this->dao->dbh($this->dbh)->insert(TABLE_USER)->data($user)->exec(); + $this->map['users'][$id] = $this->dao->lastInsertID(); + $convertCount ++; + } + } + self::$convertUserCount += $convertCount; + } + + /** + * convert relationship between user and group. + * + * @access public + * @return void + */ + public function convertUserGroup() + { + $this->map['groups'][0] = 0; + /* Get relation between user and group list. */ + $userGroups = $this->dao->dbh($this->sourceDBH) + ->select("t1.group_id, t2.login as account") + ->from(REDMINE_TABLE_GROUPS_USERS)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id') + ->fetchAll('', $autoCompany = false); + + $zentaoUserGroups = $this->dao->dbh($this->dbh)->select('*')->from(TABLE_USERGROUP)->fetchAll(); + + /* Insert into zentao. */ + $userGroupExist = false; + foreach($userGroups as $userGroup) + { + $userGroup->group = $this->map['groups'][$userGroup->group_id]; + unset($userGroup->group_id); + foreach($zentaoUserGroups as $zentaoUserGroup) + { + if($userGroup->group == $zentaoUserGroup->group and $userGroup->account == $zentaoUserGroup->account) + { + $userGroupExist = true; + } + } + if($userGroupExist == false) + { + $this->dao->dbh($this->dbh)->insert(TABLE_USERGROUP)->data($userGroup)->exec(); + } + } + } + + /** + * convert products. + * + * @access public + * @return void + */ + public function convertProduct() + { + /* Get product list */ + $products = $this->dao->dbh($this->sourceDBH) + ->select("id, name, description as `desc`, created_on as createdDate") + ->from(REDMINE_TABLE_PROJECTS) + ->fetchAll('id', $autoComapny = false); + + /* Insert into zentao */ + foreach($products as $productID => $product) + { + unset($product->id); + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCT)->data($product)->exec(); + $this->map['products'][$productID] = $this->dao->lastInsertID(); + } + self::$convertProductCount += count($products); + } + + /** + * Convert projects. + * + * @access public + * @return void + */ + public function convertProject() + { + /* Get project list */ + $projects = $this->dao->dbh($this->sourceDBH) + ->select("id, name, project_id, description as `desc`, effective_date AS end") + ->from(REDMINE_TABLE_VERSIONS) + ->fetchAll('id', $autoComapny = false); + + /* Insert into zentao */ + foreach($projects as $projectID => $project) + { + $productID = $project->project_id; + unset($project->id); + unset($project->project_id); + $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec(); + $this->map['projects'][$productID][$projectID] = $this->dao->lastInsertID(); + $this->map['project'][$projectID] = $this->map['projects'][$productID][$projectID]; + } + + /* Create a same name project with product */ + foreach($this->map['products'] as $productID) + { + $project = $this->dao->dbh($this->dbh)->select('name')->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch(); + $this->dao->dbh($this->dbh)->insert(TABLE_PROJECT)->data($project)->exec(); + $this->map['projectOfProduct'][$productID] = $this->dao->lastinsertID(); + } + $convertCount = count($projects) + count($this->map['projectOfProduct']); + self::$convertProjectCount += $convertCount; + } + + /** + * convert builds and releases + * + * @access public + * @return void + */ + public function convertBuildAndRelease() + { + /* Get build list */ + $buildAndReleases = $this->dao->dbh($this->sourceDBH) + ->select("id, name, project_id, description as `desc`, effective_date AS date") + ->from(REDMINE_TABLE_VERSIONS) + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + $convertBuildsCount = 0; + $convertReleasesCount = 0; + $zentaoBuildNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_BUILD)->fetchPairs(); + $zentaoBuildIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_BUILD)->fetchPairs(); + $zentaoReleaseNames = $this->dao->dbh($this->dbh)->select('id, name')->from(TABLE_RELEASE)->fetchPairs(); + $zentaoReleaseIDs = $this->dao->dbh($this->dbh)->select('name, id')->from(TABLE_RELEASE)->fetchPairs(); + foreach($buildAndReleases as $id => $buildAndRelease) + { + $buildAndRelease->project = $this->map['project'][$id]; + $buildAndRelease->product = $this->map['products'][$buildAndRelease->project_id]; + unset($buildAndRelease->id); + unset($buildAndRelease->project_id); + + if(in_array($buildAndRelease->name, $zentaoBuildNames)) + { + self::$info['builds'][] = sprintf($this->lang->convert->errorBuildExists, $buildAndRelease->name); + $buildAndRelease->build = $zentaoBuildIDs[$buildAndRelease->name]; + } + else + { + $this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($buildAndRelease)->exec(); + $buildAndRelease->build = $this->dao->lastInsertID(); + $convertBuildsCount ++; + } + + unset($buildAndRelease->project); + if(in_array($buildAndRelease->name, $zentaoBuildNames)) + { + self::$info['releases'][] = sprintf($this->lang->convert->errorReleaseExists, $buildAndRelease->name); + } + else + { + $this->dao->dbh($this->dbh)->insert(TABLE_RELEASE)->data($buildAndRelease)->exec(); + $convertReleasesCount ++; + } + } + self::$convertBuildCount += $convertBuildsCount; + self::$convertReleaseCount += $convertReleasesCount; + } + + /** + * convert productPlans + * + * @access public + * @return void + */ + public function convertProductPlan() + { + /* Get productPlan list */ + $productPlans = $this->dao->dbh($this->sourceDBH) + ->select("id, name as title, project_id, description as `desc`, effective_date as end, created_on AS begin") + ->from(REDMINE_TABLE_VERSIONS) + ->fetchAll('id', $autoCompany = false); + /* Insert into zentao */ + foreach($productPlans as $id => $productPlan) + { + $productPlan->product = $this->map['products'][$productPlan->project_id]; + unset($productPlan->id); + unset($productPlan->project_id); + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec(); + } + + /* Create a same plan with product */ + foreach($this->map['products'] as $productID) + { + $productPlan = $this->dao->dbh($this->dbh)->select("name as title, createdDate as begin")->from(TABLE_PRODUCT)->where('id')->eq($productID)->fetch(); + $productPlan->product = $productID; + $this->dao->dbh($this->dbh)->insert(TABLE_PRODUCTPLAN)->data($productPlan)->exec(); + $this->map['planOfProduct'][$productID] = $this->dao->lastinsertID(); + } + $convertCount = count($this->map['products']) + count($productPlans); + self::$convertProductPlanCount += $convertCount; + } + + /** + * convert relationship between project and product. + * + * @access public + * @return void + */ + public function convertProjectProduct() + { + foreach($this->map['projects'] as $productID => $projects) + { + foreach($projects as $projectID => $project) + { + $this->dao->dbh($this->dbh)->insert(TABLE_PROJECTPRODUCT) + ->set('project')->eq($project) + ->set('product')->eq($this->map['products'][$productID]) + ->exec(); + } + } + } + + /** + * convert teams. + * + * @access public + * @return void + */ + public function convertTeam() + { + /* Get team list */ + $teams = $this->dao->dbh($this->sourceDBH) + ->select("t2.login as account, t1.project_id, t1.created_on AS joinDate") + ->from(REDMINE_TABLE_MEMBERS)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.user_id = t2.id') + ->where('t2.type')->eq('User') + ->fetchAll('', $autoCompany = false); + + /* Insert into zentao */ + foreach($teams as $team) + { + $productID = $team->project_id; + unset($team->project_id); + foreach($this->map['projects'][$productID] as $projectID) + { + $team->project = $projectID; + $this->dao->dbh($this->dbh)->insert(TABLE_TEAM)->data($team)->exec(); + } + } + self::$convertTeamCount += count($teams); + } + + /** + * convert docLibs. + * + * @access public + * @return void + */ + public function convertDocLib() + { + /* Get docLib list */ + $docLibs = $this->dao->dbh($this->sourceDBH) + ->select("id, name")->from(REDMINE_TABLE_ENUMERATIONS) + ->where('type')->eq('DocumentCategory') + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($docLibs as $docLibID => $docLib) + { + unset($docLib->id); + $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($docLib)->exec(); + $this->map['docLibs'][$docLibID] = $this->dao->lastInsertID(); + } + self::$convertDocLibCount += count($docLibs); + } + + /** + * convert docs. + * + * @access public + * @return void + */ + public function convertDoc() + { + /* Get all docs */ + $docs = $this->dao->dbh($this->sourceDBH) + ->select("t1.id, t1.project_id AS product, t2.id AS lib, t1.title, t1.description AS content, t1.created_on AS addedDate") + ->from(REDMINE_TABLE_DOCUMENTS)->alias('t1') + ->leftjoin(REDMINE_TABLE_ENUMERATIONS)->alias('t2')->on('t1.category_id = t2.id') + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($docs as $docID => $doc) + { + unset($doc->id); + $doc->type = 'text'; + $doc->project = 0; + $doc->product = $this->map['products'][$doc->product]; + $doc->lib = $this->map['docLibs'][$doc->lib]; + $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec(); + $this->map['docs'][$docID] = $this->dao->lastInsertID(); + } + self::$convertDocCount += count($docs); + } + + /** + * convert news. + * + * @access public + * @return void + */ + public function convertNews() + { + /* Get news from redmine */ + $news = $this->dao->dbh($this->sourceDBH) + ->select("t1.project_id as product, t1.title, t1.summary as digest, t1.description as content, t2.login as addedBy, t1.created_on as addedDate") + ->from(REDMINE_TABLE_NEWS)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id') + ->fetchAll('', $autoCompany = false); + + /* Create a news docLib */ + $newLib->name = 'news'; + $this->dao->dbh($this->dbh)->insert(TABLE_DOCLIB)->data($newLib)->exec(); + $this->map['news'] = $this->dao->lastInsertID(); + self::$convertDocLibCount += 1; + + /* Insert into zentao */ + foreach($news as $new) + { + $new->product = $this->map['products'][$new->product]; + $new->project = 0; + $new->lib = $this->map['news']; + $new->type = 'text'; + + $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($new)->exec(); + } + self::$convertDocCount += count($news); + } + + /** + * convert issue + * + * @param array $aimTypes //aimTypes['issueTypeID'] = aimtype eg. aimTypes[1] = 'bug'; + * @param array $statusTypes //statusTypes['task']['statusTypeID'] = statusType eg. statusTypes['task'][1] = 'wait'; + * //statusTypes['bug']['statusTypeID'] = statusType eg. statusTypes['bug'][1] = 'active'; + * @param array $priTypes //priTypes['task']['priTypeID'] = priType; eg. priTypes['task'][1] = 1; + * @access public + * @return void + */ + public function convertIssue() + { + $aimTypes = $this->issueType->aimTypes; + $statusTypes = $this->issueType->statusTypes; + $priTypes = $this->issueType->priTypes; + + foreach($aimTypes as $issueType => $aimType) + { + if('story' == $aimType) + { + $this->convertStory($issueType, $statusTypes, $priTypes); + } + elseif('task' == $aimType) + { + $this->convertTask($issueType, $statusTypes, $priTypes); + } + else + { + $this->convertBug($issueType, $statusTypes, $priTypes); + } + } + } + + /** + * convert story + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes + * @access public + * @return void + */ + public function convertStory($issueType, $statusTypes, $priTypes) + { + /* Get story list*/ + $stories = $this->dao->dbh($this->sourceDBH) + ->select("t1.id, t1.project_id as product, t1.subject as title, t1.description as spec, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate") + ->from(REDMINE_TABLE_ISSUES)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') + ->where('t1.tracker_id')->eq($issueType) + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($stories as $issueID => $story) + { + $storySpec->title = $story->title; + $storySpec->spec = $story->spec; + unset($story->id); + unset($story->spec); + + /* Insert story into table story */ + $story->product = $this->map['products'][$story->product]; + $story->module = 0; + $story->plan = $this->map['planOfProduct'][$story->product]; + $story->fromBug = 0; + $story->pri = $priTypes['story'][$story->pri]; + $story->status = $statusTypes['story'][$story->status]; + $story->toBug = 0; + $story->duplicateStory = 0; + $this->dao->dbh($this->dbh)->insert(TABLE_STORY)->data($story)->exec(); + $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); + $this->map['issueType'][$issueID] = 'story'; + + /* Insert data into table storySpec */ + $storySpec->story = $this->map['issueID'][$issueID]; + $storySpec->version = 1; + $this->dao->dbh($this->dbh)->insert(TABLE_STORYSPEC)->data($storySpec)->exec(); + } + self::$convertStoryCount += count($stories); + } + + /** + * convert task + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes + * @access public + * @return void + */ + public function convertTask($issueType, $statusTypes, $priTypes) + { + /* Get task list */ + $tasks = $this->dao->dbh($this->sourceDBH) + ->select("t1.id, t1.project_id as product, t1.fixed_version_id as project, t1.subject as name, t1.description as `desc`, t1.due_date as deadline, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.estimated_hours as estimate, t1.updated_on as lastEditedDate") + ->from(REDMINE_TABLE_ISSUES)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') + ->where('t1.tracker_id')->eq($issueType) + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($tasks as $issueID => $task) + { + $task->story = 0; + $task->storyVersion = 0; + $task->type = 'misc'; + $task->pri = $priTypes['task'][$task->pri]; + $task->status = $statusTypes['task'][$task->status]; + if($task->project == 0) + { + $task->project = $this->map['projectOfProduct'][$task->product]; + } + else + { + $task->project = $this->map['project'][$task->project]; + } + unset($task->id); + unset($task->product); + $this->dao->dbh($this->dbh)->insert(TABLE_TASK)->data($task)->exec(); + $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); + $this->map['issueType'][$issueID] = 'task'; + } + self::$convertTaskCount += count($tasks); + } + + /** + * convert bug + * + * @param array $issueType + * @param array $statusTypes + * @param array $priTypes + * @access public + * @return void + */ + public function convertBug($issueType, $statusTypes, $priTypes) + { + /* Get bug list */ + $bugs = $this->dao->dbh($this->sourceDBH) + ->select("t1.id, t1.project_id as product, t1.fixed_version_id project, t1.subject as title, t1.description as steps, t1.status_id as status, t2.login as assignedTo, t1.priority_id as pri, t3.login as openedBy, t1.created_on as openedDate, t1.updated_on as lastEditedDate") + ->from(REDMINE_TABLE_ISSUES)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.assigned_to_id = t2.id') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t3')->on('t1.author_id = t3.id') + ->where('t1.tracker_id')->eq($issueType) + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($bugs as $issueID => $bug) + { + $bug->product = $this->map['products'][$bug->product]; + $bug->module = 0; + $bug->story = 0; + $bug->storyVersion = 1; + $bug->task = 0; + $bug->severity = 3; + $bug->type = 'others'; + $bug->status = $statusTypes['bug'][$bug->status]; + $bug->openedBuild = 'trunk'; + $bug->duplicateBug = 0; + $bug->case = 0; + $bug->caseVersion = 1; + $bug->result = 0; + if($bug->project == 0) + { + $bug->project = $this->map['projectOfProduct'][$bug->product]; + } + else + { + $bug->project = $this->map['project'][$bug->project]; + } + unset($bug->id); + $this->dao->dbh($this->dbh)->insert(TABLE_BUG)->data($bug)->exec(); + $this->map['issueID'][$issueID] = $this->dao->lastInsertID(); + $this->map['issueType'][$issueID] = 'bug'; + } + self::$convertBugCount += count($bugs); + } + + /** + * Convert attachments. + * + * @access public + * @return void + */ + public function convertFile() + { + $this->setPath(); + + /* Get file list */ + $files = $this->dao->dbh($this->sourceDBH) + ->select('t1.id, t1.container_id as objectID, t1.container_type as objectType, t1.filename as title, t1.disk_filename as pathname, t1.filesize as size, t2.login as addedBy, t1.created_on as addedDate, description') + ->from(REDMINE_TABLE_ATTACHMENTS)->alias('t1') + ->leftJoin(REDMINE_TABLE_USERS)->alias('t2')->on('t1.author_id = t2.id') + ->fetchAll('id', $autoCompany = false); + + /* Insert into zentao */ + foreach($files as $fileID => $file) + { + if($file->description != '') + { + $file->title = $file->description; + unset($file->description); + } + else + { + unset($file->description); + } + + /* Transform objectType and objectID */ + if($file->objectType == 'Issue') + { + $file->objectType = $this->map['issueType'][$file->objectID]; + $file->objectID = $this->map['issueID'][$file->objectID]; + } + elseif($file->objectType == 'Document') + { + $file->objectType = 'doc' ; + $file->objectID = $this->map['docs'][$file->objectID]; + } + elseif($file->objectType == 'WikiPage') + { + continue; + } + elseif($file->objectType == 'Version') + { + $doc->project = $this->map['project'][$file->objectID]; + $doc = $this->dao->dbh($this->dbh)->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($doc->project)->fetch(); + $doc->lib = 'project'; + $doc->module = 0; + $doc->title = $file->title; + $doc->type = 'file'; + $doc->addedBy = $file->addedBy; + $doc->addedDate = $file->addedDate; + $this->dao->dbh($this->dbh)->insert(TABLE_DOC)->data($doc)->exec(); + self::$convertDocCount += 1; + + $file->objectType = 'doc'; + $file->objectID = $this->dao->lastInsertID(); + } + + $pathname = pathinfo($file->pathname); + $file->extension = $pathname["extension"]; + unset($file->id); + + /* Insert into database. */ + $this->dao->dbh($this->dbh)->insert(TABLE_FILE)->data($file)->exec(); + + /* Copy file. */ + $soureFile = $this->filePath . $file->pathname; + if(!file_exists($soureFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorFileNotExits, $soureFile); + continue; + } + $targetFile = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; + $targetPath = dirname($targetFile); + if(!is_dir($targetPath)) mkdir($targetPath, 0777, true); + if(!copy($soureFile, $targetFile)) + { + self::$info['files'][] = sprintf($this->lang->convert->errorCopyFailed, $targetFile); + } + } + self::$convertFileCount += count($files); + } + + /** + * Clear the converted records. + * + * @access public + * @return void + */ + public function clear() + { + foreach($this->session->state as $table => $maxID) + { + $this->dao->dbh($this->dbh)->delete()->from($table)->where('id')->gt($maxID)->exec(); + } + } +} diff --git a/module/convert/lang/en.php b/module/convert/lang/en.php index 3e5e6d34d9..9765c29932 100644 --- a/module/convert/lang/en.php +++ b/module/convert/lang/en.php @@ -1,109 +1,109 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->convert->common = 'Import'; -$lang->convert->next = 'Next'; -$lang->convert->pre = 'Back'; -$lang->convert->reload = 'Reload'; -$lang->convert->error = 'Error '; - -$lang->convert->start = 'Begin import'; -$lang->convert->desc = <<Welcome to use this convert wizard which will help you to import other system data to ZenTaoPMS.

      -Importing is dangerous. Be sure to backup your database and other data files and sure nobody is using pms when importing. -EOT; - -$lang->convert->selectSource = 'Select source system and version'; -$lang->convert->source = 'Source system'; -$lang->convert->version = 'Version'; -$lang->convert->mustSelectSource = "Must select a source system"; - -$lang->convert->direction = 'Please select the direction of issue in Redmine'; -$lang->convert->questionTypeOfRedmine = 'Types of issue in Redmine'; -$lang->convert->aimTypeOfZentao = 'Aim type in Zentao'; - -$lang->convert->directionList['bug'] = 'Bug'; -$lang->convert->directionList['task'] = 'Task'; -$lang->convert->directionList['story'] = 'Story'; - -$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); -$lang->convert->sourceList['Redmine'] = array('Redmine_1_1' => '1.1'); - -$lang->convert->setting = 'Setting'; -$lang->convert->checkConfig = 'Check setting'; - -$lang->convert->ok = 'Check passed(√)'; -$lang->convert->fail = 'Check failed(×)'; - -$lang->convert->settingDB = 'Set database'; -$lang->convert->dbHost = 'Database server'; -$lang->convert->dbPort = 'Server port'; -$lang->convert->dbUser = 'Database user'; -$lang->convert->dbPassword = 'Database password'; -$lang->convert->dbName = '%s database'; -$lang->convert->dbCharset = '%s charset'; -$lang->convert->dbPrefix = '%s table prefix'; -$lang->convert->installPath = '%s installed path'; - -$lang->convert->checkDB = 'Database'; -$lang->convert->checkTable = 'Table'; -$lang->convert->checkPath = 'Installed path'; - -$lang->convert->execute = 'Execute import'; -$lang->convert->item = 'Imported items'; -$lang->convert->count = 'Count'; -$lang->convert->info = 'Info'; - -$lang->convert->bugfree->users = 'User'; -$lang->convert->bugfree->projects = 'Project'; -$lang->convert->bugfree->modules = 'Module'; -$lang->convert->bugfree->bugs = 'Bug'; -$lang->convert->bugfree->cases = 'Case'; -$lang->convert->bugfree->results = 'Result'; -$lang->convert->bugfree->actions = 'History'; -$lang->convert->bugfree->files = 'File'; - -$lang->convert->redmine->users = 'Users'; -$lang->convert->redmine->groups = 'Groups'; -$lang->convert->redmine->products = 'Products'; -$lang->convert->redmine->projects = 'Projects'; -$lang->convert->redmine->stories = 'Stories'; -$lang->convert->redmine->tasks = 'Tasks'; -$lang->convert->redmine->bugs = 'Bugs'; -$lang->convert->redmine->productPlans = 'ProductPlans'; -$lang->convert->redmine->teams = 'Teams'; -$lang->convert->redmine->releases = 'Releases'; -$lang->convert->redmine->builds = 'Builds'; -$lang->convert->redmine->docLibs = 'DocLibs'; -$lang->convert->redmine->docs = 'Docs'; -$lang->convert->redmine->files = 'files'; - -$lang->convert->errorConnectDB = 'Connect to database server failed.'; -$lang->convert->errorFileNotExits = 'File %s not exits.'; -$lang->convert->errorUserExists = 'User %s exits already.'; -$lang->convert->errorGroupExists = 'Group %s exits already.'; -$lang->convert->errorBuildExists = 'Build %s exits already.'; -$lang->convert->errorReleaseExists = 'Release %s exits already.'; -$lang->convert->errorCopyFailed = 'file %s copy failed.'; - -$lang->convert->setParam = 'Please set params'; - -$lang->convert->aimType = 'Issue types goto'; -$lang->convert->statusType->bug = 'Status types goto(status of Bug)'; -$lang->convert->statusType->story = 'Status types goto(status of story)'; -$lang->convert->statusType->task = 'Status types goto(status of task)'; -$lang->convert->priType->bug = 'Priority types goto(priority of Bug)'; -$lang->convert->priType->story = 'Priority types goto(priority of story)'; -$lang->convert->priType->task = 'Priority types goto(priority of task)'; - -$lang->convert->issue->redmine = 'Redmine'; -$lang->convert->issue->zentao = 'ZenTao'; -$lang->convert->issue->goto = 'Goto'; + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->convert->common = 'Import'; +$lang->convert->next = 'Next'; +$lang->convert->pre = 'Back'; +$lang->convert->reload = 'Reload'; +$lang->convert->error = 'Error '; + +$lang->convert->start = 'Begin import'; +$lang->convert->desc = <<Welcome to use this convert wizard which will help you to import other system data to ZenTaoPMS.

      +Importing is dangerous. Be sure to backup your database and other data files and sure nobody is using pms when importing. +EOT; + +$lang->convert->selectSource = 'Select source system and version'; +$lang->convert->source = 'Source system'; +$lang->convert->version = 'Version'; +$lang->convert->mustSelectSource = "Must select a source system"; + +$lang->convert->direction = 'Please select the direction of issue in Redmine'; +$lang->convert->questionTypeOfRedmine = 'Types of issue in Redmine'; +$lang->convert->aimTypeOfZentao = 'Aim type in Zentao'; + +$lang->convert->directionList['bug'] = 'Bug'; +$lang->convert->directionList['task'] = 'Task'; +$lang->convert->directionList['story'] = 'Story'; + +$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); +$lang->convert->sourceList['Redmine'] = array('Redmine_1_1' => '1.1'); + +$lang->convert->setting = 'Setting'; +$lang->convert->checkConfig = 'Check setting'; + +$lang->convert->ok = 'Check passed(√)'; +$lang->convert->fail = 'Check failed(×)'; + +$lang->convert->settingDB = 'Set database'; +$lang->convert->dbHost = 'Database server'; +$lang->convert->dbPort = 'Server port'; +$lang->convert->dbUser = 'Database user'; +$lang->convert->dbPassword = 'Database password'; +$lang->convert->dbName = '%s database'; +$lang->convert->dbCharset = '%s charset'; +$lang->convert->dbPrefix = '%s table prefix'; +$lang->convert->installPath = '%s installed path'; + +$lang->convert->checkDB = 'Database'; +$lang->convert->checkTable = 'Table'; +$lang->convert->checkPath = 'Installed path'; + +$lang->convert->execute = 'Execute import'; +$lang->convert->item = 'Imported items'; +$lang->convert->count = 'Count'; +$lang->convert->info = 'Info'; + +$lang->convert->bugfree->users = 'User'; +$lang->convert->bugfree->projects = 'Project'; +$lang->convert->bugfree->modules = 'Module'; +$lang->convert->bugfree->bugs = 'Bug'; +$lang->convert->bugfree->cases = 'Case'; +$lang->convert->bugfree->results = 'Result'; +$lang->convert->bugfree->actions = 'History'; +$lang->convert->bugfree->files = 'File'; + +$lang->convert->redmine->users = 'Users'; +$lang->convert->redmine->groups = 'Groups'; +$lang->convert->redmine->products = 'Products'; +$lang->convert->redmine->projects = 'Projects'; +$lang->convert->redmine->stories = 'Stories'; +$lang->convert->redmine->tasks = 'Tasks'; +$lang->convert->redmine->bugs = 'Bugs'; +$lang->convert->redmine->productPlans = 'ProductPlans'; +$lang->convert->redmine->teams = 'Teams'; +$lang->convert->redmine->releases = 'Releases'; +$lang->convert->redmine->builds = 'Builds'; +$lang->convert->redmine->docLibs = 'DocLibs'; +$lang->convert->redmine->docs = 'Docs'; +$lang->convert->redmine->files = 'files'; + +$lang->convert->errorConnectDB = 'Connect to database server failed.'; +$lang->convert->errorFileNotExits = 'File %s not exits.'; +$lang->convert->errorUserExists = 'User %s exits already.'; +$lang->convert->errorGroupExists = 'Group %s exits already.'; +$lang->convert->errorBuildExists = 'Build %s exits already.'; +$lang->convert->errorReleaseExists = 'Release %s exits already.'; +$lang->convert->errorCopyFailed = 'file %s copy failed.'; + +$lang->convert->setParam = 'Please set params'; + +$lang->convert->aimType = 'Issue types goto'; +$lang->convert->statusType->bug = 'Status types goto(status of Bug)'; +$lang->convert->statusType->story = 'Status types goto(status of story)'; +$lang->convert->statusType->task = 'Status types goto(status of task)'; +$lang->convert->priType->bug = 'Priority types goto(priority of Bug)'; +$lang->convert->priType->story = 'Priority types goto(priority of story)'; +$lang->convert->priType->task = 'Priority types goto(priority of task)'; + +$lang->convert->issue->redmine = 'Redmine'; +$lang->convert->issue->zentao = 'ZenTao'; +$lang->convert->issue->goto = 'Goto'; diff --git a/module/convert/lang/zh-cn.php b/module/convert/lang/zh-cn.php index 8722232709..229020eaf6 100644 --- a/module/convert/lang/zh-cn.php +++ b/module/convert/lang/zh-cn.php @@ -1,109 +1,109 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->convert->common = '从其他系统导入'; -$lang->convert->next = '下一步'; -$lang->convert->pre = '返回'; -$lang->convert->reload = '刷新'; -$lang->convert->error = '错误 '; - -$lang->convert->start = '开始转换'; -$lang->convert->desc = <<欢迎使用系统转换向导,本程序会帮助您将其他系统的数据转换到禅道项目管理系统中。

      -转换存在一定的风险,转换之前,我们强烈建议您备份数据库及相应的数据文件,并保证转换的时候,没有其他人进行操作。 -EOT; - -$lang->convert->selectSource = '选择来源系统及版本'; -$lang->convert->source = '来源系统'; -$lang->convert->version = '版本'; -$lang->convert->mustSelectSource = "必须选择一个来源。"; - -$lang->convert->direction = '请选择项目问题转换方向'; -$lang->convert->questionTypeOfRedmine = 'Redmine中问题类型'; -$lang->convert->aimTypeOfZentao = '转化为Zentao中的类型'; - -$lang->convert->directionList['bug'] = 'Bug'; -$lang->convert->directionList['task'] = '任务'; -$lang->convert->directionList['story'] = '需求'; - -$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); -$lang->convert->sourceList['Redmine'] = array('Redmine_1.1' => '1.1'); - -$lang->convert->setting = '设置'; -$lang->convert->checkConfig = '检查配置'; - -$lang->convert->ok = '检查通过(√)'; -$lang->convert->fail = '检查失败(×)'; - -$lang->convert->settingDB = '设置数据库'; -$lang->convert->dbHost = '数据库服务器'; -$lang->convert->dbPort = '服务器端口'; -$lang->convert->dbUser = '数据库用户名'; -$lang->convert->dbPassword = '数据库密码'; -$lang->convert->dbName = '%s使用的库'; -$lang->convert->dbCharset = '%s数据库编码'; -$lang->convert->dbPrefix = '%s表前缀'; -$lang->convert->installPath = '%s安装的根目录'; - -$lang->convert->checkDB = '数据库'; -$lang->convert->checkTable = '表'; -$lang->convert->checkPath = '安装路径'; - -$lang->convert->execute = '执行转换'; -$lang->convert->item = '转换项'; -$lang->convert->count = '转换数量'; -$lang->convert->info = '转换信息'; - -$lang->convert->bugfree->users = '用户'; -$lang->convert->bugfree->projects = '项目'; -$lang->convert->bugfree->modules = '模块'; -$lang->convert->bugfree->bugs = 'Bug'; -$lang->convert->bugfree->cases = '测试用例'; -$lang->convert->bugfree->results = '测试结果'; -$lang->convert->bugfree->actions = '历史记录'; -$lang->convert->bugfree->files = '附件'; - -$lang->convert->redmine->users = '用户'; -$lang->convert->redmine->groups = '用户分组'; -$lang->convert->redmine->products = '产品'; -$lang->convert->redmine->projects = '项目'; -$lang->convert->redmine->stories = '需求'; -$lang->convert->redmine->tasks = '任务'; -$lang->convert->redmine->bugs = 'Bug'; -$lang->convert->redmine->productPlans = '产品计划'; -$lang->convert->redmine->teams = '团队'; -$lang->convert->redmine->releases = '发布'; -$lang->convert->redmine->builds = 'Build'; -$lang->convert->redmine->docLibs = '文档库'; -$lang->convert->redmine->docs = '文档'; -$lang->convert->redmine->files = '附件'; - -$lang->convert->errorConnectDB = '数据库连接失败 '; -$lang->convert->errorFileNotExits = '文件 %s 不存在'; -$lang->convert->errorUserExists = '用户 %s 已存在'; -$lang->convert->errorGroupExists = '分组 %s 已存在'; -$lang->convert->errorBuildExists = 'Build %s 已存在'; -$lang->convert->errorReleaseExists = '发布 %s 已存在'; -$lang->convert->errorCopyFailed = '文件 %s 拷贝失败'; - -$lang->convert->setParam = '请设置转换参数'; - -$lang->convert->aimType = '问题类型转换'; -$lang->convert->statusType->bug = '状态类型转换(Bug状态)'; -$lang->convert->statusType->story = '状态类型转换(Story状态)'; -$lang->convert->statusType->task = '状态类型转换(Task状态)'; -$lang->convert->priType->bug = '优先级类型转换(Bug状态)'; -$lang->convert->priType->story = '优先级类型转换(Story状态)'; -$lang->convert->priType->task = '优先级类型转换(Task状态)'; - -$lang->convert->issue->redmine = 'Redmine'; -$lang->convert->issue->zentao = '禅道'; -$lang->convert->issue->goto = '转换为'; + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->convert->common = '从其他系统导入'; +$lang->convert->next = '下一步'; +$lang->convert->pre = '返回'; +$lang->convert->reload = '刷新'; +$lang->convert->error = '错误 '; + +$lang->convert->start = '开始转换'; +$lang->convert->desc = <<欢迎使用系统转换向导,本程序会帮助您将其他系统的数据转换到禅道项目管理系统中。

      +转换存在一定的风险,转换之前,我们强烈建议您备份数据库及相应的数据文件,并保证转换的时候,没有其他人进行操作。 +EOT; + +$lang->convert->selectSource = '选择来源系统及版本'; +$lang->convert->source = '来源系统'; +$lang->convert->version = '版本'; +$lang->convert->mustSelectSource = "必须选择一个来源。"; + +$lang->convert->direction = '请选择项目问题转换方向'; +$lang->convert->questionTypeOfRedmine = 'Redmine中问题类型'; +$lang->convert->aimTypeOfZentao = '转化为Zentao中的类型'; + +$lang->convert->directionList['bug'] = 'Bug'; +$lang->convert->directionList['task'] = '任务'; +$lang->convert->directionList['story'] = '需求'; + +$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); +$lang->convert->sourceList['Redmine'] = array('Redmine_1.1' => '1.1'); + +$lang->convert->setting = '设置'; +$lang->convert->checkConfig = '检查配置'; + +$lang->convert->ok = '检查通过(√)'; +$lang->convert->fail = '检查失败(×)'; + +$lang->convert->settingDB = '设置数据库'; +$lang->convert->dbHost = '数据库服务器'; +$lang->convert->dbPort = '服务器端口'; +$lang->convert->dbUser = '数据库用户名'; +$lang->convert->dbPassword = '数据库密码'; +$lang->convert->dbName = '%s使用的库'; +$lang->convert->dbCharset = '%s数据库编码'; +$lang->convert->dbPrefix = '%s表前缀'; +$lang->convert->installPath = '%s安装的根目录'; + +$lang->convert->checkDB = '数据库'; +$lang->convert->checkTable = '表'; +$lang->convert->checkPath = '安装路径'; + +$lang->convert->execute = '执行转换'; +$lang->convert->item = '转换项'; +$lang->convert->count = '转换数量'; +$lang->convert->info = '转换信息'; + +$lang->convert->bugfree->users = '用户'; +$lang->convert->bugfree->projects = '项目'; +$lang->convert->bugfree->modules = '模块'; +$lang->convert->bugfree->bugs = 'Bug'; +$lang->convert->bugfree->cases = '测试用例'; +$lang->convert->bugfree->results = '测试结果'; +$lang->convert->bugfree->actions = '历史记录'; +$lang->convert->bugfree->files = '附件'; + +$lang->convert->redmine->users = '用户'; +$lang->convert->redmine->groups = '用户分组'; +$lang->convert->redmine->products = '产品'; +$lang->convert->redmine->projects = '项目'; +$lang->convert->redmine->stories = '需求'; +$lang->convert->redmine->tasks = '任务'; +$lang->convert->redmine->bugs = 'Bug'; +$lang->convert->redmine->productPlans = '产品计划'; +$lang->convert->redmine->teams = '团队'; +$lang->convert->redmine->releases = '发布'; +$lang->convert->redmine->builds = 'Build'; +$lang->convert->redmine->docLibs = '文档库'; +$lang->convert->redmine->docs = '文档'; +$lang->convert->redmine->files = '附件'; + +$lang->convert->errorConnectDB = '数据库连接失败 '; +$lang->convert->errorFileNotExits = '文件 %s 不存在'; +$lang->convert->errorUserExists = '用户 %s 已存在'; +$lang->convert->errorGroupExists = '分组 %s 已存在'; +$lang->convert->errorBuildExists = 'Build %s 已存在'; +$lang->convert->errorReleaseExists = '发布 %s 已存在'; +$lang->convert->errorCopyFailed = '文件 %s 拷贝失败'; + +$lang->convert->setParam = '请设置转换参数'; + +$lang->convert->aimType = '问题类型转换'; +$lang->convert->statusType->bug = '状态类型转换(Bug状态)'; +$lang->convert->statusType->story = '状态类型转换(Story状态)'; +$lang->convert->statusType->task = '状态类型转换(Task状态)'; +$lang->convert->priType->bug = '优先级类型转换(Bug状态)'; +$lang->convert->priType->story = '优先级类型转换(Story状态)'; +$lang->convert->priType->task = '优先级类型转换(Task状态)'; + +$lang->convert->issue->redmine = 'Redmine'; +$lang->convert->issue->zentao = '禅道'; +$lang->convert->issue->goto = '转换为'; diff --git a/module/convert/lang/zh-tw.php b/module/convert/lang/zh-tw.php index 64b1442210..ddfa845b35 100644 --- a/module/convert/lang/zh-tw.php +++ b/module/convert/lang/zh-tw.php @@ -1,109 +1,109 @@ - - * @package convert - * @version $Id: zh-tw.php 2001 2011-07-03 05:50:54Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->convert->common = '從其他系統導入'; -$lang->convert->next = '下一步'; -$lang->convert->pre = '返回'; -$lang->convert->reload = '刷新'; -$lang->convert->error = '錯誤 '; - -$lang->convert->start = '開始轉換'; -$lang->convert->desc = <<歡迎使用系統轉換嚮導,本程序會幫助您將其他系統的數據轉換到禪道項目管理系統中。

      -轉換存在一定的風險,轉換之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證轉換的時候,沒有其他人進行操作。 -EOT; - -$lang->convert->selectSource = '選擇來源系統及版本'; -$lang->convert->source = '來源系統'; -$lang->convert->version = '版本'; -$lang->convert->mustSelectSource = "必須選擇一個來源。"; - -$lang->convert->direction = '請選擇項目問題轉換方向'; -$lang->convert->questionTypeOfRedmine = 'Redmine中問題類型'; -$lang->convert->aimTypeOfZentao = '轉化為Zentao中的類型'; - -$lang->convert->directionList['bug'] = 'Bug'; -$lang->convert->directionList['task'] = '任務'; -$lang->convert->directionList['story'] = '需求'; - -$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); -$lang->convert->sourceList['Redmine'] = array('Redmine_1.1' => '1.1'); - -$lang->convert->setting = '設置'; -$lang->convert->checkConfig = '檢查配置'; - -$lang->convert->ok = '檢查通過(√)'; -$lang->convert->fail = '檢查失敗(×)'; - -$lang->convert->settingDB = '設置資料庫'; -$lang->convert->dbHost = '資料庫伺服器'; -$lang->convert->dbPort = '伺服器連接埠'; -$lang->convert->dbUser = '資料庫用戶名'; -$lang->convert->dbPassword = '資料庫密碼'; -$lang->convert->dbName = '%s使用的庫'; -$lang->convert->dbCharset = '%s資料庫編碼'; -$lang->convert->dbPrefix = '%s表首碼'; -$lang->convert->installPath = '%s安裝的根目錄'; - -$lang->convert->checkDB = '資料庫'; -$lang->convert->checkTable = '表'; -$lang->convert->checkPath = '安裝路徑'; - -$lang->convert->execute = '執行轉換'; -$lang->convert->item = '轉換項'; -$lang->convert->count = '轉換數量'; -$lang->convert->info = '轉換信息'; - -$lang->convert->bugfree->users = '用戶'; -$lang->convert->bugfree->projects = '項目'; -$lang->convert->bugfree->modules = '模組'; -$lang->convert->bugfree->bugs = 'Bug'; -$lang->convert->bugfree->cases = '測試用例'; -$lang->convert->bugfree->results = '測試結果'; -$lang->convert->bugfree->actions = '歷史記錄'; -$lang->convert->bugfree->files = '附件'; - -$lang->convert->redmine->users = '用戶'; -$lang->convert->redmine->groups = '用戶分組'; -$lang->convert->redmine->products = '產品'; -$lang->convert->redmine->projects = '項目'; -$lang->convert->redmine->stories = '需求'; -$lang->convert->redmine->tasks = '任務'; -$lang->convert->redmine->bugs = 'Bug'; -$lang->convert->redmine->productPlans = '產品計劃'; -$lang->convert->redmine->teams = '團隊'; -$lang->convert->redmine->releases = '發佈'; -$lang->convert->redmine->builds = 'Build'; -$lang->convert->redmine->docLibs = '文檔庫'; -$lang->convert->redmine->docs = '文檔'; -$lang->convert->redmine->files = '附件'; - -$lang->convert->errorConnectDB = '資料庫連接失敗 '; -$lang->convert->errorFileNotExits = '檔案 %s 不存在'; -$lang->convert->errorUserExists = '用戶 %s 已存在'; -$lang->convert->errorGroupExists = '分組 %s 已存在'; -$lang->convert->errorBuildExists = 'Build %s 已存在'; -$lang->convert->errorReleaseExists = '發佈 %s 已存在'; -$lang->convert->errorCopyFailed = '檔案 %s 拷貝失敗'; - -$lang->convert->setParam = '請設置轉換參數'; - -$lang->convert->aimType = '問題類型轉換'; -$lang->convert->statusType->bug = '狀態類型轉換(Bug狀態)'; -$lang->convert->statusType->story = '狀態類型轉換(Story狀態)'; -$lang->convert->statusType->task = '狀態類型轉換(Task狀態)'; -$lang->convert->priType->bug = '優先順序類型轉換(Bug狀態)'; -$lang->convert->priType->story = '優先順序類型轉換(Story狀態)'; -$lang->convert->priType->task = '優先順序類型轉換(Task狀態)'; - -$lang->convert->issue->redmine = 'Redmine'; -$lang->convert->issue->zentao = '禪道'; -$lang->convert->issue->goto = '轉換為'; + + * @package convert + * @version $Id: zh-tw.php 2001 2011-07-03 05:50:54Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->convert->common = '從其他系統導入'; +$lang->convert->next = '下一步'; +$lang->convert->pre = '返回'; +$lang->convert->reload = '刷新'; +$lang->convert->error = '錯誤 '; + +$lang->convert->start = '開始轉換'; +$lang->convert->desc = <<歡迎使用系統轉換嚮導,本程序會幫助您將其他系統的數據轉換到禪道項目管理系統中。

      +轉換存在一定的風險,轉換之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證轉換的時候,沒有其他人進行操作。 +EOT; + +$lang->convert->selectSource = '選擇來源系統及版本'; +$lang->convert->source = '來源系統'; +$lang->convert->version = '版本'; +$lang->convert->mustSelectSource = "必須選擇一個來源。"; + +$lang->convert->direction = '請選擇項目問題轉換方向'; +$lang->convert->questionTypeOfRedmine = 'Redmine中問題類型'; +$lang->convert->aimTypeOfZentao = '轉化為Zentao中的類型'; + +$lang->convert->directionList['bug'] = 'Bug'; +$lang->convert->directionList['task'] = '任務'; +$lang->convert->directionList['story'] = '需求'; + +$lang->convert->sourceList['BugFree'] = array('bugfree_1' => '1.x', 'bugfree_2' => '2.x'); +$lang->convert->sourceList['Redmine'] = array('Redmine_1.1' => '1.1'); + +$lang->convert->setting = '設置'; +$lang->convert->checkConfig = '檢查配置'; + +$lang->convert->ok = '檢查通過(√)'; +$lang->convert->fail = '檢查失敗(×)'; + +$lang->convert->settingDB = '設置資料庫'; +$lang->convert->dbHost = '資料庫伺服器'; +$lang->convert->dbPort = '伺服器連接埠'; +$lang->convert->dbUser = '資料庫用戶名'; +$lang->convert->dbPassword = '資料庫密碼'; +$lang->convert->dbName = '%s使用的庫'; +$lang->convert->dbCharset = '%s資料庫編碼'; +$lang->convert->dbPrefix = '%s表首碼'; +$lang->convert->installPath = '%s安裝的根目錄'; + +$lang->convert->checkDB = '資料庫'; +$lang->convert->checkTable = '表'; +$lang->convert->checkPath = '安裝路徑'; + +$lang->convert->execute = '執行轉換'; +$lang->convert->item = '轉換項'; +$lang->convert->count = '轉換數量'; +$lang->convert->info = '轉換信息'; + +$lang->convert->bugfree->users = '用戶'; +$lang->convert->bugfree->projects = '項目'; +$lang->convert->bugfree->modules = '模組'; +$lang->convert->bugfree->bugs = 'Bug'; +$lang->convert->bugfree->cases = '測試用例'; +$lang->convert->bugfree->results = '測試結果'; +$lang->convert->bugfree->actions = '歷史記錄'; +$lang->convert->bugfree->files = '附件'; + +$lang->convert->redmine->users = '用戶'; +$lang->convert->redmine->groups = '用戶分組'; +$lang->convert->redmine->products = '產品'; +$lang->convert->redmine->projects = '項目'; +$lang->convert->redmine->stories = '需求'; +$lang->convert->redmine->tasks = '任務'; +$lang->convert->redmine->bugs = 'Bug'; +$lang->convert->redmine->productPlans = '產品計劃'; +$lang->convert->redmine->teams = '團隊'; +$lang->convert->redmine->releases = '發佈'; +$lang->convert->redmine->builds = 'Build'; +$lang->convert->redmine->docLibs = '文檔庫'; +$lang->convert->redmine->docs = '文檔'; +$lang->convert->redmine->files = '附件'; + +$lang->convert->errorConnectDB = '資料庫連接失敗 '; +$lang->convert->errorFileNotExits = '檔案 %s 不存在'; +$lang->convert->errorUserExists = '用戶 %s 已存在'; +$lang->convert->errorGroupExists = '分組 %s 已存在'; +$lang->convert->errorBuildExists = 'Build %s 已存在'; +$lang->convert->errorReleaseExists = '發佈 %s 已存在'; +$lang->convert->errorCopyFailed = '檔案 %s 拷貝失敗'; + +$lang->convert->setParam = '請設置轉換參數'; + +$lang->convert->aimType = '問題類型轉換'; +$lang->convert->statusType->bug = '狀態類型轉換(Bug狀態)'; +$lang->convert->statusType->story = '狀態類型轉換(Story狀態)'; +$lang->convert->statusType->task = '狀態類型轉換(Task狀態)'; +$lang->convert->priType->bug = '優先順序類型轉換(Bug狀態)'; +$lang->convert->priType->story = '優先順序類型轉換(Story狀態)'; +$lang->convert->priType->task = '優先順序類型轉換(Task狀態)'; + +$lang->convert->issue->redmine = 'Redmine'; +$lang->convert->issue->zentao = '禪道'; +$lang->convert->issue->goto = '轉換為'; diff --git a/module/convert/model.php b/module/convert/model.php index 088f7bc7dd..3965851ef7 100644 --- a/module/convert/model.php +++ b/module/convert/model.php @@ -1,94 +1,94 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -?> -post->dbHost}; port={$this->post->dbPort};dbname={$this->post->dbName}"; - try - { - $dbh = new PDO($dsn, $this->post->dbUser, $this->post->dbPassword); - $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); - $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $dbh->exec("SET NAMES {$this->post->dbCharset}"); - $this->sourceDBH = $dbh; - return $dbh; - } - catch (PDOException $exception) - { - return $exception->getMessage(); - } - } - - /** - * Check database exits or not. - * - * @access public - * @return bool - */ - public function dbExists() - { - $sql = "SHOW DATABASES like '{$this->post->db->name}'"; - return $this->dbh->query($sql)->fetch(); - } - - /** - * Check table exits or not. - * - * @access public - * @return bool - */ - public function tableExists($table) - { - $sql = "SHOW tables like '$table'"; - return $this->dbh->query($sql)->fetch(); - } - - /** - * Save the max id of every table. Thus when we convert again, when can delete id larger then the saved max id. - * - * @access public - * @return void - */ - public function saveState() - { - /* Get user defined tables. */ - $constants = get_defined_constants(true); - $userConstants = $constants['user']; - - /* These tables needn't save. */ - unset($userConstants['TABLE_BURN']); - unset($userConstants['TABLE_GROUPPRIV']); - unset($userConstants['TABLE_PROJECTPRODUCT']); - unset($userConstants['TABLE_PROJECTSTORY']); - unset($userConstants['TABLE_STORYSPEC']); - unset($userConstants['TABLE_TEAM']); - unset($userConstants['TABLE_USERGROUP']); - - /* Get max id of every table. */ - foreach($userConstants as $key => $value) - { - if(strpos($key, 'TABLE') === false) continue; - if($key == 'TABLE_COMPANY') continue; - $state[$value] = (int)$this->dao->select('MAX(id) AS id')->from($value)->fetch('id'); - } - $this->session->set('state', $state); - } -} + + * @package convert + * @version $Id$ + * @link http://www.zentao.net + */ +?> +post->dbHost}; port={$this->post->dbPort};dbname={$this->post->dbName}"; + try + { + $dbh = new PDO($dsn, $this->post->dbUser, $this->post->dbPassword); + $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $dbh->exec("SET NAMES {$this->post->dbCharset}"); + $this->sourceDBH = $dbh; + return $dbh; + } + catch (PDOException $exception) + { + return $exception->getMessage(); + } + } + + /** + * Check database exits or not. + * + * @access public + * @return bool + */ + public function dbExists() + { + $sql = "SHOW DATABASES like '{$this->post->db->name}'"; + return $this->dbh->query($sql)->fetch(); + } + + /** + * Check table exits or not. + * + * @access public + * @return bool + */ + public function tableExists($table) + { + $sql = "SHOW tables like '$table'"; + return $this->dbh->query($sql)->fetch(); + } + + /** + * Save the max id of every table. Thus when we convert again, when can delete id larger then the saved max id. + * + * @access public + * @return void + */ + public function saveState() + { + /* Get user defined tables. */ + $constants = get_defined_constants(true); + $userConstants = $constants['user']; + + /* These tables needn't save. */ + unset($userConstants['TABLE_BURN']); + unset($userConstants['TABLE_GROUPPRIV']); + unset($userConstants['TABLE_PROJECTPRODUCT']); + unset($userConstants['TABLE_PROJECTSTORY']); + unset($userConstants['TABLE_STORYSPEC']); + unset($userConstants['TABLE_TEAM']); + unset($userConstants['TABLE_USERGROUP']); + + /* Get max id of every table. */ + foreach($userConstants as $key => $value) + { + if(strpos($key, 'TABLE') === false) continue; + if($key == 'TABLE_COMPANY') continue; + $state[$value] = (int)$this->dao->select('MAX(id) AS id')->from($value)->fetch('id'); + } + $this->session->set('state', $state); + } +} diff --git a/module/convert/view/checkconfig.html.php b/module/convert/view/checkconfig.html.php index 4133386e8c..c6585684bb 100644 --- a/module/convert/view/checkconfig.html.php +++ b/module/convert/view/checkconfig.html.php @@ -1,29 +1,29 @@ - - * @package convert - * @version $Id$ - */ -?> - -
      '> - - - -
      convert->checkConfig . $lang->colon . strtoupper($source);?>
      -post->dbHost); -echo html::hidden('dbPort', $this->post->dbPort); -echo html::hidden('dbUser', $this->post->dbUser); -echo html::hidden('dbPassword', $this->post->dbPassword); -echo html::hidden('dbName', $this->post->dbName); -echo html::hidden('dbCharset', $this->post->dbCharset); -echo html::hidden('dbPrefix', $this->post->dbPrefix); -echo html::hidden('installPath',$this->post->installPath); -?> -
      - + + * @package convert + * @version $Id$ + */ +?> + +
      '> + + + +
      convert->checkConfig . $lang->colon . strtoupper($source);?>
      +post->dbHost); +echo html::hidden('dbPort', $this->post->dbPort); +echo html::hidden('dbUser', $this->post->dbUser); +echo html::hidden('dbPassword', $this->post->dbPassword); +echo html::hidden('dbName', $this->post->dbName); +echo html::hidden('dbCharset', $this->post->dbCharset); +echo html::hidden('dbPrefix', $this->post->dbPrefix); +echo html::hidden('installPath',$this->post->installPath); +?> +
      + diff --git a/module/convert/view/execute.html.php b/module/convert/view/execute.html.php index ca81c5904b..08c19d0419 100644 --- a/module/convert/view/execute.html.php +++ b/module/convert/view/execute.html.php @@ -1,18 +1,18 @@ - - * @package convert - * @version $Id$ - */ -?> - - - - -
      convert->execute . $lang->colon . strtoupper($source);?>
      - - + + * @package convert + * @version $Id$ + */ +?> + + + + +
      convert->execute . $lang->colon . strtoupper($source);?>
      + + diff --git a/module/convert/view/index.html.php b/module/convert/view/index.html.php index 1ba5646a73..00c8ed0f58 100644 --- a/module/convert/view/index.html.php +++ b/module/convert/view/index.html.php @@ -1,18 +1,18 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - - - -
      convert->common;?>
      convert->desc);?>

      createLink('convert', 'selectsource'), $lang->convert->start);?>

      - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + + + +
      convert->common;?>
      convert->desc);?>

      createLink('convert', 'selectsource'), $lang->convert->start);?>

      + diff --git a/module/convert/view/selectsource.html.php b/module/convert/view/selectsource.html.php index 35d99a9c68..7364692b33 100644 --- a/module/convert/view/selectsource.html.php +++ b/module/convert/view/selectsource.html.php @@ -1,31 +1,31 @@ - - * @package convert - * @version $Id$ - */ -?> - -
      '> - - - - - - - convert->sourceList as $name => $versions):?> - - - - - - - - -
      convert->selectSource;?>
      convert->source;?>convert->version;?>
      -
      - + + * @package convert + * @version $Id$ + */ +?> + +
      '> + + + + + + + convert->sourceList as $name => $versions):?> + + + + + + + + +
      convert->selectSource;?>
      convert->source;?>convert->version;?>
      +
      + diff --git a/module/convert/view/setconfig.html.php b/module/convert/view/setconfig.html.php index bd4f7fe82e..5fc9ea0402 100644 --- a/module/convert/view/setconfig.html.php +++ b/module/convert/view/setconfig.html.php @@ -1,23 +1,23 @@ - - * @package convert - * @version $Id$ - */ -?> - -
      '> - - - - - - -
      convert->setting . $lang->colon . strtoupper($source);?>
      - -
      - + + * @package convert + * @version $Id$ + */ +?> + +
      '> + + + + + + +
      convert->setting . $lang->colon . strtoupper($source);?>
      + +
      + diff --git a/module/dept/control.php b/module/dept/control.php index 17124a3629..68fca6cd2d 100644 --- a/module/dept/control.php +++ b/module/dept/control.php @@ -1,101 +1,101 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -class dept extends control -{ - const NEW_CHILD_COUNT = 5; - - /** - * Construct function, set menu. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('company')->setMenu(); - } - - /** - * Browse a department. - * - * @param int $deptID - * @access public - * @return void - */ - public function browse($deptID = 0) - { - $header['title'] = $this->lang->dept->manage . $this->lang->colon . $this->app->company->name; - $position[] = $this->lang->dept->manage; - - $parentDepts = $this->dept->getParents($deptID); - $this->view->header = $header; - $this->view->position = $position; - $this->view->deptID = $deptID; - $this->view->depts = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptmodel', 'createManageLink')); - $this->view->parentDepts = $parentDepts; - $this->view->sons = $this->dept->getSons($deptID); - $this->display(); - } - - /** - * Update the departments order. - * - * @access public - * @return void - */ - public function updateOrder() - { - if(!empty($_POST)) - { - $this->dept->updateOrder($_POST['orders']); - die(js::reload('parent')); - } - } - - /** - * Manage childs. - * - * @access public - * @return void - */ - public function manageChild() - { - if(!empty($_POST)) - { - $this->dept->manageChild($_POST['parentDeptID'], $_POST['depts']); - die(js::reload('parent')); - } - } - - /** - * Delete a department. - * - * @param int $deptID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($deptID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->dept->confirmDelete, $this->createLink('dept', 'delete', "deptID=$deptID&confirm=yes")); - exit; - } - else - { - $this->dept->delete($deptID); - die(js::reload('parent')); - } - } -} + + * @package dept + * @version $Id$ + * @link http://www.zentao.net + */ +class dept extends control +{ + const NEW_CHILD_COUNT = 5; + + /** + * Construct function, set menu. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('company')->setMenu(); + } + + /** + * Browse a department. + * + * @param int $deptID + * @access public + * @return void + */ + public function browse($deptID = 0) + { + $header['title'] = $this->lang->dept->manage . $this->lang->colon . $this->app->company->name; + $position[] = $this->lang->dept->manage; + + $parentDepts = $this->dept->getParents($deptID); + $this->view->header = $header; + $this->view->position = $position; + $this->view->deptID = $deptID; + $this->view->depts = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptmodel', 'createManageLink')); + $this->view->parentDepts = $parentDepts; + $this->view->sons = $this->dept->getSons($deptID); + $this->display(); + } + + /** + * Update the departments order. + * + * @access public + * @return void + */ + public function updateOrder() + { + if(!empty($_POST)) + { + $this->dept->updateOrder($_POST['orders']); + die(js::reload('parent')); + } + } + + /** + * Manage childs. + * + * @access public + * @return void + */ + public function manageChild() + { + if(!empty($_POST)) + { + $this->dept->manageChild($_POST['parentDeptID'], $_POST['depts']); + die(js::reload('parent')); + } + } + + /** + * Delete a department. + * + * @param int $deptID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($deptID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->dept->confirmDelete, $this->createLink('dept', 'delete', "deptID=$deptID&confirm=yes")); + exit; + } + else + { + $this->dept->delete($deptID); + die(js::reload('parent')); + } + } +} diff --git a/module/dept/lang/en.php b/module/dept/lang/en.php index 25d41ab6e3..8254579652 100644 --- a/module/dept/lang/en.php +++ b/module/dept/lang/en.php @@ -1,23 +1,23 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->dept->common = 'Department'; -$lang->dept->add = "Add"; -$lang->dept->addChild = "Add child department"; -$lang->dept->manageChild = "Child deprtment"; -$lang->dept->delete = "Delete"; -$lang->dept->browse = "Manage"; -$lang->dept->manage = "Manage"; -$lang->dept->updateOrder = "Update order"; -$lang->dept->users = "Users"; - -$lang->dept->saveButton = " Save (S) "; -$lang->dept->confirmDelete = "Are you sure to delete this department?"; + + * @package dept + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->dept->common = 'Department'; +$lang->dept->add = "Add"; +$lang->dept->addChild = "Add child department"; +$lang->dept->manageChild = "Child deprtment"; +$lang->dept->delete = "Delete"; +$lang->dept->browse = "Manage"; +$lang->dept->manage = "Manage"; +$lang->dept->updateOrder = "Update order"; +$lang->dept->users = "Users"; + +$lang->dept->saveButton = " Save (S) "; +$lang->dept->confirmDelete = "Are you sure to delete this department?"; diff --git a/module/dept/lang/zh-cn.php b/module/dept/lang/zh-cn.php index 66140f775a..3c0adf855c 100644 --- a/module/dept/lang/zh-cn.php +++ b/module/dept/lang/zh-cn.php @@ -1,23 +1,23 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->dept->common = '部门结构'; -$lang->dept->add = "添加"; -$lang->dept->addChild = "添加下级部门"; -$lang->dept->manageChild = "下级部门"; -$lang->dept->delete = "删除部门"; -$lang->dept->browse = "部门维护"; -$lang->dept->manage = "维护部门结构"; -$lang->dept->updateOrder = "更新排序"; -$lang->dept->users = "成员列表"; - -$lang->dept->saveButton = " 保存 (S) "; -$lang->dept->confirmDelete = " 您确定删除该部门吗?"; + + * @package dept + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->dept->common = '部门结构'; +$lang->dept->add = "添加"; +$lang->dept->addChild = "添加下级部门"; +$lang->dept->manageChild = "下级部门"; +$lang->dept->delete = "删除部门"; +$lang->dept->browse = "部门维护"; +$lang->dept->manage = "维护部门结构"; +$lang->dept->updateOrder = "更新排序"; +$lang->dept->users = "成员列表"; + +$lang->dept->saveButton = " 保存 (S) "; +$lang->dept->confirmDelete = " 您确定删除该部门吗?"; diff --git a/module/dept/lang/zh-tw.php b/module/dept/lang/zh-tw.php index f79da30ad7..b67d3d42c9 100644 --- a/module/dept/lang/zh-tw.php +++ b/module/dept/lang/zh-tw.php @@ -1,23 +1,23 @@ - - * @package dept - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->dept->common = '部門結構'; -$lang->dept->add = "添加"; -$lang->dept->addChild = "添加下級部門"; -$lang->dept->manageChild = "下級部門"; -$lang->dept->delete = "刪除部門"; -$lang->dept->browse = "部門維護"; -$lang->dept->manage = "維護部門結構"; -$lang->dept->updateOrder = "更新排序"; -$lang->dept->users = "成員列表"; - -$lang->dept->saveButton = " 保存 (S) "; -$lang->dept->confirmDelete = " 您確定刪除該部門嗎?"; + + * @package dept + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->dept->common = '部門結構'; +$lang->dept->add = "添加"; +$lang->dept->addChild = "添加下級部門"; +$lang->dept->manageChild = "下級部門"; +$lang->dept->delete = "刪除部門"; +$lang->dept->browse = "部門維護"; +$lang->dept->manage = "維護部門結構"; +$lang->dept->updateOrder = "更新排序"; +$lang->dept->users = "成員列表"; + +$lang->dept->saveButton = " 保存 (S) "; +$lang->dept->confirmDelete = " 您確定刪除該部門嗎?"; diff --git a/module/dept/model.php b/module/dept/model.php index 49ccf54424..21b1b88e4a 100644 --- a/module/dept/model.php +++ b/module/dept/model.php @@ -1,302 +1,302 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findById($deptID)->from(TABLE_DEPT)->fetch(); - } - - /** - * Build the query. - * - * @param int $rootDeptID - * @access private - * @return string - */ - private function buildMenuQuery($rootDeptID) - { - $rootDept = $this->getByID($rootDeptID); - if(!$rootDept) $rootDept->path = ''; - return $this->dao->select('*')->from(TABLE_DEPT) - ->beginIF($rootDeptID > 0)->where('path')->like($rootDept->path . '%')->fi() - ->orderBy('grade desc, `order`') - ->get(); - } - - /** - * Get option menu of departments. - * - * @param int $rootDeptID - * @access public - * @return array - */ - public function getOptionMenu($rootDeptID = 0) - { - $deptMenu = array(); - $stmt = $this->dbh->query($this->buildMenuQuery($rootDeptID)); - $depts = array(); - while($dept = $stmt->fetch()) $depts[$dept->id] = $dept; - - foreach($depts as $dept) - { - $parentDepts = explode(',', $dept->path); - $deptName = '/'; - foreach($parentDepts as $parentDeptID) - { - if(empty($parentDeptID)) continue; - $deptName .= $depts[$parentDeptID]->name . '/'; - } - $deptName = rtrim($deptName, '/'); - $deptName .= "|$dept->id\n"; - - if(isset($deptMenu[$dept->id]) and !empty($deptMenu[$dept->id])) - { - if(isset($deptMenu[$dept->parent])) - { - $deptMenu[$dept->parent] .= $deptName; - } - else - { - $deptMenu[$dept->parent] = $deptName;; - } - $deptMenu[$dept->parent] .= $deptMenu[$dept->id]; - } - else - { - if(isset($deptMenu[$dept->parent]) and !empty($deptMenu[$dept->parent])) - { - $deptMenu[$dept->parent] .= $deptName; - } - else - { - $deptMenu[$dept->parent] = $deptName; - } - } - } - - $topMenu = @array_pop($deptMenu); - $topMenu = explode("\n", trim($topMenu)); - $lastMenu[] = '/'; - foreach($topMenu as $menu) - { - if(!strpos($menu, '|')) continue; - list($label, $deptID) = explode('|', $menu); - $lastMenu[$deptID] = $label; - } - return $lastMenu; - } - - /** - * Get the treemenu of departments. - * - * @param int $rootDeptID - * @param string $userFunc - * @access public - * @return string - */ - public function getTreeMenu($rootDeptID = 0, $userFunc) - { - $deptMenu = array(); - $stmt = $this->dbh->query($this->buildMenuQuery($rootDeptID)); - while($dept = $stmt->fetch()) - { - $linkHtml = call_user_func($userFunc, $dept); - - if(isset($deptMenu[$dept->id]) and !empty($deptMenu[$dept->id])) - { - if(!isset($deptMenu[$dept->parent])) $deptMenu[$dept->parent] = ''; - $deptMenu[$dept->parent] .= "
    • $linkHtml"; - $deptMenu[$dept->parent] .= "
        ".$deptMenu[$dept->id]."
      \n"; - } - else - { - if(isset($deptMenu[$dept->parent]) and !empty($deptMenu[$dept->parent])) - { - $deptMenu[$dept->parent] .= "
    • $linkHtml\n"; - } - else - { - $deptMenu[$dept->parent] = "
    • $linkHtml\n"; - } - } - $deptMenu[$dept->parent] .= "
    • \n"; - } - - $lastMenu = "
        " . @array_pop($deptMenu) . "
      \n"; - return $lastMenu; - } - - /** - * Create the manage link. - * - * @param int $dept - * @access public - * @return string - */ - public function createManageLink($dept) - { - $linkHtml = $dept->name; - $linkHtml .= ' ' . html::a(helper::createLink('dept', 'browse', "deptid={$dept->id}"), $this->lang->dept->manageChild); - $linkHtml .= ' ' . html::a(helper::createLink('dept', 'delete', "deptid={$dept->id}"), $this->lang->dept->delete, 'hiddenwin'); - $linkHtml .= ' ' . html::input("orders[$dept->id]", $dept->order, 'style="width:30px;text-align:center"'); - return $linkHtml; - } - - /** - * Create the member link. - * - * @param int $dept - * @access public - * @return string - */ - public function createMemberLink($dept) - { - $linkHtml = html::a(helper::createLink('company', 'browse', "dept={$dept->id}"), $dept->name, '_self', "id='dept{$dept->id}'"); - return $linkHtml; - } - - /** - * Get sons of a department. - * - * @param int $deptID - * @access public - * @return array - */ - public function getSons($deptID) - { - return $this->dao->select('*')->from(TABLE_DEPT)->where('parent')->eq($deptID)->orderBy('`order`')->fetchAll(); - } - - /** - * Get all childs. - * - * @param int $deptID - * @access public - * @return array - */ - public function getAllChildId($deptID) - { - if($deptID == 0) return array(); - $dept = $this->getById($deptID); - $childs = $this->dao->select('id')->from(TABLE_DEPT)->where('path')->like($dept->path . '%')->fetchPairs(); - return array_keys($childs); - } - - /** - * Get parents. - * - * @param int $deptID - * @access public - * @return array - */ - public function getParents($deptID) - { - if($deptID == 0) return array(); - $path = $this->dao->select('path')->from(TABLE_DEPT)->where('id')->eq($deptID)->fetch('path'); - $path = substr($path, 1, -1); - if(empty($path)) return array(); - return $this->dao->select('*')->from(TABLE_DEPT)->where('id')->in($path)->orderBy('grade')->fetchAll(); - } - - /** - * Update order. - * - * @param int $orders - * @access public - * @return void - */ - public function updateOrder($orders) - { - foreach($orders as $deptID => $order) $this->dao->update(TABLE_DEPT)->set('`order`')->eq($order)->where('id')->eq($deptID)->exec(); - } - - /** - * Manage childs. - * - * @param int $parentDeptID - * @param string $childs - * @access public - * @return void - */ - public function manageChild($parentDeptID, $childs) - { - $parentDept = $this->getByID($parentDeptID); - if($parentDept) - { - $grade = $parentDept->grade + 1; - $parentPath = $parentDept->path; - } - else - { - $grade = 1; - $parentPath = ','; - } - - foreach($childs as $deptID => $deptName) - { - if(empty($deptName)) continue; - if(is_numeric($deptID)) - { - $dept->name = strip_tags($deptName); - $dept->parent = $parentDeptID; - $dept->grade = $grade; - $this->dao->insert(TABLE_DEPT)->data($dept)->exec(); - $deptID = $this->dao->lastInsertID(); - $childPath = $parentPath . "$deptID,"; - $this->dao->update(TABLE_DEPT)->set('path')->eq($childPath)->where('id')->eq($deptID)->exec(); - } - else - { - $deptID = str_replace('id', '', $deptID); - $this->dao->update(TABLE_DEPT)->set('name')->eq(strip_tags($deptName))->where('id')->eq($deptID)->exec(); - } - } - } - - /** - * Get users of a deparment. - * - * @param int $deptID - * @access public - * @return array - */ - public function getUsers($deptID) - { - return $this->dao->select('*')->from(TABLE_USER) - ->where('deleted')->eq(0) - ->beginIF($deptID)->andWhere('dept')->in($deptID)->fi() - ->orderBy('id') - ->fetchAll(); - } - - /** - * Delete a department. - * - * @param int $deptID - * @access public - * @return void - */ - public function delete($deptID) - { - $this->dao->delete()->from(TABLE_DEPT)->where('id')->eq($deptID)->exec(); - } -} + + * @package dept + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->findById($deptID)->from(TABLE_DEPT)->fetch(); + } + + /** + * Build the query. + * + * @param int $rootDeptID + * @access private + * @return string + */ + private function buildMenuQuery($rootDeptID) + { + $rootDept = $this->getByID($rootDeptID); + if(!$rootDept) $rootDept->path = ''; + return $this->dao->select('*')->from(TABLE_DEPT) + ->beginIF($rootDeptID > 0)->where('path')->like($rootDept->path . '%')->fi() + ->orderBy('grade desc, `order`') + ->get(); + } + + /** + * Get option menu of departments. + * + * @param int $rootDeptID + * @access public + * @return array + */ + public function getOptionMenu($rootDeptID = 0) + { + $deptMenu = array(); + $stmt = $this->dbh->query($this->buildMenuQuery($rootDeptID)); + $depts = array(); + while($dept = $stmt->fetch()) $depts[$dept->id] = $dept; + + foreach($depts as $dept) + { + $parentDepts = explode(',', $dept->path); + $deptName = '/'; + foreach($parentDepts as $parentDeptID) + { + if(empty($parentDeptID)) continue; + $deptName .= $depts[$parentDeptID]->name . '/'; + } + $deptName = rtrim($deptName, '/'); + $deptName .= "|$dept->id\n"; + + if(isset($deptMenu[$dept->id]) and !empty($deptMenu[$dept->id])) + { + if(isset($deptMenu[$dept->parent])) + { + $deptMenu[$dept->parent] .= $deptName; + } + else + { + $deptMenu[$dept->parent] = $deptName;; + } + $deptMenu[$dept->parent] .= $deptMenu[$dept->id]; + } + else + { + if(isset($deptMenu[$dept->parent]) and !empty($deptMenu[$dept->parent])) + { + $deptMenu[$dept->parent] .= $deptName; + } + else + { + $deptMenu[$dept->parent] = $deptName; + } + } + } + + $topMenu = @array_pop($deptMenu); + $topMenu = explode("\n", trim($topMenu)); + $lastMenu[] = '/'; + foreach($topMenu as $menu) + { + if(!strpos($menu, '|')) continue; + list($label, $deptID) = explode('|', $menu); + $lastMenu[$deptID] = $label; + } + return $lastMenu; + } + + /** + * Get the treemenu of departments. + * + * @param int $rootDeptID + * @param string $userFunc + * @access public + * @return string + */ + public function getTreeMenu($rootDeptID = 0, $userFunc) + { + $deptMenu = array(); + $stmt = $this->dbh->query($this->buildMenuQuery($rootDeptID)); + while($dept = $stmt->fetch()) + { + $linkHtml = call_user_func($userFunc, $dept); + + if(isset($deptMenu[$dept->id]) and !empty($deptMenu[$dept->id])) + { + if(!isset($deptMenu[$dept->parent])) $deptMenu[$dept->parent] = ''; + $deptMenu[$dept->parent] .= "
    • $linkHtml"; + $deptMenu[$dept->parent] .= "
        ".$deptMenu[$dept->id]."
      \n"; + } + else + { + if(isset($deptMenu[$dept->parent]) and !empty($deptMenu[$dept->parent])) + { + $deptMenu[$dept->parent] .= "
    • $linkHtml\n"; + } + else + { + $deptMenu[$dept->parent] = "
    • $linkHtml\n"; + } + } + $deptMenu[$dept->parent] .= "
    • \n"; + } + + $lastMenu = "
        " . @array_pop($deptMenu) . "
      \n"; + return $lastMenu; + } + + /** + * Create the manage link. + * + * @param int $dept + * @access public + * @return string + */ + public function createManageLink($dept) + { + $linkHtml = $dept->name; + $linkHtml .= ' ' . html::a(helper::createLink('dept', 'browse', "deptid={$dept->id}"), $this->lang->dept->manageChild); + $linkHtml .= ' ' . html::a(helper::createLink('dept', 'delete', "deptid={$dept->id}"), $this->lang->dept->delete, 'hiddenwin'); + $linkHtml .= ' ' . html::input("orders[$dept->id]", $dept->order, 'style="width:30px;text-align:center"'); + return $linkHtml; + } + + /** + * Create the member link. + * + * @param int $dept + * @access public + * @return string + */ + public function createMemberLink($dept) + { + $linkHtml = html::a(helper::createLink('company', 'browse', "dept={$dept->id}"), $dept->name, '_self', "id='dept{$dept->id}'"); + return $linkHtml; + } + + /** + * Get sons of a department. + * + * @param int $deptID + * @access public + * @return array + */ + public function getSons($deptID) + { + return $this->dao->select('*')->from(TABLE_DEPT)->where('parent')->eq($deptID)->orderBy('`order`')->fetchAll(); + } + + /** + * Get all childs. + * + * @param int $deptID + * @access public + * @return array + */ + public function getAllChildId($deptID) + { + if($deptID == 0) return array(); + $dept = $this->getById($deptID); + $childs = $this->dao->select('id')->from(TABLE_DEPT)->where('path')->like($dept->path . '%')->fetchPairs(); + return array_keys($childs); + } + + /** + * Get parents. + * + * @param int $deptID + * @access public + * @return array + */ + public function getParents($deptID) + { + if($deptID == 0) return array(); + $path = $this->dao->select('path')->from(TABLE_DEPT)->where('id')->eq($deptID)->fetch('path'); + $path = substr($path, 1, -1); + if(empty($path)) return array(); + return $this->dao->select('*')->from(TABLE_DEPT)->where('id')->in($path)->orderBy('grade')->fetchAll(); + } + + /** + * Update order. + * + * @param int $orders + * @access public + * @return void + */ + public function updateOrder($orders) + { + foreach($orders as $deptID => $order) $this->dao->update(TABLE_DEPT)->set('`order`')->eq($order)->where('id')->eq($deptID)->exec(); + } + + /** + * Manage childs. + * + * @param int $parentDeptID + * @param string $childs + * @access public + * @return void + */ + public function manageChild($parentDeptID, $childs) + { + $parentDept = $this->getByID($parentDeptID); + if($parentDept) + { + $grade = $parentDept->grade + 1; + $parentPath = $parentDept->path; + } + else + { + $grade = 1; + $parentPath = ','; + } + + foreach($childs as $deptID => $deptName) + { + if(empty($deptName)) continue; + if(is_numeric($deptID)) + { + $dept->name = strip_tags($deptName); + $dept->parent = $parentDeptID; + $dept->grade = $grade; + $this->dao->insert(TABLE_DEPT)->data($dept)->exec(); + $deptID = $this->dao->lastInsertID(); + $childPath = $parentPath . "$deptID,"; + $this->dao->update(TABLE_DEPT)->set('path')->eq($childPath)->where('id')->eq($deptID)->exec(); + } + else + { + $deptID = str_replace('id', '', $deptID); + $this->dao->update(TABLE_DEPT)->set('name')->eq(strip_tags($deptName))->where('id')->eq($deptID)->exec(); + } + } + } + + /** + * Get users of a deparment. + * + * @param int $deptID + * @access public + * @return array + */ + public function getUsers($deptID) + { + return $this->dao->select('*')->from(TABLE_USER) + ->where('deleted')->eq(0) + ->beginIF($deptID)->andWhere('dept')->in($deptID)->fi() + ->orderBy('id') + ->fetchAll(); + } + + /** + * Delete a department. + * + * @param int $deptID + * @access public + * @return void + */ + public function delete($deptID) + { + $this->dao->delete()->from(TABLE_DEPT)->where('id')->eq($deptID)->exec(); + } +} diff --git a/module/dept/view/browse.html.php b/module/dept/view/browse.html.php index 220fff29f7..debc7952cf 100644 --- a/module/dept/view/browse.html.php +++ b/module/dept/view/browse.html.php @@ -1,67 +1,67 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
      -
      '> - - - - - -
      title;?>
      -
      -
      dept->updateOrder);?>
      -
      -
      -
      -
      '> - - - - - - - - - -
      dept->manageChild;?>
      - - createLink('dept', 'browse'), $this->app->company->name); - echo $lang->arrow; - foreach($parentDepts as $dept) - { - echo html::a($this->createLink('dept', 'browse', "deptID=$dept->id"), $dept->name); - echo $lang->arrow; - } - ?> - - - id]", $sonDept->name) . '
      '; - for($i = 0; $i < DEPT::NEW_CHILD_COUNT ; $i ++) echo html::input("depts[]") . '
      '; - ?> -
      - - -
      -
      -
      - + + * @package dept + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
      +
      '> + + + + + +
      title;?>
      +
      +
      dept->updateOrder);?>
      +
      +
      +
      +
      '> + + + + + + + + + +
      dept->manageChild;?>
      + + createLink('dept', 'browse'), $this->app->company->name); + echo $lang->arrow; + foreach($parentDepts as $dept) + { + echo html::a($this->createLink('dept', 'browse', "deptID=$dept->id"), $dept->name); + echo $lang->arrow; + } + ?> + + + id]", $sonDept->name) . '
      '; + for($i = 0; $i < DEPT::NEW_CHILD_COUNT ; $i ++) echo html::input("depts[]") . '
      '; + ?> +
      + + +
      +
      +
      + diff --git a/module/doc/control.php b/module/doc/control.php index 336a9a3714..11a4a85fb2 100644 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1,420 +1,420 @@ - - * @package doc - * @version $Id: control.php 933 2010-07-06 06:53:40Z wwccss $ - * @link http://www.zentao.net - */ -class doc extends control -{ - /** - * Construct function, load user, tree, action auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('user'); - $this->loadModel('tree'); - $this->loadModel('action'); - $this->loadModel('product'); - $this->loadModel('project'); - $this->libs = $this->doc->getLibs(); - } - - /** - * Go to browse page. - * - * @access public - * @return void - */ - public function index() - { - $this->locate(inlink('browse')); - } - - /** - * Browse docs. - * - * @param string|int $libID product|project or the int id of custom library - * @param int $moduleID - * @param int $productID - * @param int $projectID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browse($libID = 'product', $moduleID = 0, $productID = 0, $projectID = 0, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Set browseType.*/ - $browseType = strtolower($browseType); - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Set menu, save session. */ - $this->doc->setMenu($this->libs, $libID, 'doc'); - $this->session->set('docList', $this->app->getURI(true)); - - /* Set header and position. */ - $this->view->header->title = $this->lang->doc->index . $this->lang->colon . $this->libs[$libID]; - $this->view->position[] = $this->libs[$libID]; - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - /* Get docs. */ - $modules = 0; - $docs=array(); - if($browseType == "bymodule") - { - if($moduleID) $modules = $this->tree->getAllChildID($moduleID); - $docs = $this->doc->getDocs($libID, $productID, $projectID, $modules, $orderBy, $pager); - } - elseif($browseType == "bysearch") - { - if($queryID) - { - $query = $this->loadModel('search')->getQuery($queryID); - if($query) - { - $this->session->set('docQuery', $query->sql); - $this->session->set('docForm', $query->form); - } - else - { - $this->session->set('docQuery', ' 1 = 1'); - } - } - else - { - if($this->session->docQuery == false) $this->session->set('docQuery', ' 1 = 1'); - } - $docQuery = str_replace("`product` = 'all'", '1', $this->session->docQuery); // Search all producti. - $docQuery = str_replace("`project` = 'all'", '1', $docQuery); // Search all project. - $docs = $this->dao->select('*')->from(TABLE_DOC)->where($docQuery) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /* Get the tree menu. */ - if($libID == 'product') - { - $moduleTree = $this->tree->getProductDocTreeMenu(); - } - elseif($libID == 'project') - { - $moduleTree = $this->tree->getProjectDocTreeMenu(); - } - else - { - $moduleTree = $this->tree->getTreeMenu($libID, $viewType = 'customdoc', $startModuleID = 0, array('treeModel', 'createDocLink')); - } - - /* Build the search form. */ - $this->config->doc->search['actionURL'] = $this->createLink('doc', 'browse', "libID=$libID&moduleID=$moduleID&procuctID=$productID&projectID=$projectID&browseType=bySearch&queryID=myQueryID"); - $this->config->doc->search['queryID'] = $queryID; - $this->config->doc->search['params']['product']['values'] = array(''=>'') + $this->product->getPairs() + array('all'=>$this->lang->doc->allProduct); - $this->config->doc->search['params']['project']['values'] = array(''=>'') + $this->project->getPairs() + array('all'=>$this->lang->doc->allProject); - $this->config->doc->search['params']['lib']['values'] = array(''=>'') + $this->libs; - $this->config->doc->search['params']['type']['values'] = array(''=>'') + $this->config->doc->search['params']['type']['values']; - - /* Get the modules. */ - if($libID == 'product' or $libID == 'project') - { - $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); - } - else - { - $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); - } - $this->config->doc->search['params']['module']['values'] = array(''=>'') + $moduleOptionMenu; - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->doc->search); - - $this->view->libID = $libID; - $this->view->libName = $this->libs[$libID]; - $this->view->moduleID = $moduleID; - $this->view->moduleTree = $moduleTree; - $this->view->parentModules = $this->tree->getParents($moduleID); - $this->view->docs = $docs; - $this->view->pager = $pager; - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->orderBy = $orderBy; - $this->view->productID = $productID; - $this->view->projectID = $projectID; - $this->view->browseType = $browseType; - $this->view->param = $param; - - $this->display(); - } - - /** - * Create a library. - * - * @access public - * @return void - */ - public function createLib() - { - if(!empty($_POST)) - { - $libID = $this->doc->createLib(); - if(!dao::isError()) - { - $this->loadModel('action')->create('docLib', $libID, 'Created'); - die(js::locate($this->createLink($this->moduleName, 'browse', "libID=$libID"), 'parent')); - } - else - { - echo js::error(dao::getError()); - } - } - die($this->display()); - } - - /** - * Edit a library. - * - * @param int $libID - * @access public - * @return void - */ - public function editLib($libID) - { - if(!empty($_POST)) - { - $changes = $this->doc->updateLib($libID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('docLib', $libID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink($this->moduleName, 'browse', "libID=$libID"), 'parent')); - } - - $lib = $this->doc->getLibByID($libID); - $this->view->libName = empty($lib) ? $libID : $lib->name; - $this->view->libID = $libID; - - die($this->display()); - } - - /** - * Delete a library. - * - * @param int $libID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function deleteLib($libID, $confirm = 'no') - { - if($libID == 'product' or $libID == 'project') die(); - if($confirm == 'no') - { - die(js::confirm($this->lang->doc->confirmDeleteLib, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes"))); - } - else - { - $this->doc->delete(TABLE_DOCLIB, $libID); - die(js::locate($this->createLink('doc', 'browse'), 'parent')); - } - } - - /** - * Create a doc. - * - * @param int|string $libID - * @param int $moduleID - * @param int $productID - * @param int $projectID - * @param string $from - * @access public - * @return void - */ - public function create($libID, $moduleID = 0, $productID = 0, $projectID = 0, $from = 'doc') - { - $projectID = (int)$projectID; - if(!empty($_POST)) - { - $docID = $this->doc->create(); - if(dao::isError()) die(js::error(dao::getError())); - $this->action->create('doc', $docID, 'Created'); - - if($from == 'product') $link = $this->createLink('product', 'doc', "productID={$this->post->product}"); - if($from == 'project') $link = $this->createLink('project', 'doc', "projectID={$this->post->project}"); - if($from == 'doc') - { - $productID = intval($this->post->product); - $projectID = intval($this->post->project); - $vars = "libID=$libID&moduleID={$this->post->module}&productID=$productID&projectID=$projectID"; - $link = $this->createLink('doc', 'browse', $vars); - } - die(js::locate($link, 'parent')); - } - - $this->loadModel('product'); - $this->loadModel('project'); - - /* According the from, set menus. */ - if($from == 'product') - { - $this->lang->doc->menu = $this->lang->product->menu; - $this->product->setMenu($this->product->getPairs(), $productID); - $this->lang->set('menugroup.doc', 'product'); - } - elseif($from == 'project') - { - $this->lang->doc->menu = $this->lang->project->menu; - $this->project->setMenu($this->project->getPairs('nocode'), $projectID); - $this->lang->set('menugroup.doc', 'project'); - } - else - { - $this->doc->setMenu($this->libs, $libID); - } - - /* Get the modules. */ - if($libID == 'product' or $libID == 'project') - { - $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); - } - else - { - $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); - } - - $this->view->header->title = $this->libs[$libID] . $this->lang->colon . $this->lang->doc->create; - $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$libID"), $this->libs[$libID]); - $this->view->position[] = $this->lang->doc->create; - - $this->view->libID = $libID; - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->view->moduleID = $moduleID; - $this->view->productID = $productID; - $this->view->projectID = $projectID; - $this->view->products = $projectID == 0 ? $this->product->getPairs() : $this->project->getProducts($projectID); - $this->view->projects = $this->loadModel('project')->getPairs('all'); - - $this->display(); - } - - /** - * Edit a doc. - * - * @param int $docID - * @access public - * @return void - */ - public function edit($docID) - { - if(!empty($_POST)) - { - $changes = $this->doc->update($docID); - if(dao::isError()) die(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('doc', $docID); - if($this->post->comment != '' or !empty($changes) or !empty($files)) - { - $action = !empty($changes) ? 'Edited' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; - $actionID = $this->action->create('doc', $docID, $action, $fileAction . $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('doc', 'view', "docID=$docID"), 'parent')); - } - - /* Get doc and set menu. */ - $doc = $this->doc->getById($docID); - $libID = $doc->lib; - $this->doc->setMenu($this->libs, $libID); - - /* Get modules. */ - if($libID == 'product' or $libID == 'project') - { - $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); - } - else - { - $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); - } - - $this->view->header->title = $this->libs[$libID] . $this->lang->colon . $this->lang->doc->create; - $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$libID"), $this->libs[$libID]); - $this->view->position[] = $this->lang->doc->edit; - - $this->view->doc = $doc; - $this->view->libID = $libID; - $this->view->users = $this->user->getPairs('noclosed,nodeleted'); - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->display(); - } - - /** - * View a doc. - * - * @param int $docID - * @access public - * @return void - */ - public function view($docID) - { - /* Get doc. */ - $doc = $this->doc->getById($docID); - if(!$doc) die(js::error($this->lang->notFound) . js::locate('back')); - if($doc->project != 0 and !$this->project->checkPriv($this->project->getById($doc->project))) - { - echo(js::alert($this->lang->error->accessDenied)); - die(js::locate('back')); - } - - /* Get library. */ - $lib = $doc->libName; - if($doc->lib == 'product') $lib = $doc->productName; - if($doc->lib == 'project') $lib = $doc->productName . $this->lang->arrow . $doc->projectName; - - /* Set menu. */ - $this->doc->setMenu($this->libs, $doc->lib); - - $this->view->header->title = $this->libs[$doc->lib] . $this->lang->colon . $this->lang->doc->view; - $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$doc->lib"), $this->libs[$doc->lib]); - $this->view->position[] = $this->lang->doc->view; - - $this->view->doc = $doc; - $this->view->lib = $lib; - $this->view->actions = $this->loadModel('action')->getList('doc', $docID); - $this->view->users = $this->user->getPairs('noclosed,nodeleted'); - - $this->display(); - } - - /** - * Delete a doc. - * - * @param int $docID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($docID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->doc->confirmDelete, inlink('delete', "docID=$docID&confirm=yes"))); - } - else - { - $this->doc->delete(TABLE_DOC, $docID); - die(js::locate($this->session->docList, 'parent')); - } - } -} + + * @package doc + * @version $Id: control.php 933 2010-07-06 06:53:40Z wwccss $ + * @link http://www.zentao.net + */ +class doc extends control +{ + /** + * Construct function, load user, tree, action auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('user'); + $this->loadModel('tree'); + $this->loadModel('action'); + $this->loadModel('product'); + $this->loadModel('project'); + $this->libs = $this->doc->getLibs(); + } + + /** + * Go to browse page. + * + * @access public + * @return void + */ + public function index() + { + $this->locate(inlink('browse')); + } + + /** + * Browse docs. + * + * @param string|int $libID product|project or the int id of custom library + * @param int $moduleID + * @param int $productID + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($libID = 'product', $moduleID = 0, $productID = 0, $projectID = 0, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Set browseType.*/ + $browseType = strtolower($browseType); + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Set menu, save session. */ + $this->doc->setMenu($this->libs, $libID, 'doc'); + $this->session->set('docList', $this->app->getURI(true)); + + /* Set header and position. */ + $this->view->header->title = $this->lang->doc->index . $this->lang->colon . $this->libs[$libID]; + $this->view->position[] = $this->libs[$libID]; + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + /* Get docs. */ + $modules = 0; + $docs=array(); + if($browseType == "bymodule") + { + if($moduleID) $modules = $this->tree->getAllChildID($moduleID); + $docs = $this->doc->getDocs($libID, $productID, $projectID, $modules, $orderBy, $pager); + } + elseif($browseType == "bysearch") + { + if($queryID) + { + $query = $this->loadModel('search')->getQuery($queryID); + if($query) + { + $this->session->set('docQuery', $query->sql); + $this->session->set('docForm', $query->form); + } + else + { + $this->session->set('docQuery', ' 1 = 1'); + } + } + else + { + if($this->session->docQuery == false) $this->session->set('docQuery', ' 1 = 1'); + } + $docQuery = str_replace("`product` = 'all'", '1', $this->session->docQuery); // Search all producti. + $docQuery = str_replace("`project` = 'all'", '1', $docQuery); // Search all project. + $docs = $this->dao->select('*')->from(TABLE_DOC)->where($docQuery) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /* Get the tree menu. */ + if($libID == 'product') + { + $moduleTree = $this->tree->getProductDocTreeMenu(); + } + elseif($libID == 'project') + { + $moduleTree = $this->tree->getProjectDocTreeMenu(); + } + else + { + $moduleTree = $this->tree->getTreeMenu($libID, $viewType = 'customdoc', $startModuleID = 0, array('treeModel', 'createDocLink')); + } + + /* Build the search form. */ + $this->config->doc->search['actionURL'] = $this->createLink('doc', 'browse', "libID=$libID&moduleID=$moduleID&procuctID=$productID&projectID=$projectID&browseType=bySearch&queryID=myQueryID"); + $this->config->doc->search['queryID'] = $queryID; + $this->config->doc->search['params']['product']['values'] = array(''=>'') + $this->product->getPairs() + array('all'=>$this->lang->doc->allProduct); + $this->config->doc->search['params']['project']['values'] = array(''=>'') + $this->project->getPairs() + array('all'=>$this->lang->doc->allProject); + $this->config->doc->search['params']['lib']['values'] = array(''=>'') + $this->libs; + $this->config->doc->search['params']['type']['values'] = array(''=>'') + $this->config->doc->search['params']['type']['values']; + + /* Get the modules. */ + if($libID == 'product' or $libID == 'project') + { + $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); + } + else + { + $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); + } + $this->config->doc->search['params']['module']['values'] = array(''=>'') + $moduleOptionMenu; + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->doc->search); + + $this->view->libID = $libID; + $this->view->libName = $this->libs[$libID]; + $this->view->moduleID = $moduleID; + $this->view->moduleTree = $moduleTree; + $this->view->parentModules = $this->tree->getParents($moduleID); + $this->view->docs = $docs; + $this->view->pager = $pager; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->orderBy = $orderBy; + $this->view->productID = $productID; + $this->view->projectID = $projectID; + $this->view->browseType = $browseType; + $this->view->param = $param; + + $this->display(); + } + + /** + * Create a library. + * + * @access public + * @return void + */ + public function createLib() + { + if(!empty($_POST)) + { + $libID = $this->doc->createLib(); + if(!dao::isError()) + { + $this->loadModel('action')->create('docLib', $libID, 'Created'); + die(js::locate($this->createLink($this->moduleName, 'browse', "libID=$libID"), 'parent')); + } + else + { + echo js::error(dao::getError()); + } + } + die($this->display()); + } + + /** + * Edit a library. + * + * @param int $libID + * @access public + * @return void + */ + public function editLib($libID) + { + if(!empty($_POST)) + { + $changes = $this->doc->updateLib($libID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('docLib', $libID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink($this->moduleName, 'browse', "libID=$libID"), 'parent')); + } + + $lib = $this->doc->getLibByID($libID); + $this->view->libName = empty($lib) ? $libID : $lib->name; + $this->view->libID = $libID; + + die($this->display()); + } + + /** + * Delete a library. + * + * @param int $libID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function deleteLib($libID, $confirm = 'no') + { + if($libID == 'product' or $libID == 'project') die(); + if($confirm == 'no') + { + die(js::confirm($this->lang->doc->confirmDeleteLib, $this->createLink('doc', 'deleteLib', "libID=$libID&confirm=yes"))); + } + else + { + $this->doc->delete(TABLE_DOCLIB, $libID); + die(js::locate($this->createLink('doc', 'browse'), 'parent')); + } + } + + /** + * Create a doc. + * + * @param int|string $libID + * @param int $moduleID + * @param int $productID + * @param int $projectID + * @param string $from + * @access public + * @return void + */ + public function create($libID, $moduleID = 0, $productID = 0, $projectID = 0, $from = 'doc') + { + $projectID = (int)$projectID; + if(!empty($_POST)) + { + $docID = $this->doc->create(); + if(dao::isError()) die(js::error(dao::getError())); + $this->action->create('doc', $docID, 'Created'); + + if($from == 'product') $link = $this->createLink('product', 'doc', "productID={$this->post->product}"); + if($from == 'project') $link = $this->createLink('project', 'doc', "projectID={$this->post->project}"); + if($from == 'doc') + { + $productID = intval($this->post->product); + $projectID = intval($this->post->project); + $vars = "libID=$libID&moduleID={$this->post->module}&productID=$productID&projectID=$projectID"; + $link = $this->createLink('doc', 'browse', $vars); + } + die(js::locate($link, 'parent')); + } + + $this->loadModel('product'); + $this->loadModel('project'); + + /* According the from, set menus. */ + if($from == 'product') + { + $this->lang->doc->menu = $this->lang->product->menu; + $this->product->setMenu($this->product->getPairs(), $productID); + $this->lang->set('menugroup.doc', 'product'); + } + elseif($from == 'project') + { + $this->lang->doc->menu = $this->lang->project->menu; + $this->project->setMenu($this->project->getPairs('nocode'), $projectID); + $this->lang->set('menugroup.doc', 'project'); + } + else + { + $this->doc->setMenu($this->libs, $libID); + } + + /* Get the modules. */ + if($libID == 'product' or $libID == 'project') + { + $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); + } + else + { + $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); + } + + $this->view->header->title = $this->libs[$libID] . $this->lang->colon . $this->lang->doc->create; + $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$libID"), $this->libs[$libID]); + $this->view->position[] = $this->lang->doc->create; + + $this->view->libID = $libID; + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->view->moduleID = $moduleID; + $this->view->productID = $productID; + $this->view->projectID = $projectID; + $this->view->products = $projectID == 0 ? $this->product->getPairs() : $this->project->getProducts($projectID); + $this->view->projects = $this->loadModel('project')->getPairs('all'); + + $this->display(); + } + + /** + * Edit a doc. + * + * @param int $docID + * @access public + * @return void + */ + public function edit($docID) + { + if(!empty($_POST)) + { + $changes = $this->doc->update($docID); + if(dao::isError()) die(js::error(dao::getError())); + $files = $this->loadModel('file')->saveUpload('doc', $docID); + if($this->post->comment != '' or !empty($changes) or !empty($files)) + { + $action = !empty($changes) ? 'Edited' : 'Commented'; + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; + $actionID = $this->action->create('doc', $docID, $action, $fileAction . $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('doc', 'view', "docID=$docID"), 'parent')); + } + + /* Get doc and set menu. */ + $doc = $this->doc->getById($docID); + $libID = $doc->lib; + $this->doc->setMenu($this->libs, $libID); + + /* Get modules. */ + if($libID == 'product' or $libID == 'project') + { + $moduleOptionMenu = $this->tree->getOptionMenu(0, $libID . 'doc', $startModuleID = 0); + } + else + { + $moduleOptionMenu = $this->tree->getOptionMenu($libID, 'customdoc', $startModuleID = 0); + } + + $this->view->header->title = $this->libs[$libID] . $this->lang->colon . $this->lang->doc->create; + $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$libID"), $this->libs[$libID]); + $this->view->position[] = $this->lang->doc->edit; + + $this->view->doc = $doc; + $this->view->libID = $libID; + $this->view->users = $this->user->getPairs('noclosed,nodeleted'); + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->display(); + } + + /** + * View a doc. + * + * @param int $docID + * @access public + * @return void + */ + public function view($docID) + { + /* Get doc. */ + $doc = $this->doc->getById($docID); + if(!$doc) die(js::error($this->lang->notFound) . js::locate('back')); + if($doc->project != 0 and !$this->project->checkPriv($this->project->getById($doc->project))) + { + echo(js::alert($this->lang->error->accessDenied)); + die(js::locate('back')); + } + + /* Get library. */ + $lib = $doc->libName; + if($doc->lib == 'product') $lib = $doc->productName; + if($doc->lib == 'project') $lib = $doc->productName . $this->lang->arrow . $doc->projectName; + + /* Set menu. */ + $this->doc->setMenu($this->libs, $doc->lib); + + $this->view->header->title = $this->libs[$doc->lib] . $this->lang->colon . $this->lang->doc->view; + $this->view->position[] = html::a($this->createLink('doc', 'browse', "libID=$doc->lib"), $this->libs[$doc->lib]); + $this->view->position[] = $this->lang->doc->view; + + $this->view->doc = $doc; + $this->view->lib = $lib; + $this->view->actions = $this->loadModel('action')->getList('doc', $docID); + $this->view->users = $this->user->getPairs('noclosed,nodeleted'); + + $this->display(); + } + + /** + * Delete a doc. + * + * @param int $docID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($docID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->doc->confirmDelete, inlink('delete', "docID=$docID&confirm=yes"))); + } + else + { + $this->doc->delete(TABLE_DOC, $docID); + die(js::locate($this->session->docList, 'parent')); + } + } +} diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index b4629578d2..2df0055ddb 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -1,65 +1,65 @@ - - * @package doc - * @version $Id: en.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -/* Fields. */ -$lang->doc->common = 'Doc'; -$lang->doc->id = 'ID'; -$lang->doc->product = 'Product'; -$lang->doc->project = 'Project'; -$lang->doc->lib = 'Library'; -$lang->doc->module = 'Module'; -$lang->doc->title = 'Title'; -$lang->doc->digest = 'Digest'; -$lang->doc->comment = 'Comment'; -$lang->doc->type = 'Type'; -$lang->doc->content = 'Content'; -$lang->doc->keywords = 'Keywords'; -$lang->doc->url = 'URL'; -$lang->doc->files = 'File'; -$lang->doc->views = 'Views'; -$lang->doc->addedBy = 'Added by'; -$lang->doc->addedDate = 'Added date'; -$lang->doc->editedBy = 'Edited by'; -$lang->doc->editedDate = 'Edited date'; - -$lang->doc->moduleDoc = 'By module'; -$lang->doc->searchDoc = 'By search'; -//$lang->doc->allDoc = 'All document'; - -$lang->doc->moduleName = 'Module name'; -$lang->doc->moduleOrder = 'Module order'; - -/* Actions. */ -$lang->doc->index = 'Index'; -$lang->doc->create = 'Create doc'; -$lang->doc->edit = 'Edit doc'; -$lang->doc->delete = 'Delete doc'; -$lang->doc->browse = 'Browse doc'; -$lang->doc->view = 'View doc'; -$lang->doc->createLib = 'Create library'; -$lang->doc->editLib = 'Edit library'; -$lang->doc->deleteLib = 'Delete library'; -$lang->doc->libName = 'Library name'; - -/* Browse tabs. */ -$lang->doc->allProduct = 'All products'; -$lang->doc->allProject = 'All projects'; - -$lang->doc->systemLibs['product'] = 'Product doc'; -$lang->doc->systemLibs['project'] = 'Project doc'; - -$lang->doc->types['file'] = 'File'; -$lang->doc->types['url'] = 'Link'; -$lang->doc->types['text'] = 'Html'; - -$lang->doc->confirmDelete = "Are you sure to delete this doc?"; -$lang->doc->confirmDeleteLib = " Are you sure to delete this doc library?"; -$lang->doc->errorEditSystemDoc = "System doc library needn't edit"; + + * @package doc + * @version $Id: en.php 824 2010-05-02 15:32:06Z wwccss $ + * @link http://www.zentao.net + */ +/* Fields. */ +$lang->doc->common = 'Doc'; +$lang->doc->id = 'ID'; +$lang->doc->product = 'Product'; +$lang->doc->project = 'Project'; +$lang->doc->lib = 'Library'; +$lang->doc->module = 'Module'; +$lang->doc->title = 'Title'; +$lang->doc->digest = 'Digest'; +$lang->doc->comment = 'Comment'; +$lang->doc->type = 'Type'; +$lang->doc->content = 'Content'; +$lang->doc->keywords = 'Keywords'; +$lang->doc->url = 'URL'; +$lang->doc->files = 'File'; +$lang->doc->views = 'Views'; +$lang->doc->addedBy = 'Added by'; +$lang->doc->addedDate = 'Added date'; +$lang->doc->editedBy = 'Edited by'; +$lang->doc->editedDate = 'Edited date'; + +$lang->doc->moduleDoc = 'By module'; +$lang->doc->searchDoc = 'By search'; +//$lang->doc->allDoc = 'All document'; + +$lang->doc->moduleName = 'Module name'; +$lang->doc->moduleOrder = 'Module order'; + +/* Actions. */ +$lang->doc->index = 'Index'; +$lang->doc->create = 'Create doc'; +$lang->doc->edit = 'Edit doc'; +$lang->doc->delete = 'Delete doc'; +$lang->doc->browse = 'Browse doc'; +$lang->doc->view = 'View doc'; +$lang->doc->createLib = 'Create library'; +$lang->doc->editLib = 'Edit library'; +$lang->doc->deleteLib = 'Delete library'; +$lang->doc->libName = 'Library name'; + +/* Browse tabs. */ +$lang->doc->allProduct = 'All products'; +$lang->doc->allProject = 'All projects'; + +$lang->doc->systemLibs['product'] = 'Product doc'; +$lang->doc->systemLibs['project'] = 'Project doc'; + +$lang->doc->types['file'] = 'File'; +$lang->doc->types['url'] = 'Link'; +$lang->doc->types['text'] = 'Html'; + +$lang->doc->confirmDelete = "Are you sure to delete this doc?"; +$lang->doc->confirmDeleteLib = " Are you sure to delete this doc library?"; +$lang->doc->errorEditSystemDoc = "System doc library needn't edit"; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 9c26317f65..b980621798 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -1,65 +1,65 @@ - - * @package doc - * @version $Id: zh-cn.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -/* 字段列表。*/ -$lang->doc->common = '文档视图'; -$lang->doc->id = '文档编号'; -$lang->doc->product = '所属产品'; -$lang->doc->project = '所属项目'; -$lang->doc->lib = '所属文档库'; -$lang->doc->module = '所属分类'; -$lang->doc->title = '文档标题'; -$lang->doc->digest = '文档摘要'; -$lang->doc->comment = '文档备注'; -$lang->doc->type = '文档类型'; -$lang->doc->content = '文档正文'; -$lang->doc->keywords = '关键字'; -$lang->doc->url = '文档URL'; -$lang->doc->files = '附件'; -$lang->doc->views = '查阅次数'; -$lang->doc->addedBy = '由谁添加'; -$lang->doc->addedDate = '添加时间'; -$lang->doc->editedBy = '由谁编辑'; -$lang->doc->editedDate = '编辑时间'; - -$lang->doc->moduleDoc = '按模块浏览'; -$lang->doc->searchDoc = '搜索'; -//$lang->doc->allDoc = '所有文档'; - -$lang->doc->moduleName = '模块名称'; -$lang->doc->moduleOrder = '模块排序'; - -/* 方法列表。*/ -$lang->doc->index = '首页'; -$lang->doc->create = '创建文档'; -$lang->doc->edit = '编辑文档'; -$lang->doc->delete = '删除文档'; -$lang->doc->browse = '文档列表'; -$lang->doc->view = '文档详情'; -$lang->doc->createLib = '创建文档库'; -$lang->doc->editLib = '编辑文档库'; -$lang->doc->deleteLib = '删除文档库'; -$lang->doc->libName = '文档库名称'; - -/* 查询条件列表 */ -$lang->doc->allProduct = '所有产品'; -$lang->doc->allProject = '所有项目'; - -$lang->doc->systemLibs['product'] = '产品文档库'; -$lang->doc->systemLibs['project'] = '项目文档库'; - -$lang->doc->types['file'] = '文件'; -$lang->doc->types['url'] = '链接'; -$lang->doc->types['text'] = '网页'; - -$lang->doc->confirmDelete = "您确定删除该文档吗?"; -$lang->doc->confirmDeleteLib = " 您确定删除该文档库吗?"; -$lang->doc->errorEditSystemDoc = "系统文档库无需修改。"; + + * @package doc + * @version $Id: zh-cn.php 824 2010-05-02 15:32:06Z wwccss $ + * @link http://www.zentao.net + */ +/* 字段列表。*/ +$lang->doc->common = '文档视图'; +$lang->doc->id = '文档编号'; +$lang->doc->product = '所属产品'; +$lang->doc->project = '所属项目'; +$lang->doc->lib = '所属文档库'; +$lang->doc->module = '所属分类'; +$lang->doc->title = '文档标题'; +$lang->doc->digest = '文档摘要'; +$lang->doc->comment = '文档备注'; +$lang->doc->type = '文档类型'; +$lang->doc->content = '文档正文'; +$lang->doc->keywords = '关键字'; +$lang->doc->url = '文档URL'; +$lang->doc->files = '附件'; +$lang->doc->views = '查阅次数'; +$lang->doc->addedBy = '由谁添加'; +$lang->doc->addedDate = '添加时间'; +$lang->doc->editedBy = '由谁编辑'; +$lang->doc->editedDate = '编辑时间'; + +$lang->doc->moduleDoc = '按模块浏览'; +$lang->doc->searchDoc = '搜索'; +//$lang->doc->allDoc = '所有文档'; + +$lang->doc->moduleName = '模块名称'; +$lang->doc->moduleOrder = '模块排序'; + +/* 方法列表。*/ +$lang->doc->index = '首页'; +$lang->doc->create = '创建文档'; +$lang->doc->edit = '编辑文档'; +$lang->doc->delete = '删除文档'; +$lang->doc->browse = '文档列表'; +$lang->doc->view = '文档详情'; +$lang->doc->createLib = '创建文档库'; +$lang->doc->editLib = '编辑文档库'; +$lang->doc->deleteLib = '删除文档库'; +$lang->doc->libName = '文档库名称'; + +/* 查询条件列表 */ +$lang->doc->allProduct = '所有产品'; +$lang->doc->allProject = '所有项目'; + +$lang->doc->systemLibs['product'] = '产品文档库'; +$lang->doc->systemLibs['project'] = '项目文档库'; + +$lang->doc->types['file'] = '文件'; +$lang->doc->types['url'] = '链接'; +$lang->doc->types['text'] = '网页'; + +$lang->doc->confirmDelete = "您确定删除该文档吗?"; +$lang->doc->confirmDeleteLib = " 您确定删除该文档库吗?"; +$lang->doc->errorEditSystemDoc = "系统文档库无需修改。"; diff --git a/module/doc/lang/zh-tw.php b/module/doc/lang/zh-tw.php index 4bc9947b56..28aaee6e43 100644 --- a/module/doc/lang/zh-tw.php +++ b/module/doc/lang/zh-tw.php @@ -1,65 +1,65 @@ - - * @package doc - * @version $Id: zh-tw.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -/* 欄位列表。*/ -$lang->doc->common = '文檔視圖'; -$lang->doc->id = '文檔編號'; -$lang->doc->product = '所屬產品'; -$lang->doc->project = '所屬項目'; -$lang->doc->lib = '所屬文檔庫'; -$lang->doc->module = '所屬分類'; -$lang->doc->title = '文檔標題'; -$lang->doc->digest = '文檔摘要'; -$lang->doc->comment = '文檔備註'; -$lang->doc->type = '文檔類型'; -$lang->doc->content = '文檔正文'; -$lang->doc->keywords = '關鍵字'; -$lang->doc->url = '文檔URL'; -$lang->doc->files = '附件'; -$lang->doc->views = '查閲次數'; -$lang->doc->addedBy = '由誰添加'; -$lang->doc->addedDate = '添加時間'; -$lang->doc->editedBy = '由誰編輯'; -$lang->doc->editedDate = '編輯時間'; - -$lang->doc->moduleDoc = '按模組瀏覽'; -$lang->doc->searchDoc = '搜索'; -//$lang->doc->allDoc = '所有文檔'; - -$lang->doc->moduleName = '模組名稱'; -$lang->doc->moduleOrder = '模組排序'; - -/* 方法列表。*/ -$lang->doc->index = '首頁'; -$lang->doc->create = '創建文檔'; -$lang->doc->edit = '編輯文檔'; -$lang->doc->delete = '刪除文檔'; -$lang->doc->browse = '文檔列表'; -$lang->doc->view = '文檔詳情'; -$lang->doc->createLib = '創建文檔庫'; -$lang->doc->editLib = '編輯文檔庫'; -$lang->doc->deleteLib = '刪除文檔庫'; -$lang->doc->libName = '文檔庫名稱'; - -/* 查詢條件列表 */ -$lang->doc->allProduct = '所有產品'; -$lang->doc->allProject = '所有項目'; - -$lang->doc->systemLibs['product'] = '產品文檔庫'; -$lang->doc->systemLibs['project'] = '項目文檔庫'; - -$lang->doc->types['file'] = '檔案'; -$lang->doc->types['url'] = '連結'; -$lang->doc->types['text'] = '網頁'; - -$lang->doc->confirmDelete = "您確定刪除該文檔嗎?"; -$lang->doc->confirmDeleteLib = " 您確定刪除該文檔庫嗎?"; -$lang->doc->errorEditSystemDoc = "系統文檔庫無需修改。"; + + * @package doc + * @version $Id: zh-tw.php 824 2010-05-02 15:32:06Z wwccss $ + * @link http://www.zentao.net + */ +/* 欄位列表。*/ +$lang->doc->common = '文檔視圖'; +$lang->doc->id = '文檔編號'; +$lang->doc->product = '所屬產品'; +$lang->doc->project = '所屬項目'; +$lang->doc->lib = '所屬文檔庫'; +$lang->doc->module = '所屬分類'; +$lang->doc->title = '文檔標題'; +$lang->doc->digest = '文檔摘要'; +$lang->doc->comment = '文檔備註'; +$lang->doc->type = '文檔類型'; +$lang->doc->content = '文檔正文'; +$lang->doc->keywords = '關鍵字'; +$lang->doc->url = '文檔URL'; +$lang->doc->files = '附件'; +$lang->doc->views = '查閲次數'; +$lang->doc->addedBy = '由誰添加'; +$lang->doc->addedDate = '添加時間'; +$lang->doc->editedBy = '由誰編輯'; +$lang->doc->editedDate = '編輯時間'; + +$lang->doc->moduleDoc = '按模組瀏覽'; +$lang->doc->searchDoc = '搜索'; +//$lang->doc->allDoc = '所有文檔'; + +$lang->doc->moduleName = '模組名稱'; +$lang->doc->moduleOrder = '模組排序'; + +/* 方法列表。*/ +$lang->doc->index = '首頁'; +$lang->doc->create = '創建文檔'; +$lang->doc->edit = '編輯文檔'; +$lang->doc->delete = '刪除文檔'; +$lang->doc->browse = '文檔列表'; +$lang->doc->view = '文檔詳情'; +$lang->doc->createLib = '創建文檔庫'; +$lang->doc->editLib = '編輯文檔庫'; +$lang->doc->deleteLib = '刪除文檔庫'; +$lang->doc->libName = '文檔庫名稱'; + +/* 查詢條件列表 */ +$lang->doc->allProduct = '所有產品'; +$lang->doc->allProject = '所有項目'; + +$lang->doc->systemLibs['product'] = '產品文檔庫'; +$lang->doc->systemLibs['project'] = '項目文檔庫'; + +$lang->doc->types['file'] = '檔案'; +$lang->doc->types['url'] = '連結'; +$lang->doc->types['text'] = '網頁'; + +$lang->doc->confirmDelete = "您確定刪除該文檔嗎?"; +$lang->doc->confirmDeleteLib = " 您確定刪除該文檔庫嗎?"; +$lang->doc->errorEditSystemDoc = "系統文檔庫無需修改。"; diff --git a/module/doc/model.php b/module/doc/model.php index 46efa509d5..b7befc86ae 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1,281 +1,281 @@ - - * @package doc - * @version $Id: model.php 881 2010-06-22 06:50:32Z chencongzhi520 $ - * @link http://www.zentao.net - */ -?> -app->getModuleName(); - $currentMethod = $this->app->getMethodName(); - - $selectHtml = html::select('libID', $libs, $libID, "onchange=\"switchDocLib(this.value, '$currentModule', '$currentMethod', '$extra');\""); - common::setMenuVars($this->lang->doc->menu, 'list', $selectHtml . $this->lang->arrow); - foreach($this->lang->doc->menu as $key => $menu) - { - if($key != 'list') common::setMenuVars($this->lang->doc->menu, $key, $libID); - } - } - - /** - * Get library by id. - * - * @param int $libID - * @access public - * @return object - */ - public function getLibById($libID) - { - return $this->dao->findByID($libID)->from(TABLE_DOCLIB)->fetch(); - } - - /** - * Get libraries. - * - * @access public - * @return array - */ - public function getLibs() - { - $libs = $this->dao->select('id, name')->from(TABLE_DOCLIB)->where('deleted')->eq(0)->fetchPairs(); - return $this->lang->doc->systemLibs + $libs; - } - - /** - * Create a library. - * - * @access public - * @return void - */ - public function createLib() - { - $lib = fixer::input('post')->stripTags('name')->get(); - $this->dao->insert(TABLE_DOCLIB) - ->data($lib) - ->autoCheck() - ->batchCheck('name', 'notempty') - ->check('name', 'unique') - ->exec(); - return $this->dao->lastInsertID(); - } - - /** - * Update a library. - * - * @param int $libID - * @access public - * @return void - */ - public function updateLib($libID) - { - $libID = (int)$libID; - $oldLib = $this->getLibById($libID); - $lib = fixer::input('post')->stripTags('name')->get(); - $this->dao->update(TABLE_DOCLIB) - ->data($lib) - ->autoCheck() - ->batchCheck('name', 'notempty') - ->check('name', 'unique', "id != $libID") - ->where('id')->eq($libID) - ->exec(); - if(!dao::isError()) return common::createChanges($oldLib, $lib); - } - - /** - * Get docs. - * - * @param int|string $libID - * @param int $productID - * @param int $projectID - * @param int $module - * @param string $orderBy - * @param object $pager - * @access public - * @return void - */ - public function getDocs($libID, $productID, $projectID, $module, $orderBy, $pager) - { - $products = $this->loadModel('product')->getPairs(); - $projects = $this->loadModel('project')->getPairs(); - $keysOfProducts = array_keys($products); - $keysOfProjects = array_keys($projects); - $allKeysOfProjects = $keysOfProjects; - $allKeysOfProjects[] = 0; - - return $this->dao->select('*')->from(TABLE_DOC) - ->where('deleted')->eq(0) - ->beginIF(is_numeric($libID))->andWhere('lib')->eq($libID)->fi() - ->beginIF($libID == 'product')->andWhere('product')->in($keysOfProducts)->andWhere('project')->in($allKeysOfProjects)->fi() - ->beginIF($libID == 'project')->andWhere('project')->in($keysOfProjects)->fi() - ->beginIF($productID > 0)->andWhere('product')->eq($productID)->fi() - ->beginIF($projectID > 0)->andWhere('project')->eq($projectID)->fi() - ->beginIF((string)$projectID == 'int')->andWhere('project')->gt(0)->fi() - ->beginIF($module)->andWhere('module')->in($module)->fi() - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * Get doc info by id. - * - * @param int $docID - * @access public - * @return void - */ - public function getById($docID) - { - $doc = $this->dao->select('*') - ->from(TABLE_DOC) - ->where('id')->eq((int)$docID) - ->fetch(); - if(!$doc) return false; - $doc->content = $this->loadModel('file')->setImgSize($doc->content); - $doc->files = $this->loadModel('file')->getByObject('doc', $docID); - - $doc->libName = ''; - $doc->productName = ''; - $doc->projectName = ''; - $doc->moduleName = ''; - if($doc->lib) $doc->libName = $this->dao->findByID($doc->lib)->from(TABLE_DOCLIB)->fetch('name'); - if($doc->product) $doc->productName = $this->dao->findByID($doc->product)->from(TABLE_PRODUCT)->fetch('name'); - if($doc->project) $doc->projectName = $this->dao->findByID($doc->project)->from(TABLE_PROJECT)->fetch('name'); - if($doc->module) $doc->moduleName = $this->dao->findByID($doc->module)->from(TABLE_MODULE)->fetch('name'); - return $doc; - } - - /** - * Create a doc. - * - * @access public - * @return void - */ - public function create() - { - $now = helper::now(); - $doc = fixer::input('post') - ->add('addedBy', $this->app->user->account) - ->add('addedDate', $now) - ->setDefault('product, project, module', 0) - ->specialChars('title, digest, keywords') - ->encodeURL('url') - ->cleanInt('product, project, module') - ->remove('files, labels') - ->get(); - $condition = "lib = '$doc->lib' AND module = $doc->module"; - $this->dao->insert(TABLE_DOC) - ->data($doc) - ->autoCheck() - ->batchCheck($this->config->doc->create->requiredFields, 'notempty') - ->check('title', 'unique', $condition) - ->exec(); - if(!dao::isError()) - { - $docID = $this->dao->lastInsertID(); - $this->loadModel('file')->saveUpload('doc', $docID); - return $docID; - } - return false; - } - - /** - * Update a doc. - * - * @param int $docID - * @access public - * @return void - */ - public function update($docID) - { - $oldDoc = $this->getById($docID); - $now = helper::now(); - $doc = fixer::input('post') - ->cleanInt('module') - ->setDefault('module', 0) - ->specialChars('title, digest, keywords') - ->encodeURL('url') - ->remove('comment,files, labels') - ->add('editedBy', $this->app->user->account) - ->add('editedDate', $now) - ->get(); - - $condition = "lib = '$doc->lib' AND module = $doc->module AND id != $docID"; - $this->dao->update(TABLE_DOC)->data($doc) - ->autoCheck() - ->batchCheck($this->config->doc->edit->requiredFields, 'notempty') - ->check('title', 'unique', $condition) - ->where('id')->eq((int)$docID) - ->exec(); - if(!dao::isError()) return common::createChanges($oldDoc, $doc); - } - - /** - * Get docs of a product. - * - * @param int $productID - * @access public - * @return array - */ - public function getProductDocs($productID) - { - return $this->dao->select('t1.*, t2.name as module') - ->from(TABLE_DOC)->alias('t1') - ->leftjoin(TABLE_MODULE)->alias('t2')->on('t1.module = t2.id') - ->where('t1.product')->eq($productID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy('t1.id_desc') - ->fetchAll(); - } - - /** - * Get docs of a project. - * - * @param int $projectID - * @access public - * @return array - */ - public function getProjectDocs($projectID) - { - return $this->dao->findByProject($projectID)->from(TABLE_DOC)->andWhere('deleted')->eq(0)->orderBy('id_desc')->fetchAll(); - } - - /** - * Get pairs of product modules. - * - * @access public - * @return array - */ - public function getProductModulePairs() - { - return $this->dao->findByType('productdoc')->from(TABLE_MODULE)->fetchPairs('id', 'name'); - } - - /** - * Get pairs of project modules. - * - * @access public - * @return array - */ - public function getProjectModulePairs() - { - return $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->andWhere('type')->eq('projectdoc')->fetchPairs('id', 'name'); - } -} + + * @package doc + * @version $Id: model.php 881 2010-06-22 06:50:32Z chencongzhi520 $ + * @link http://www.zentao.net + */ +?> +app->getModuleName(); + $currentMethod = $this->app->getMethodName(); + + $selectHtml = html::select('libID', $libs, $libID, "onchange=\"switchDocLib(this.value, '$currentModule', '$currentMethod', '$extra');\""); + common::setMenuVars($this->lang->doc->menu, 'list', $selectHtml . $this->lang->arrow); + foreach($this->lang->doc->menu as $key => $menu) + { + if($key != 'list') common::setMenuVars($this->lang->doc->menu, $key, $libID); + } + } + + /** + * Get library by id. + * + * @param int $libID + * @access public + * @return object + */ + public function getLibById($libID) + { + return $this->dao->findByID($libID)->from(TABLE_DOCLIB)->fetch(); + } + + /** + * Get libraries. + * + * @access public + * @return array + */ + public function getLibs() + { + $libs = $this->dao->select('id, name')->from(TABLE_DOCLIB)->where('deleted')->eq(0)->fetchPairs(); + return $this->lang->doc->systemLibs + $libs; + } + + /** + * Create a library. + * + * @access public + * @return void + */ + public function createLib() + { + $lib = fixer::input('post')->stripTags('name')->get(); + $this->dao->insert(TABLE_DOCLIB) + ->data($lib) + ->autoCheck() + ->batchCheck('name', 'notempty') + ->check('name', 'unique') + ->exec(); + return $this->dao->lastInsertID(); + } + + /** + * Update a library. + * + * @param int $libID + * @access public + * @return void + */ + public function updateLib($libID) + { + $libID = (int)$libID; + $oldLib = $this->getLibById($libID); + $lib = fixer::input('post')->stripTags('name')->get(); + $this->dao->update(TABLE_DOCLIB) + ->data($lib) + ->autoCheck() + ->batchCheck('name', 'notempty') + ->check('name', 'unique', "id != $libID") + ->where('id')->eq($libID) + ->exec(); + if(!dao::isError()) return common::createChanges($oldLib, $lib); + } + + /** + * Get docs. + * + * @param int|string $libID + * @param int $productID + * @param int $projectID + * @param int $module + * @param string $orderBy + * @param object $pager + * @access public + * @return void + */ + public function getDocs($libID, $productID, $projectID, $module, $orderBy, $pager) + { + $products = $this->loadModel('product')->getPairs(); + $projects = $this->loadModel('project')->getPairs(); + $keysOfProducts = array_keys($products); + $keysOfProjects = array_keys($projects); + $allKeysOfProjects = $keysOfProjects; + $allKeysOfProjects[] = 0; + + return $this->dao->select('*')->from(TABLE_DOC) + ->where('deleted')->eq(0) + ->beginIF(is_numeric($libID))->andWhere('lib')->eq($libID)->fi() + ->beginIF($libID == 'product')->andWhere('product')->in($keysOfProducts)->andWhere('project')->in($allKeysOfProjects)->fi() + ->beginIF($libID == 'project')->andWhere('project')->in($keysOfProjects)->fi() + ->beginIF($productID > 0)->andWhere('product')->eq($productID)->fi() + ->beginIF($projectID > 0)->andWhere('project')->eq($projectID)->fi() + ->beginIF((string)$projectID == 'int')->andWhere('project')->gt(0)->fi() + ->beginIF($module)->andWhere('module')->in($module)->fi() + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * Get doc info by id. + * + * @param int $docID + * @access public + * @return void + */ + public function getById($docID) + { + $doc = $this->dao->select('*') + ->from(TABLE_DOC) + ->where('id')->eq((int)$docID) + ->fetch(); + if(!$doc) return false; + $doc->content = $this->loadModel('file')->setImgSize($doc->content); + $doc->files = $this->loadModel('file')->getByObject('doc', $docID); + + $doc->libName = ''; + $doc->productName = ''; + $doc->projectName = ''; + $doc->moduleName = ''; + if($doc->lib) $doc->libName = $this->dao->findByID($doc->lib)->from(TABLE_DOCLIB)->fetch('name'); + if($doc->product) $doc->productName = $this->dao->findByID($doc->product)->from(TABLE_PRODUCT)->fetch('name'); + if($doc->project) $doc->projectName = $this->dao->findByID($doc->project)->from(TABLE_PROJECT)->fetch('name'); + if($doc->module) $doc->moduleName = $this->dao->findByID($doc->module)->from(TABLE_MODULE)->fetch('name'); + return $doc; + } + + /** + * Create a doc. + * + * @access public + * @return void + */ + public function create() + { + $now = helper::now(); + $doc = fixer::input('post') + ->add('addedBy', $this->app->user->account) + ->add('addedDate', $now) + ->setDefault('product, project, module', 0) + ->specialChars('title, digest, keywords') + ->encodeURL('url') + ->cleanInt('product, project, module') + ->remove('files, labels') + ->get(); + $condition = "lib = '$doc->lib' AND module = $doc->module"; + $this->dao->insert(TABLE_DOC) + ->data($doc) + ->autoCheck() + ->batchCheck($this->config->doc->create->requiredFields, 'notempty') + ->check('title', 'unique', $condition) + ->exec(); + if(!dao::isError()) + { + $docID = $this->dao->lastInsertID(); + $this->loadModel('file')->saveUpload('doc', $docID); + return $docID; + } + return false; + } + + /** + * Update a doc. + * + * @param int $docID + * @access public + * @return void + */ + public function update($docID) + { + $oldDoc = $this->getById($docID); + $now = helper::now(); + $doc = fixer::input('post') + ->cleanInt('module') + ->setDefault('module', 0) + ->specialChars('title, digest, keywords') + ->encodeURL('url') + ->remove('comment,files, labels') + ->add('editedBy', $this->app->user->account) + ->add('editedDate', $now) + ->get(); + + $condition = "lib = '$doc->lib' AND module = $doc->module AND id != $docID"; + $this->dao->update(TABLE_DOC)->data($doc) + ->autoCheck() + ->batchCheck($this->config->doc->edit->requiredFields, 'notempty') + ->check('title', 'unique', $condition) + ->where('id')->eq((int)$docID) + ->exec(); + if(!dao::isError()) return common::createChanges($oldDoc, $doc); + } + + /** + * Get docs of a product. + * + * @param int $productID + * @access public + * @return array + */ + public function getProductDocs($productID) + { + return $this->dao->select('t1.*, t2.name as module') + ->from(TABLE_DOC)->alias('t1') + ->leftjoin(TABLE_MODULE)->alias('t2')->on('t1.module = t2.id') + ->where('t1.product')->eq($productID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('t1.id_desc') + ->fetchAll(); + } + + /** + * Get docs of a project. + * + * @param int $projectID + * @access public + * @return array + */ + public function getProjectDocs($projectID) + { + return $this->dao->findByProject($projectID)->from(TABLE_DOC)->andWhere('deleted')->eq(0)->orderBy('id_desc')->fetchAll(); + } + + /** + * Get pairs of product modules. + * + * @access public + * @return array + */ + public function getProductModulePairs() + { + return $this->dao->findByType('productdoc')->from(TABLE_MODULE)->fetchPairs('id', 'name'); + } + + /** + * Get pairs of project modules. + * + * @access public + * @return array + */ + public function getProjectModulePairs() + { + return $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->andWhere('type')->eq('projectdoc')->fetchPairs('id', 'name'); + } +} diff --git a/module/doc/view/browse.html.php b/module/doc/view/browse.html.php index 8ba47bf750..edb2542029 100644 --- a/module/doc/view/browse.html.php +++ b/module/doc/view/browse.html.php @@ -1,82 +1,82 @@ - - * @package lib - * @version $Id: browse.html.php 958 2010-07-22 08:09:42Z wwccss $ - * @link http://www.zentao.net - */ -?> - - - - -
      - -
      - doc->create);?> -
      -
      -
      '>
      - - - - - - - -
      -
      -
      - -
      - tree->docManage);?> -
      -
      -
      - - - - recTotal}&recPerPage={$pager->recPerPage}";?> - - - - - - - - - - $doc):?> - createLink('doc', 'view', "docID=$doc->id"); - $canView = common::hasPriv('doc', 'view'); - ?> - - - - - - - - - - - -
      idAB);?>doc->title);?>doc->type);?>doc->addedBy);?>doc->addedDate);?>actions;?>
      id)); else printf('%03d', $doc->id);?>title);?>doc->types[$doc->type];?>addedBy]) ? print($users[$doc->addedBy]) : print($doc->addedBy);?>addedDate));?> - id}"; - if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; - if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; - ?> -
      show();?>
      -
      - + + * @package lib + * @version $Id: browse.html.php 958 2010-07-22 08:09:42Z wwccss $ + * @link http://www.zentao.net + */ +?> + + + + +
      + +
      + doc->create);?> +
      +
      +
      '>
      + + + + + + + +
      +
      +
      + +
      + tree->docManage);?> +
      +
      +
      + + + + recTotal}&recPerPage={$pager->recPerPage}";?> + + + + + + + + + + $doc):?> + createLink('doc', 'view', "docID=$doc->id"); + $canView = common::hasPriv('doc', 'view'); + ?> + + + + + + + + + + + +
      idAB);?>doc->title);?>doc->type);?>doc->addedBy);?>doc->addedDate);?>actions;?>
      id)); else printf('%03d', $doc->id);?>title);?>doc->types[$doc->type];?>addedBy]) ? print($users[$doc->addedBy]) : print($doc->addedBy);?>addedDate));?> + id}"; + if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; + if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; + ?> +
      show();?>
      +
      + diff --git a/module/doc/view/create.html.php b/module/doc/view/create.html.php index 1643fe9e71..4d47319629 100644 --- a/module/doc/view/create.html.php +++ b/module/doc/view/create.html.php @@ -1,70 +1,70 @@ - - * @package doc - * @version $Id: create.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      doc->create;?>
      doc->product;?>
      doc->project;?>
      doc->product;?>
      doc->module;?>
      doc->type;?>doc->types, 'file', "onclick=setType(this.value)");?>
      doc->title;?>
      doc->keywords;?>
      doc->digest;?>
      doc->files;?>fetch('file', 'buildform', 'fileCount=2');?>
      -
      - + + * @package doc + * @version $Id: create.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      doc->create;?>
      doc->product;?>
      doc->project;?>
      doc->product;?>
      doc->module;?>
      doc->type;?>doc->types, 'file', "onclick=setType(this.value)");?>
      doc->title;?>
      doc->keywords;?>
      doc->digest;?>
      doc->files;?>fetch('file', 'buildform', 'fileCount=2');?>
      +
      + diff --git a/module/doc/view/createlib.html.php b/module/doc/view/createlib.html.php index 06ba25e5a9..ca0cd3b918 100644 --- a/module/doc/view/createlib.html.php +++ b/module/doc/view/createlib.html.php @@ -1,26 +1,26 @@ - - * @package doc - * @version $Id: createlib.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
      - - - - - - - - - -
      doc->createLib;?>
      doc->libName;?>
      -
      - + + * @package doc + * @version $Id: createlib.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
      + + + + + + + + + +
      doc->createLib;?>
      doc->libName;?>
      +
      + diff --git a/module/doc/view/edit.html.php b/module/doc/view/edit.html.php index 6bcfac2e3b..75bbfd050b 100644 --- a/module/doc/view/edit.html.php +++ b/module/doc/view/edit.html.php @@ -1,68 +1,68 @@ - - * @package doc - * @version $Id: edit.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - - -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      doc->edit;?>
      doc->module;?>module, "class='select-3'");?>
      doc->type;?>doc->types[$doc->type];?>
      doc->title;?>title, "class='text-1'");?>
      doc->keywords;?>keywords, "class='text-1'");?>
      doc->digest;?>digest, "class='text-1' rows=3");?>
      doc->comment;?>
      - - product) . html::hidden('project', $doc->project);?> -
      -
      - + + * @package doc + * @version $Id: edit.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      doc->edit;?>
      doc->module;?>module, "class='select-3'");?>
      doc->type;?>doc->types[$doc->type];?>
      doc->title;?>title, "class='text-1'");?>
      doc->keywords;?>keywords, "class='text-1'");?>
      doc->digest;?>digest, "class='text-1' rows=3");?>
      doc->comment;?>
      + + product) . html::hidden('project', $doc->project);?> +
      +
      + diff --git a/module/doc/view/editlib.html.php b/module/doc/view/editlib.html.php index 573ed8402f..160f3f0a1b 100644 --- a/module/doc/view/editlib.html.php +++ b/module/doc/view/editlib.html.php @@ -1,28 +1,28 @@ - - * @package doc - * @version $Id: editlib.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - -

      doc->errorEditSystemDoc;?>

      - -
      - - - - - - - -
      doc->editLib;?>
      doc->libName;?>
      -
      - - + + * @package doc + * @version $Id: editlib.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + +

      doc->errorEditSystemDoc;?>

      + +
      + + + + + + + +
      doc->editLib;?>
      doc->libName;?>
      +
      + + diff --git a/module/doc/view/view.html.php b/module/doc/view/view.html.php index e067419be2..a92b88dff1 100644 --- a/module/doc/view/view.html.php +++ b/module/doc/view/view.html.php @@ -1,75 +1,75 @@ - - * @package doc - * @version $Id: view.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      title . $lang->colon . $lang->doc->view;?>
      doc->title;?>deleted) echo "class='deleted'";?>>title;?>
      doc->lib;?>
      doc->module;?>moduleName;?>
      doc->type;?>doc->types[$doc->type];?>
      doc->title;?>title;?>
      doc->keywords;?>keywords;?>
      doc->digest;?>digest);?>
      -
      - session->docList ? $this->session->docList : inlink('browse'); - if(!$doc->deleted) - { - common::printLink('doc', 'edit', "docID=$doc->id", $lang->edit); - common::printLink('doc', 'delete', "docID=$doc->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
      - - + + * @package doc + * @version $Id: view.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      title . $lang->colon . $lang->doc->view;?>
      doc->title;?>deleted) echo "class='deleted'";?>>title;?>
      doc->lib;?>
      doc->module;?>moduleName;?>
      doc->type;?>doc->types[$doc->type];?>
      doc->title;?>title;?>
      doc->keywords;?>keywords;?>
      doc->digest;?>digest);?>
      +
      + session->docList ? $this->session->docList : inlink('browse'); + if(!$doc->deleted) + { + common::printLink('doc', 'edit', "docID=$doc->id", $lang->edit); + common::printLink('doc', 'delete', "docID=$doc->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
      + + diff --git a/module/editor/control.php b/module/editor/control.php index a636d86c9f..c87c7070f6 100644 --- a/module/editor/control.php +++ b/module/editor/control.php @@ -1,164 +1,164 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -class editor extends control -{ - /** - * Show module files and edit them. - * - * @access public - * @return void - */ - public function index() - { - $this->view->moduleList = $this->editor->getModules(); - $this->display(); - } - - /** - * Show this module of files. - * - * @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($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 = '') - { - if($filePath and $_POST) - { - $filePath = helper::safe64Decode($filePath); - 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)); - - } -} - + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +class editor extends control +{ + /** + * Show module files and edit them. + * + * @access public + * @return void + */ + public function index() + { + $this->view->moduleList = $this->editor->getModules(); + $this->display(); + } + + /** + * Show this module of files. + * + * @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($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 = '') + { + if($filePath and $_POST) + { + $filePath = helper::safe64Decode($filePath); + 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/model.php b/module/editor/model.php index da1effae7b..838b725124 100644 --- a/module/editor/model.php +++ b/module/editor/model.php @@ -1,561 +1,561 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -class editorModel extends model -{ - private $pathFix = DIRECTORY_SEPARATOR; - - /** - * 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') . '
      • '; - } - $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 . $this->pathFix . $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'; - foreach(glob($moduleFullFile . $this->pathFix . "*.$ext") 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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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, $this->pathFix . 'module' . $this->pathFix); - $class = substr($class, 0, strpos($class, $this->pathFix, 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 . $this->pathFix . $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 ? "
        \n" : "
          \n"; - if($isRoot) - { - $langFile = dirname(key($files)) . $this->pathFix . 'lang' . $this->pathFix . $this->cookie->lang. '.php'; - if(file_exists($langFile)) include_once $langFile; - $module = basename(dirname(key($files))); - if(isset($lang->$module)) - { - $this->module = $lang->$module; - } - elseif(isset($this->lang->$module)) - { - $this->module = $this->lang->$module; - } - else - { - $this->module = ''; - } - } - foreach($files as $key => $file) - { - $tree .= "
        • \n"; - if(is_array($file)) - { - $tree .= $this->addLink4Dir($key); - $tree .= $this->printTree($file, false); - } - else - { - $tree .= $this->addLink4File($key, $file); - } - $tree .= "
        • \n"; - } - $tree .= "
        \n"; - return $tree; - } - - /** - * Add link for directory or has children grade - * - * @param string $filePath - * @access public - * @return string - */ - public function addLink4Dir($filePath) - { - $tree = ''; - $fileName = basename($filePath); - if(isset($this->lang->editor->modules[$fileName])) - { - $file = "" . $this->lang->editor->modules[$fileName] . ''; - } - elseif(isset($this->lang->editor->translate[$fileName])) - { - $file = "" . $this->lang->editor->translate[$fileName] . ''; - } - else - { - $file = "$fileName"; - } - if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false) - { - switch($fileName) - { - case 'lang': $tree .= $file; break; - case 'js': $tree .= "$file " . html::a($this->getExtendLink($filePath, "newJS"), $this->lang->editor->newExtend, 'editWin'); break; - case 'css': $tree .= "$file " . html::a($this->getExtendLink($filePath, "newCSS"), $this->lang->editor->newExtend, 'editWin'); break; - default: $tree .= "$file " . html::a($this->getExtendLink($filePath, "newExtend"), $this->lang->editor->newExtend, 'editWin'); - } - } - elseif($fileName == 'model.php') - { - $tree .= "$file " . html::a($this->getExtendLink($filePath, 'newMethod'), $this->lang->editor->newMethod, 'editWin'); - } - elseif($fileName == 'control.php') - { - $tree .= "$file " . html::a(inlink('newPage', "filePath=" . helper::safe64Encode($filePath)), $this->lang->editor->newPage, 'editWin'); - } - else - { - $tree .= $file; - } - return $tree; - } - - /** - * Add link for file - * - * @param string $filePath - * @param string $file - * @access public - * @return string - */ - public function addLink4File($filePath, $file) - { - $tree = ''; - if(isset($this->module->$file) and !is_object($this->module->$file) and !is_array($this->module->$file)) - { - $file = "" . $this->module->$file . ''; - } - elseif(isset($this->lang->editor->translate[$file])) - { - if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false and $file == 'config.php') - { - $file = "$file"; - } - else - { - $file = "" . $this->lang->editor->translate[$file] . ''; - } - } - else - { - $file = "$file"; - } - if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false) - { - $tree .= "$file " . html::a($this->getExtendLink($filePath, "edit"), $this->lang->edit, 'editWin'); - $tree .= html::a(inlink('delete', 'path=' . helper::safe64Encode($filePath)), $this->lang->delete, 'hiddenwin') . "\n"; - } - elseif(basename(dirname($filePath))== 'view') - { - $tree .= "$file " . html::a($this->getExtendLink($filePath, "override"), $this->lang->editor->override, 'editWin'); - $tree .= html::a($this->getExtendLink($filePath, "newHook"), $this->lang->editor->newHook, 'editWin') . "\n"; - } - else - { - $parentDir = basename(dirname($filePath)); - $action = 'extendOther'; - if($parentDir == 'control.php') $action = 'extendControl'; - if($parentDir == 'model.php') $action = 'extendModel'; - $tree .= "$file " . html::a($this->getExtendLink($filePath, $action), $this->lang->editor->extend, 'editWin'); - if($parentDir == 'lang') $tree .= html::a($this->getExtendLink($filePath, "new" . str_replace('-', '_', basename($filePath, '.php'))), $this->lang->editor->newLang, 'editWin'); - if(basename($filePath) == 'config.php') $tree .= html::a($this->getExtendLink($filePath, "newConfig"), $this->lang->editor->newConfig, 'editWin'); - } - return $tree; - } - - /** - * Get extend link - * - * @param string $filePath - * @param string $action - * @param string $isExtends - * @access public - * @return string - */ - public function getExtendLink($filePath, $action, $isExtends = '') - { - return inlink('edit', "filePath=" . helper::safe64Encode($filePath) . "&action=$action&isExtends=$isExtends"); - } - - /** - * Save file to extension. - * - * @param string $filePath - * @access public - * @return void - */ - public function save($filePath) - { - $fileContent = $this->post->fileContent; - if(get_magic_quotes_gpc()) $fileContent = stripslashes($fileContent); - $dirPath = dirname($filePath); - $extFilePath = substr($filePath, 0, strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) + 4); - if(!is_dir($dirPath) and is_writable($extFilePath)) mkdir($dirPath, 0777, true); - if(is_writable($dirPath)) - { - file_put_contents($filePath, $fileContent); - } - else - { - die(js::alert($this->lang->editor->notWritable . $extFilePath)); - } - } - - /** - * Extend model.php and get file content. - * - * @param string $filePath - * @access public - * @return string - */ - public function extendModel($filePath) - { - $className = basename(dirname(dirname($filePath))); - if(!class_exists($className)) include(dirname($filePath)); - $methodName = basename($filePath); - $methodParam = $this->getParam($className, $methodName, 'Model'); - return $fileContent = <<getParam($className, $methodName); - return $fileContent = <<getMethodCode($className, $methodName); - return $fileContent = <<pathFix . 'module' . $this->pathFix); - $className = substr($className, 0, strpos($className, $this->pathFix, 9)); - $className = basename($className); - $methodName = basename($filePath, '.php'); - return $fileContent = <<getParameters() as $param) - { - $methodParam .= '$' . $param->getName(); - if($param->isOptional()) - { - $defaultParam = $param->getDefaultValue(); - if(is_string($defaultParam)) $methodParam .= "='$defaultParam', "; - else $methodParam .= "=$defaultParam, "; - } - else - { - $methodParam .= ', '; - } - } - $methodParam = rtrim($methodParam, ', '); - return $methodParam; - } - - /** - * Get method code. - * - * @param string $className - * @param string $methodName - * @param string $ext value may be Model - * @access public - * @return string - */ - public function getMethodCode($className, $methodName, $ext = '') - { - $method = new ReflectionMethod($className . $ext, $methodName); - $fileName = $method->getFileName(); - $startLine = $method->getStartLine(); - $endLine = $method->getEndLine(); - $file = file($fileName); - $code = ''; - for($i = $startLine - 1; $i <= $endLine; $i++) - { - $code .= $file[$i]; - } - return $code; - } - - /** - * Get save path. - * - * @param string $filePath - * @param string $action - * @access public - * @return string - */ - public function getSavePath($filePath, $action) - { - $fileName = empty($_POST['fileName']) ? '' : trim($this->post->fileName); - $moduleName = strstr($filePath, $this->pathFix . 'module' . $this->pathFix); - $moduleName = substr($moduleName, 0, strpos($moduleName, $this->pathFix, 9)); - $moduleName = basename($moduleName); - $extPath = $this->app->getModuleRoot() . $moduleName . $this->pathFix . 'ext' . $this->pathFix; - switch($action) - { - case 'extendModel': - $fileName = empty($fileName) ? strtolower(basename($filePath)) . '.php' : $fileName; - return $extPath . 'model' . $this->pathFix . $fileName; - case 'extendControl': - $fileName = strtolower(basename($filePath)) . '.php'; - return $extPath . 'control' . $this->pathFix . $fileName; - case 'override': - $fileName = basename($filePath); - return $extPath . 'view' . $this->pathFix . $fileName; - case 'extendOther': - $editName = basename($filePath); - $fileName = empty($fileName) ? $editName: $fileName; - if($editName == 'config.php') return $extPath . 'config' .$this->pathFix . $fileName; - elseif(strpos($editName, '.php') !== false) return $extPath . 'lang' . $this->pathFix . str_replace('.php', '', $editName) . $this->pathFix . $fileName; - else return $extPath . substr($editName, strrpos($editName, '.') + 1) . $this->pathFix . substr($editName, 0, strrpos($editName, '.')) . $this->pathFix . $fileName; - default: - if(empty($fileName)) die(js::error($this->lang->editor->emptyFileName)); - $action = strtolower(str_replace('new', '', $action)); - if($action == 'hook') return $extPath . 'view' . $this->pathFix . $fileName; - elseif($action == 'method') return $extPath . basename($filePath, '.php') . $this->pathFix . $fileName; - elseif($action == 'extend') return $filePath . $this->pathFix . $fileName; - elseif($action == 'config') return $extPath . 'config' . $this->pathFix . $fileName; - elseif($action == 'js') return $extPath . 'js' . $this->pathFix . substr($fileName, 0, strrpos($fileName, '.')) . $this->pathFix . $fileName; - elseif($action == 'css') return $extPath . 'css' . $this->pathFix . substr($fileName, 0, strrpos($fileName, '.')) . $this->pathFix . $fileName; - else return $extPath . 'lang' . $this->pathFix . str_replace('_', '-', $action) . $this->pathFix . $fileName; - } - } -} + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +class editorModel extends model +{ + private $pathFix = DIRECTORY_SEPARATOR; + + /** + * 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') . '
        • '; + } + $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 . $this->pathFix . $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'; + foreach(glob($moduleFullFile . $this->pathFix . "*.$ext") 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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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 . $this->pathFix . $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, $this->pathFix . 'module' . $this->pathFix); + $class = substr($class, 0, strpos($class, $this->pathFix, 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 . $this->pathFix . $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 ? "
          \n" : "
            \n"; + if($isRoot) + { + $langFile = dirname(key($files)) . $this->pathFix . 'lang' . $this->pathFix . $this->cookie->lang. '.php'; + if(file_exists($langFile)) include_once $langFile; + $module = basename(dirname(key($files))); + if(isset($lang->$module)) + { + $this->module = $lang->$module; + } + elseif(isset($this->lang->$module)) + { + $this->module = $this->lang->$module; + } + else + { + $this->module = ''; + } + } + foreach($files as $key => $file) + { + $tree .= "
          • \n"; + if(is_array($file)) + { + $tree .= $this->addLink4Dir($key); + $tree .= $this->printTree($file, false); + } + else + { + $tree .= $this->addLink4File($key, $file); + } + $tree .= "
          • \n"; + } + $tree .= "
          \n"; + return $tree; + } + + /** + * Add link for directory or has children grade + * + * @param string $filePath + * @access public + * @return string + */ + public function addLink4Dir($filePath) + { + $tree = ''; + $fileName = basename($filePath); + if(isset($this->lang->editor->modules[$fileName])) + { + $file = "" . $this->lang->editor->modules[$fileName] . ''; + } + elseif(isset($this->lang->editor->translate[$fileName])) + { + $file = "" . $this->lang->editor->translate[$fileName] . ''; + } + else + { + $file = "$fileName"; + } + if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false) + { + switch($fileName) + { + case 'lang': $tree .= $file; break; + case 'js': $tree .= "$file " . html::a($this->getExtendLink($filePath, "newJS"), $this->lang->editor->newExtend, 'editWin'); break; + case 'css': $tree .= "$file " . html::a($this->getExtendLink($filePath, "newCSS"), $this->lang->editor->newExtend, 'editWin'); break; + default: $tree .= "$file " . html::a($this->getExtendLink($filePath, "newExtend"), $this->lang->editor->newExtend, 'editWin'); + } + } + elseif($fileName == 'model.php') + { + $tree .= "$file " . html::a($this->getExtendLink($filePath, 'newMethod'), $this->lang->editor->newMethod, 'editWin'); + } + elseif($fileName == 'control.php') + { + $tree .= "$file " . html::a(inlink('newPage', "filePath=" . helper::safe64Encode($filePath)), $this->lang->editor->newPage, 'editWin'); + } + else + { + $tree .= $file; + } + return $tree; + } + + /** + * Add link for file + * + * @param string $filePath + * @param string $file + * @access public + * @return string + */ + public function addLink4File($filePath, $file) + { + $tree = ''; + if(isset($this->module->$file) and !is_object($this->module->$file) and !is_array($this->module->$file)) + { + $file = "" . $this->module->$file . ''; + } + elseif(isset($this->lang->editor->translate[$file])) + { + if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false and $file == 'config.php') + { + $file = "$file"; + } + else + { + $file = "" . $this->lang->editor->translate[$file] . ''; + } + } + else + { + $file = "$file"; + } + if(strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) !== false) + { + $tree .= "$file " . html::a($this->getExtendLink($filePath, "edit"), $this->lang->edit, 'editWin'); + $tree .= html::a(inlink('delete', 'path=' . helper::safe64Encode($filePath)), $this->lang->delete, 'hiddenwin') . "\n"; + } + elseif(basename(dirname($filePath))== 'view') + { + $tree .= "$file " . html::a($this->getExtendLink($filePath, "override"), $this->lang->editor->override, 'editWin'); + $tree .= html::a($this->getExtendLink($filePath, "newHook"), $this->lang->editor->newHook, 'editWin') . "\n"; + } + else + { + $parentDir = basename(dirname($filePath)); + $action = 'extendOther'; + if($parentDir == 'control.php') $action = 'extendControl'; + if($parentDir == 'model.php') $action = 'extendModel'; + $tree .= "$file " . html::a($this->getExtendLink($filePath, $action), $this->lang->editor->extend, 'editWin'); + if($parentDir == 'lang') $tree .= html::a($this->getExtendLink($filePath, "new" . str_replace('-', '_', basename($filePath, '.php'))), $this->lang->editor->newLang, 'editWin'); + if(basename($filePath) == 'config.php') $tree .= html::a($this->getExtendLink($filePath, "newConfig"), $this->lang->editor->newConfig, 'editWin'); + } + return $tree; + } + + /** + * Get extend link + * + * @param string $filePath + * @param string $action + * @param string $isExtends + * @access public + * @return string + */ + public function getExtendLink($filePath, $action, $isExtends = '') + { + return inlink('edit', "filePath=" . helper::safe64Encode($filePath) . "&action=$action&isExtends=$isExtends"); + } + + /** + * Save file to extension. + * + * @param string $filePath + * @access public + * @return void + */ + public function save($filePath) + { + $fileContent = $this->post->fileContent; + if(get_magic_quotes_gpc()) $fileContent = stripslashes($fileContent); + $dirPath = dirname($filePath); + $extFilePath = substr($filePath, 0, strpos($filePath, $this->pathFix . 'ext' . $this->pathFix) + 4); + if(!is_dir($dirPath) and is_writable($extFilePath)) mkdir($dirPath, 0777, true); + if(is_writable($dirPath)) + { + file_put_contents($filePath, $fileContent); + } + else + { + die(js::alert($this->lang->editor->notWritable . $extFilePath)); + } + } + + /** + * Extend model.php and get file content. + * + * @param string $filePath + * @access public + * @return string + */ + public function extendModel($filePath) + { + $className = basename(dirname(dirname($filePath))); + if(!class_exists($className)) include(dirname($filePath)); + $methodName = basename($filePath); + $methodParam = $this->getParam($className, $methodName, 'Model'); + return $fileContent = <<getParam($className, $methodName); + return $fileContent = <<getMethodCode($className, $methodName); + return $fileContent = <<pathFix . 'module' . $this->pathFix); + $className = substr($className, 0, strpos($className, $this->pathFix, 9)); + $className = basename($className); + $methodName = basename($filePath, '.php'); + return $fileContent = <<getParameters() as $param) + { + $methodParam .= '$' . $param->getName(); + if($param->isOptional()) + { + $defaultParam = $param->getDefaultValue(); + if(is_string($defaultParam)) $methodParam .= "='$defaultParam', "; + else $methodParam .= "=$defaultParam, "; + } + else + { + $methodParam .= ', '; + } + } + $methodParam = rtrim($methodParam, ', '); + return $methodParam; + } + + /** + * Get method code. + * + * @param string $className + * @param string $methodName + * @param string $ext value may be Model + * @access public + * @return string + */ + public function getMethodCode($className, $methodName, $ext = '') + { + $method = new ReflectionMethod($className . $ext, $methodName); + $fileName = $method->getFileName(); + $startLine = $method->getStartLine(); + $endLine = $method->getEndLine(); + $file = file($fileName); + $code = ''; + for($i = $startLine - 1; $i <= $endLine; $i++) + { + $code .= $file[$i]; + } + return $code; + } + + /** + * Get save path. + * + * @param string $filePath + * @param string $action + * @access public + * @return string + */ + public function getSavePath($filePath, $action) + { + $fileName = empty($_POST['fileName']) ? '' : trim($this->post->fileName); + $moduleName = strstr($filePath, $this->pathFix . 'module' . $this->pathFix); + $moduleName = substr($moduleName, 0, strpos($moduleName, $this->pathFix, 9)); + $moduleName = basename($moduleName); + $extPath = $this->app->getModuleRoot() . $moduleName . $this->pathFix . 'ext' . $this->pathFix; + switch($action) + { + case 'extendModel': + $fileName = empty($fileName) ? strtolower(basename($filePath)) . '.php' : $fileName; + return $extPath . 'model' . $this->pathFix . $fileName; + case 'extendControl': + $fileName = strtolower(basename($filePath)) . '.php'; + return $extPath . 'control' . $this->pathFix . $fileName; + case 'override': + $fileName = basename($filePath); + return $extPath . 'view' . $this->pathFix . $fileName; + case 'extendOther': + $editName = basename($filePath); + $fileName = empty($fileName) ? $editName: $fileName; + if($editName == 'config.php') return $extPath . 'config' .$this->pathFix . $fileName; + elseif(strpos($editName, '.php') !== false) return $extPath . 'lang' . $this->pathFix . str_replace('.php', '', $editName) . $this->pathFix . $fileName; + else return $extPath . substr($editName, strrpos($editName, '.') + 1) . $this->pathFix . substr($editName, 0, strrpos($editName, '.')) . $this->pathFix . $fileName; + default: + if(empty($fileName)) die(js::error($this->lang->editor->emptyFileName)); + $action = strtolower(str_replace('new', '', $action)); + if($action == 'hook') return $extPath . 'view' . $this->pathFix . $fileName; + elseif($action == 'method') return $extPath . basename($filePath, '.php') . $this->pathFix . $fileName; + elseif($action == 'extend') return $filePath . $this->pathFix . $fileName; + elseif($action == 'config') return $extPath . 'config' . $this->pathFix . $fileName; + elseif($action == 'js') return $extPath . 'js' . $this->pathFix . substr($fileName, 0, strrpos($fileName, '.')) . $this->pathFix . $fileName; + elseif($action == 'css') return $extPath . 'css' . $this->pathFix . substr($fileName, 0, strrpos($fileName, '.')) . $this->pathFix . $fileName; + else return $extPath . 'lang' . $this->pathFix . str_replace('_', '-', $action) . $this->pathFix . $fileName; + } + } +} diff --git a/module/editor/view/edit.html.php b/module/editor/view/edit.html.php index 6680b3ece8..d3cd51937e 100644 --- a/module/editor/view/edit.html.php +++ b/module/editor/view/edit.html.php @@ -1,70 +1,70 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          '> - - - - - - - - - - - - - - - - -
          - {$lang->editor->filePath}"?> - -
          - " . $lang->editor->sourceFile . ''?>
          - -
          - -
          - - " . $lang->editor->fileName . ''?> - - editor->exampleHook; - } - elseif($action and $action == 'extendOther' and strpos(basename($filePath), '.js') !== false or $action == 'newJS') - { - echo $lang->editor->exampleJs; - } - elseif($action and $action == 'extendOther' and strpos(basename($filePath), '.css') !== false or $action == 'newCSS') - { - echo $lang->editor->exampleCss; - } - else - { - echo $lang->editor->examplePHP; - } - ?> - - - - editor->isOverride?> - -
          -
          - + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          '> + + + + + + + + + + + + + + + + +
          + {$lang->editor->filePath}"?> + +
          + " . $lang->editor->sourceFile . ''?>
          + +
          + +
          + + " . $lang->editor->fileName . ''?> + + editor->exampleHook; + } + elseif($action and $action == 'extendOther' and strpos(basename($filePath), '.js') !== false or $action == 'newJS') + { + echo $lang->editor->exampleJs; + } + elseif($action and $action == 'extendOther' and strpos(basename($filePath), '.css') !== false or $action == 'newCSS') + { + echo $lang->editor->exampleCss; + } + else + { + echo $lang->editor->examplePHP; + } + ?> + + + + editor->isOverride?> + +
          +
          + diff --git a/module/editor/view/extend.html.php b/module/editor/view/extend.html.php index 54ff199445..668d34e193 100644 --- a/module/editor/view/extend.html.php +++ b/module/editor/view/extend.html.php @@ -1,29 +1,29 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          editor->modules[$module])? $lang->editor->modules[$module] : $module;?>
          - - - - + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          editor->modules[$module])? $lang->editor->modules[$module] : $module;?>
          + + + + diff --git a/module/editor/view/index.html.php b/module/editor/view/index.html.php index 01118fe16d..6a824817d8 100644 --- a/module/editor/view/index.html.php +++ b/module/editor/view/index.html.php @@ -1,24 +1,24 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          -
          editor->moduleList?>
          -
          -
          - + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          +
          editor->moduleList?>
          +
          +
          + diff --git a/module/editor/view/newpage.html.php b/module/editor/view/newpage.html.php index cf51a84701..66d835762c 100644 --- a/module/editor/view/newpage.html.php +++ b/module/editor/view/newpage.html.php @@ -1,33 +1,33 @@ - - * @package editor - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - -
          editor->newPage?>
          editor->filePath?>
          editor->pageName?> - editor->examplePHP; - ?> -
          -
          - + + * @package editor + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + +
          editor->newPage?>
          editor->filePath?>
          editor->pageName?> + editor->examplePHP; + ?> +
          +
          + diff --git a/module/extension/control.php b/module/extension/control.php index 3573e695a6..e3fe510267 100644 --- a/module/extension/control.php +++ b/module/extension/control.php @@ -1,353 +1,353 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -class extension extends control -{ - /** - * Browse extensions. - * - * @param string $status - * @access public - * @return void - */ - public function browse($status = 'installed') - { - $extensions = $this->extension->getLocalExtensions($status); - $versions = array(); - if($extensions and $status == 'installed') - { - /* Get latest release from remote. */ - $extCodes = helper::safe64Encode(join(',', array_keys($extensions))); - $results = $this->extension->getExtensionsByAPI('bycode', $extCodes, $recTotal = 0, $recPerPage = 1000, $pageID = 1); - if(isset($results->extensions)) - { - $remoteReleases = $results->extensions; - foreach($remoteReleases as $release) - { - if(!isset($extensions[$release->code])) continue; - - $extension = $extensions[$release->code]; - if($extension->version != $release->latestRelease->releaseVersion and $this->extension->checkVersion($release->latestRelease->zentaoVersion)) - { - $extension->upgradeLink = inlink('upgrade', "extension=$release->code&downLink=" . helper::safe64Encode($release->downLink) . "&md5=$release->md5&type=$release->type"); - } - } - } - } - - $this->view->header->title = $this->lang->extension->browse; - $this->view->position[] = $this->lang->extension->browse; - $this->view->tab = $status; - $this->view->extensions = $extensions; - $this->view->versions = $versions; - $this->display(); - } - - /** - * Obtain extensions from the community. - * - * @param string $type - * @param string $param - * @access public - * @return void - */ - public function obtain($type = 'byUpdatedTime', $param = '', $recTotal = 0, $recPerPage = 10, $pageID = 1) - { - /* Init vars. */ - $type = strtolower($type); - $moduleID = $type == 'bymodule' ? (int)$param : 0; - $extensions = array(); - $pager = null; - - /* Set the key. */ - if($type == 'bysearch') $param = helper::safe64Encode($this->post->key); - - /* Get results from the api. */ - $results = $this->extension->getExtensionsByAPI($type, $param, $recTotal, $recPerPage, $pageID); - if($results) - { - $this->app->loadClass('pager', $static = true); - $pager = new pager($results->dbPager->recTotal, $results->dbPager->recPerPage, $results->dbPager->pageID); - $extensions = $results->extensions; - } - - $this->view->moduleTree = $this->extension->getModulesByAPI(); - $this->view->extensions = $extensions; - $this->view->installeds = $this->extension->getLocalExtensions('installed'); - $this->view->pager = $pager; - $this->view->tab = 'obtain'; - $this->view->type = $type; - $this->view->moduleID = $moduleID; - $this->display(); - } - - /** - * Install a extension - * - * @param string $extension - * @param string $downLink - * @param string $md5 - * @param string $type - * @param string $overridePackage - * @param string $ignoreCompatible - * @param string $overrideFile - * @param string $agreeLicense - * @access public - * @return void - */ - public function install($extension, $downLink = '', $md5 = '', $type = '', $overridePackage = 'no', $ignoreCompatible = 'no', $overrideFile = 'no', $agreeLicense = 'no') - { - $this->view->error = ''; - $this->view->header->title = $this->lang->extension->install . $this->lang->colon . $extension; - - /* Get the package file name. */ - $packageFile = $this->extension->getPackageFile($extension); - - if($downLink) - { - /* Checking download path. */ - $return = $this->extension->checkDownloadPath(); - if($return->result != 'ok') - { - $this->view->error = $return->error; - die($this->display()); - } - - /* Check file exists or not. */ - if(file_exists($packageFile) and $overridePackage == 'no') - { - $overrideLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=yes&ignoreCompatible=$ignoreCompatible&overrideFile=$overrideFile&agreeLicense=$agreeLicense"); - $this->view->error = sprintf($this->lang->extension->errorPackageFileExists, $packageFile, $overrideLink); - die($this->display()); - } - - /* Download the package file. */ - $this->extension->downloadPackage($extension, helper::safe64Decode($downLink)); - if(!file_exists($packageFile)) - { - $this->view->error = sprintf($this->lang->extension->errorDownloadFailed, $packageFile); - die($this->display()); - } - elseif($md5 != '' and md5_file($packageFile) != $md5) - { - unlink($packageFile); - $this->view->error = sprintf($this->lang->extension->errorMd5Checking, $packageFile); - die($this->display()); - } - } - - /* Check the package file exists or not. */ - if(!file_exists($packageFile)) - { - $this->view->error = sprintf($this->lang->extension->errorPackageNotFound, $packageFile); - die($this->display()); - } - - /* Checking the extension pathes. */ - $return = $this->extension->checkExtensionPathes($extension); - if($this->session->dirs2Created == false) $this->session->set('dirs2Created', $return->dirs2Created); // Save the dirs to be created. - if($return->result != 'ok') - { - $this->view->error = $return->errors; - die($this->display()); - } - - /* Extract the package. */ - $return = $this->extension->extractPackage($extension); - if($return->result != 'ok') - { - $this->view->error = sprintf($this->lang->extension->errorExtracted, $packageFile, $return->error); - die($this->display()); - } - - /* Check version comptiable. */ - $zentaoVersion = $this->extension->getZentaoVersion($extension); - if(!$this->extension->checkVersion($zentaoVersion) and $ignoreCompatible == 'no') - { - $ignoreLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=yes"); - $returnLink = inlink('obtain'); - $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $ignoreLink, $returnLink); - die($this->display()); - } - - /* Check files in the package conflicts with exists files or not. */ - if($overrideFile == 'no') - { - $return = $this->extension->checkFile($extension); - if($return->result != 'ok') - { - $overrideLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=yes"); - $returnLink = inlink('obtain'); - $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, $returnLink); - die($this->display()); - } - } - - /* Print the license form. */ - if($agreeLicense == 'no') - { - $extensionInfo = $this->extension->getInfoFromPackage($extension); - $license = $this->extension->processLicense($extensionInfo->license); - $agreeLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=$overrideFile&agreeLicense=yes"); - $this->view->license = $license; - $this->view->author = $extensionInfo->author; - $this->view->agreeLink = $agreeLink; - die($this->display()); - } - - /* The preInstall hook file. */ - if($preInstallHook = $this->extension->getHookFile($extension, 'preinstall')) include $preInstallHook; - - /* Save to database. */ - $this->extension->saveExtension($extension, $type); - - /* Copy files to target directory. */ - $this->view->files = $this->extension->copyPackageFiles($extension); - - /* Judge need execute db install or not. */ - $data->status = 'installed'; - $data->dirs = $this->session->dirs2Created; - $data->files = $this->view->files; - $data->installedTime = helper::now(); - $this->session->set('dirs2Created', array()); // clean the session. - - /* Execute the install.sql. */ - if($this->extension->needExecuteDB($extension, 'install')) - { - $return = $this->extension->executeDB($extension, 'install'); - if($return->result != 'ok') - { - $this->view->error = sprintf($this->lang->extension->errorInstallDB, $return->error); - die($this->display()); - } - } - - /* Update status, dirs, files and installed time. */ - $this->extension->updateExtension($extension, $data); - $this->view->downloadedPackage = !empty($downLink); - - /* The postInstall hook file. */ - if($postInstallHook = $this->extension->getHookFile($extension, 'postinstall')) include $postInstallHook; - - $this->display(); - } - - /** - * Uninstall an extension. - * - * @param string $extension - * @access public - * @return void - */ - public function uninstall($extension) - { - if($preUninstallHook = $this->extension->getHookFile($extension, 'preuninstall')) include $preUninstallHook; - - $this->extension->executeDB($extension, 'uninstall'); - $this->extension->updateExtension($extension, array('status' => 'available')); - $this->view->removeCommands = $this->extension->removePackage($extension); - $this->view->header->title = $this->lang->extension->uninstallFinished; - - if($postUninstallHook = $this->extension->getHookFile($extension, 'postuninstall')) include $postUninstallHook; - $this->display(); - } - - /** - * Activate an extension; - * - * @param string $extension - * @access public - * @return void - */ - public function activate($extension, $ignore = 'no') - { - if($ignore == 'no') - { - $return = $this->extension->checkFile($extension); - if($return->result != 'ok') - { - $ignoreLink = inlink('activate', "extension=$extension&ignore=yes"); - $resetLink = inlink('browse', 'type=deactivated'); - $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $ignoreLink, $resetLink); - die($this->display()); - } - } - - $this->extension->copyPackageFiles($extension); - $this->extension->updateExtension($extension, array('status' => 'installed')); - $this->view->header->title = $this->lang->extension->activateFinished; - $this->display(); - } - - /** - * Deactivate an extension - * - * @param string $extension - * @access public - * @return void - */ - public function deactivate($extension) - { - $this->extension->updateExtension($extension, array('status' => 'deactivated')); - $this->view->removeCommands = $this->extension->removePackage($extension); - $this->view->header->title = $this->lang->extension->deactivateFinished; - $this->display(); - } - - /** - * Upload an extension - * - * @access public - * @return void - */ - public function upload() - { - if($_FILES) - { - $tmpName = $_FILES['file']['tmp_name']; - $fileName = $_FILES['file']['name']; - $extension = basename($fileName, '.zip'); - move_uploaded_file($tmpName, $this->app->getTmpRoot() . "/extension/$fileName"); - $this->locate(inlink('install', "extension=$extension")); - } - $this->display(); - } - - /** - * Erase an extension. - * - * @param string $extension - * @access public - * @return void - */ - public function erase($extension) - { - $this->view->removeCommands = $this->extension->erasePackage($extension); - $this->view->header->title = $this->lang->extension->eraseFinished; - $this->display(); - } - - /** - * Update extension. - * - * @param string $extension - * @param string $downLink - * @param string $md5 - * @param string $type - * @access public - * @return void - */ - public function upgrade($extension, $downLink, $md5, $type) - { - $this->extension->removePackage($extension); - $this->locate(inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=no&ignoreCompatible=yes")); - } -} + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +class extension extends control +{ + /** + * Browse extensions. + * + * @param string $status + * @access public + * @return void + */ + public function browse($status = 'installed') + { + $extensions = $this->extension->getLocalExtensions($status); + $versions = array(); + if($extensions and $status == 'installed') + { + /* Get latest release from remote. */ + $extCodes = helper::safe64Encode(join(',', array_keys($extensions))); + $results = $this->extension->getExtensionsByAPI('bycode', $extCodes, $recTotal = 0, $recPerPage = 1000, $pageID = 1); + if(isset($results->extensions)) + { + $remoteReleases = $results->extensions; + foreach($remoteReleases as $release) + { + if(!isset($extensions[$release->code])) continue; + + $extension = $extensions[$release->code]; + if($extension->version != $release->latestRelease->releaseVersion and $this->extension->checkVersion($release->latestRelease->zentaoVersion)) + { + $extension->upgradeLink = inlink('upgrade', "extension=$release->code&downLink=" . helper::safe64Encode($release->downLink) . "&md5=$release->md5&type=$release->type"); + } + } + } + } + + $this->view->header->title = $this->lang->extension->browse; + $this->view->position[] = $this->lang->extension->browse; + $this->view->tab = $status; + $this->view->extensions = $extensions; + $this->view->versions = $versions; + $this->display(); + } + + /** + * Obtain extensions from the community. + * + * @param string $type + * @param string $param + * @access public + * @return void + */ + public function obtain($type = 'byUpdatedTime', $param = '', $recTotal = 0, $recPerPage = 10, $pageID = 1) + { + /* Init vars. */ + $type = strtolower($type); + $moduleID = $type == 'bymodule' ? (int)$param : 0; + $extensions = array(); + $pager = null; + + /* Set the key. */ + if($type == 'bysearch') $param = helper::safe64Encode($this->post->key); + + /* Get results from the api. */ + $results = $this->extension->getExtensionsByAPI($type, $param, $recTotal, $recPerPage, $pageID); + if($results) + { + $this->app->loadClass('pager', $static = true); + $pager = new pager($results->dbPager->recTotal, $results->dbPager->recPerPage, $results->dbPager->pageID); + $extensions = $results->extensions; + } + + $this->view->moduleTree = $this->extension->getModulesByAPI(); + $this->view->extensions = $extensions; + $this->view->installeds = $this->extension->getLocalExtensions('installed'); + $this->view->pager = $pager; + $this->view->tab = 'obtain'; + $this->view->type = $type; + $this->view->moduleID = $moduleID; + $this->display(); + } + + /** + * Install a extension + * + * @param string $extension + * @param string $downLink + * @param string $md5 + * @param string $type + * @param string $overridePackage + * @param string $ignoreCompatible + * @param string $overrideFile + * @param string $agreeLicense + * @access public + * @return void + */ + public function install($extension, $downLink = '', $md5 = '', $type = '', $overridePackage = 'no', $ignoreCompatible = 'no', $overrideFile = 'no', $agreeLicense = 'no') + { + $this->view->error = ''; + $this->view->header->title = $this->lang->extension->install . $this->lang->colon . $extension; + + /* Get the package file name. */ + $packageFile = $this->extension->getPackageFile($extension); + + if($downLink) + { + /* Checking download path. */ + $return = $this->extension->checkDownloadPath(); + if($return->result != 'ok') + { + $this->view->error = $return->error; + die($this->display()); + } + + /* Check file exists or not. */ + if(file_exists($packageFile) and $overridePackage == 'no') + { + $overrideLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=yes&ignoreCompatible=$ignoreCompatible&overrideFile=$overrideFile&agreeLicense=$agreeLicense"); + $this->view->error = sprintf($this->lang->extension->errorPackageFileExists, $packageFile, $overrideLink); + die($this->display()); + } + + /* Download the package file. */ + $this->extension->downloadPackage($extension, helper::safe64Decode($downLink)); + if(!file_exists($packageFile)) + { + $this->view->error = sprintf($this->lang->extension->errorDownloadFailed, $packageFile); + die($this->display()); + } + elseif($md5 != '' and md5_file($packageFile) != $md5) + { + unlink($packageFile); + $this->view->error = sprintf($this->lang->extension->errorMd5Checking, $packageFile); + die($this->display()); + } + } + + /* Check the package file exists or not. */ + if(!file_exists($packageFile)) + { + $this->view->error = sprintf($this->lang->extension->errorPackageNotFound, $packageFile); + die($this->display()); + } + + /* Checking the extension pathes. */ + $return = $this->extension->checkExtensionPathes($extension); + if($this->session->dirs2Created == false) $this->session->set('dirs2Created', $return->dirs2Created); // Save the dirs to be created. + if($return->result != 'ok') + { + $this->view->error = $return->errors; + die($this->display()); + } + + /* Extract the package. */ + $return = $this->extension->extractPackage($extension); + if($return->result != 'ok') + { + $this->view->error = sprintf($this->lang->extension->errorExtracted, $packageFile, $return->error); + die($this->display()); + } + + /* Check version comptiable. */ + $zentaoVersion = $this->extension->getZentaoVersion($extension); + if(!$this->extension->checkVersion($zentaoVersion) and $ignoreCompatible == 'no') + { + $ignoreLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=yes"); + $returnLink = inlink('obtain'); + $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $ignoreLink, $returnLink); + die($this->display()); + } + + /* Check files in the package conflicts with exists files or not. */ + if($overrideFile == 'no') + { + $return = $this->extension->checkFile($extension); + if($return->result != 'ok') + { + $overrideLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=yes"); + $returnLink = inlink('obtain'); + $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, $returnLink); + die($this->display()); + } + } + + /* Print the license form. */ + if($agreeLicense == 'no') + { + $extensionInfo = $this->extension->getInfoFromPackage($extension); + $license = $this->extension->processLicense($extensionInfo->license); + $agreeLink = inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=$overridePackage&ignoreCompatible=$ignoreCompatible&overrideFile=$overrideFile&agreeLicense=yes"); + $this->view->license = $license; + $this->view->author = $extensionInfo->author; + $this->view->agreeLink = $agreeLink; + die($this->display()); + } + + /* The preInstall hook file. */ + if($preInstallHook = $this->extension->getHookFile($extension, 'preinstall')) include $preInstallHook; + + /* Save to database. */ + $this->extension->saveExtension($extension, $type); + + /* Copy files to target directory. */ + $this->view->files = $this->extension->copyPackageFiles($extension); + + /* Judge need execute db install or not. */ + $data->status = 'installed'; + $data->dirs = $this->session->dirs2Created; + $data->files = $this->view->files; + $data->installedTime = helper::now(); + $this->session->set('dirs2Created', array()); // clean the session. + + /* Execute the install.sql. */ + if($this->extension->needExecuteDB($extension, 'install')) + { + $return = $this->extension->executeDB($extension, 'install'); + if($return->result != 'ok') + { + $this->view->error = sprintf($this->lang->extension->errorInstallDB, $return->error); + die($this->display()); + } + } + + /* Update status, dirs, files and installed time. */ + $this->extension->updateExtension($extension, $data); + $this->view->downloadedPackage = !empty($downLink); + + /* The postInstall hook file. */ + if($postInstallHook = $this->extension->getHookFile($extension, 'postinstall')) include $postInstallHook; + + $this->display(); + } + + /** + * Uninstall an extension. + * + * @param string $extension + * @access public + * @return void + */ + public function uninstall($extension) + { + if($preUninstallHook = $this->extension->getHookFile($extension, 'preuninstall')) include $preUninstallHook; + + $this->extension->executeDB($extension, 'uninstall'); + $this->extension->updateExtension($extension, array('status' => 'available')); + $this->view->removeCommands = $this->extension->removePackage($extension); + $this->view->header->title = $this->lang->extension->uninstallFinished; + + if($postUninstallHook = $this->extension->getHookFile($extension, 'postuninstall')) include $postUninstallHook; + $this->display(); + } + + /** + * Activate an extension; + * + * @param string $extension + * @access public + * @return void + */ + public function activate($extension, $ignore = 'no') + { + if($ignore == 'no') + { + $return = $this->extension->checkFile($extension); + if($return->result != 'ok') + { + $ignoreLink = inlink('activate', "extension=$extension&ignore=yes"); + $resetLink = inlink('browse', 'type=deactivated'); + $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $ignoreLink, $resetLink); + die($this->display()); + } + } + + $this->extension->copyPackageFiles($extension); + $this->extension->updateExtension($extension, array('status' => 'installed')); + $this->view->header->title = $this->lang->extension->activateFinished; + $this->display(); + } + + /** + * Deactivate an extension + * + * @param string $extension + * @access public + * @return void + */ + public function deactivate($extension) + { + $this->extension->updateExtension($extension, array('status' => 'deactivated')); + $this->view->removeCommands = $this->extension->removePackage($extension); + $this->view->header->title = $this->lang->extension->deactivateFinished; + $this->display(); + } + + /** + * Upload an extension + * + * @access public + * @return void + */ + public function upload() + { + if($_FILES) + { + $tmpName = $_FILES['file']['tmp_name']; + $fileName = $_FILES['file']['name']; + $extension = basename($fileName, '.zip'); + move_uploaded_file($tmpName, $this->app->getTmpRoot() . "/extension/$fileName"); + $this->locate(inlink('install', "extension=$extension")); + } + $this->display(); + } + + /** + * Erase an extension. + * + * @param string $extension + * @access public + * @return void + */ + public function erase($extension) + { + $this->view->removeCommands = $this->extension->erasePackage($extension); + $this->view->header->title = $this->lang->extension->eraseFinished; + $this->display(); + } + + /** + * Update extension. + * + * @param string $extension + * @param string $downLink + * @param string $md5 + * @param string $type + * @access public + * @return void + */ + public function upgrade($extension, $downLink, $md5, $type) + { + $this->extension->removePackage($extension); + $this->locate(inlink('install', "extension=$extension&downLink=$downLink&md5=$md5&type=$type&overridePackage=no&ignoreCompatible=yes")); + } +} diff --git a/module/extension/lang/en.php b/module/extension/lang/en.php index eeee5e6291..c9f848497e 100644 --- a/module/extension/lang/en.php +++ b/module/extension/lang/en.php @@ -1,93 +1,93 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->extension->common = 'Extension'; -$lang->extension->browse = 'Browse'; -$lang->extension->install = 'Install'; -$lang->extension->installAuto = 'AutoInstall'; -$lang->extension->installForce = 'ForceInstall'; -$lang->extension->uninstall = 'Uninstall'; -$lang->extension->activate = 'Activate'; -$lang->extension->deactivate = 'Deactivate'; -$lang->extension->obtain = 'Obtain'; -$lang->extension->view = 'Info'; -$lang->extension->download = 'Download'; -$lang->extension->downloadAB = 'Down'; -$lang->extension->upload = 'Upload and install'; -$lang->extension->erase = 'Erase'; -$lang->extension->upgrade = 'Upgrade'; -$lang->extension->agreeLicense = 'I agree the license'; - -$lang->extension->installed = 'Installed'; -$lang->extension->deactivated = 'Deactivated'; -$lang->extension->available = 'Downloaded'; - -$lang->extension->id = 'ID'; -$lang->extension->name = 'Name'; -$lang->extension->code = 'Code'; -$lang->extension->version = 'Version'; -$lang->extension->compatible = 'Compatible'; -$lang->extension->latest = 'Latest:%s,need zentao %s'; -$lang->extension->author = 'Author'; -$lang->extension->license = 'License'; -$lang->extension->intro = 'Description'; -$lang->extension->abstract = 'Abstract'; -$lang->extension->site = 'Site'; -$lang->extension->addedTime = 'Added Time'; -$lang->extension->updatedTime = 'Updated Time'; -$lang->extension->downloads = 'Downloads'; -$lang->extension->public = 'Public'; -$lang->extension->compatible = 'Compatible'; -$lang->extension->grade = 'Grade'; - -$lang->extension->publicList[0] = 'Manually'; -$lang->extension->publicList[1] = 'Auto'; - -$lang->extension->compatibleList[0] = 'Unknow'; -$lang->extension->compatibleList[1] = 'Compatible'; - -$lang->extension->byDownloads = 'Downloads'; -$lang->extension->byAddedTime = 'New added'; -$lang->extension->byUpdatedTime = 'Last updated'; -$lang->extension->bySearch = 'Search'; -$lang->extension->byCategory = 'By Category'; - -$lang->extension->installFailed = 'Install failed, the reason is:'; -$lang->extension->installFinished = 'Good, the extension has been installed successfully.'; -$lang->extension->refreshPage = 'Refresh'; -$lang->extension->uninstallFinished = 'Extension has been successfully uninstalled.'; -$lang->extension->deactivateFinished = 'Extension has been successfully deactivated.'; -$lang->extension->activateFinished = 'Extension has been successfully activated.'; -$lang->extension->eraseFinished = 'Extension has been successfully erased.'; -$lang->extension->unremovedFiles = 'There are some unremoved files, you need remove them manually'; -$lang->extension->executeCommands = '

          Execute the following commands to fix them:

          '; -$lang->extension->successDownloadedPackage = 'Successfully downloaded the package file.'; -$lang->extension->successCopiedFiles = 'Successfully copied files. '; -$lang->extension->successInstallDB = 'Successfully installed database.'; -$lang->extension->viewInstalled = 'View installed extensions.'; -$lang->extension->viewAvailable = 'View available extensions'; -$lang->extension->viewDeactivated = 'View deactivated extensions'; - -$lang->extension->errorOccurs = 'Error:'; -$lang->extension->errorGetModules = "Get extensions' categories data from the www.zentao.net failed. "; -$lang->extension->errorGetExtensions = 'Get extensions from www.zentao.net failed. You can visit
          www.zentao.net to find your extensions, download it manually and then upload to zentaopms to install it.'; -$lang->extension->errorDownloadPathNotFound = 'The save path of package file %sdoes not exists.
          For linux users, can execute mkdir -p %s to fix it.'; -$lang->extension->errorDownloadPathNotWritable = 'The save path of package file %sis not writable.
          For linux users, can execute sudo chmod 777 %s to fix it.'; -$lang->extension->errorPackageFileExists = 'There is already a file with the same name %s.

          If you want to install again, please click this link.

          '; -$lang->extension->errorDownloadFailed = 'Download failed, please try again. Or you can download it manually and upload it to install.'; -$lang->extension->errorMd5Checking = 'The downloawd files checking failed, Please download it manually and upload it to install'; -$lang->extension->errorExtracted = 'The package file %s extracted failed. The error is:
          %s'; -$lang->extension->errorCheckIncompatible = 'This extenion is not compatible with current zentao version.

          You can force install or cancel the installation

          .'; -$lang->extension->errorFileConflicted = 'There are some files conflicted:
          %s

          You can Overide them or Cancel the installation

          .'; -$lang->extension->errorPackageNotFound = 'The package file %s not found, perhaps download failed, try again.'; -$lang->extension->errorTargetPathNotWritable = 'Target path %s not writable.'; -$lang->extension->errorTargetPathNotExists = 'Target path %s not exists'; -$lang->extension->errorInstallDB = 'Execute database sql failed, the error is: %s'; + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->extension->common = 'Extension'; +$lang->extension->browse = 'Browse'; +$lang->extension->install = 'Install'; +$lang->extension->installAuto = 'AutoInstall'; +$lang->extension->installForce = 'ForceInstall'; +$lang->extension->uninstall = 'Uninstall'; +$lang->extension->activate = 'Activate'; +$lang->extension->deactivate = 'Deactivate'; +$lang->extension->obtain = 'Obtain'; +$lang->extension->view = 'Info'; +$lang->extension->download = 'Download'; +$lang->extension->downloadAB = 'Down'; +$lang->extension->upload = 'Upload and install'; +$lang->extension->erase = 'Erase'; +$lang->extension->upgrade = 'Upgrade'; +$lang->extension->agreeLicense = 'I agree the license'; + +$lang->extension->installed = 'Installed'; +$lang->extension->deactivated = 'Deactivated'; +$lang->extension->available = 'Downloaded'; + +$lang->extension->id = 'ID'; +$lang->extension->name = 'Name'; +$lang->extension->code = 'Code'; +$lang->extension->version = 'Version'; +$lang->extension->compatible = 'Compatible'; +$lang->extension->latest = 'Latest:%s,need zentao %s'; +$lang->extension->author = 'Author'; +$lang->extension->license = 'License'; +$lang->extension->intro = 'Description'; +$lang->extension->abstract = 'Abstract'; +$lang->extension->site = 'Site'; +$lang->extension->addedTime = 'Added Time'; +$lang->extension->updatedTime = 'Updated Time'; +$lang->extension->downloads = 'Downloads'; +$lang->extension->public = 'Public'; +$lang->extension->compatible = 'Compatible'; +$lang->extension->grade = 'Grade'; + +$lang->extension->publicList[0] = 'Manually'; +$lang->extension->publicList[1] = 'Auto'; + +$lang->extension->compatibleList[0] = 'Unknow'; +$lang->extension->compatibleList[1] = 'Compatible'; + +$lang->extension->byDownloads = 'Downloads'; +$lang->extension->byAddedTime = 'New added'; +$lang->extension->byUpdatedTime = 'Last updated'; +$lang->extension->bySearch = 'Search'; +$lang->extension->byCategory = 'By Category'; + +$lang->extension->installFailed = 'Install failed, the reason is:'; +$lang->extension->installFinished = 'Good, the extension has been installed successfully.'; +$lang->extension->refreshPage = 'Refresh'; +$lang->extension->uninstallFinished = 'Extension has been successfully uninstalled.'; +$lang->extension->deactivateFinished = 'Extension has been successfully deactivated.'; +$lang->extension->activateFinished = 'Extension has been successfully activated.'; +$lang->extension->eraseFinished = 'Extension has been successfully erased.'; +$lang->extension->unremovedFiles = 'There are some unremoved files, you need remove them manually'; +$lang->extension->executeCommands = '

          Execute the following commands to fix them:

          '; +$lang->extension->successDownloadedPackage = 'Successfully downloaded the package file.'; +$lang->extension->successCopiedFiles = 'Successfully copied files. '; +$lang->extension->successInstallDB = 'Successfully installed database.'; +$lang->extension->viewInstalled = 'View installed extensions.'; +$lang->extension->viewAvailable = 'View available extensions'; +$lang->extension->viewDeactivated = 'View deactivated extensions'; + +$lang->extension->errorOccurs = 'Error:'; +$lang->extension->errorGetModules = "Get extensions' categories data from the www.zentao.net failed. "; +$lang->extension->errorGetExtensions = 'Get extensions from www.zentao.net failed. You can visit
          www.zentao.net to find your extensions, download it manually and then upload to zentaopms to install it.'; +$lang->extension->errorDownloadPathNotFound = 'The save path of package file %sdoes not exists.
          For linux users, can execute mkdir -p %s to fix it.'; +$lang->extension->errorDownloadPathNotWritable = 'The save path of package file %sis not writable.
          For linux users, can execute sudo chmod 777 %s to fix it.'; +$lang->extension->errorPackageFileExists = 'There is already a file with the same name %s.

          If you want to install again, please click this link.

          '; +$lang->extension->errorDownloadFailed = 'Download failed, please try again. Or you can download it manually and upload it to install.'; +$lang->extension->errorMd5Checking = 'The downloawd files checking failed, Please download it manually and upload it to install'; +$lang->extension->errorExtracted = 'The package file %s extracted failed. The error is:
          %s'; +$lang->extension->errorCheckIncompatible = 'This extenion is not compatible with current zentao version.

          You can force install or cancel the installation

          .'; +$lang->extension->errorFileConflicted = 'There are some files conflicted:
          %s

          You can Overide them or Cancel the installation

          .'; +$lang->extension->errorPackageNotFound = 'The package file %s not found, perhaps download failed, try again.'; +$lang->extension->errorTargetPathNotWritable = 'Target path %s not writable.'; +$lang->extension->errorTargetPathNotExists = 'Target path %s not exists'; +$lang->extension->errorInstallDB = 'Execute database sql failed, the error is: %s'; diff --git a/module/extension/lang/zh-cn.php b/module/extension/lang/zh-cn.php index caf2f2e88b..d8a2ba735c 100644 --- a/module/extension/lang/zh-cn.php +++ b/module/extension/lang/zh-cn.php @@ -1,93 +1,93 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->extension->common = '插件管理'; -$lang->extension->browse = '浏览插件'; -$lang->extension->install = '安装插件'; -$lang->extension->installAuto = '自动安装'; -$lang->extension->installForce = '强制安装'; -$lang->extension->uninstall = '卸载'; -$lang->extension->activate = '激活'; -$lang->extension->deactivate = '禁用'; -$lang->extension->obtain = '获得插件'; -$lang->extension->view = '详情'; -$lang->extension->download = '下载插件'; -$lang->extension->downloadAB = '下载'; -$lang->extension->upload = '本地安装'; -$lang->extension->erase = '清除'; -$lang->extension->upgrade = '升级'; -$lang->extension->agreeLicense = '我同意该授权'; - -$lang->extension->installed = '已安装'; -$lang->extension->deactivated = '被禁用'; -$lang->extension->available = '已下载'; - -$lang->extension->id = '编号'; -$lang->extension->name = '名称'; -$lang->extension->code = '插件代号'; -$lang->extension->version = '版本'; -$lang->extension->compatible = '适用版本'; -$lang->extension->latest = '最新版本%s,兼容禅道%s'; -$lang->extension->author = '作者'; -$lang->extension->license = '授权'; -$lang->extension->intro = '详情'; -$lang->extension->abstract = '简介'; -$lang->extension->site = '官网'; -$lang->extension->addedTime = '添加时间'; -$lang->extension->updatedTime = '更新时间'; -$lang->extension->downloads = '下载量'; -$lang->extension->public = '下载方式'; -$lang->extension->compatible = '兼容性'; -$lang->extension->grade = '评分'; - -$lang->extension->publicList[0] = '手工下载'; -$lang->extension->publicList[1] = '直接下载'; - -$lang->extension->compatibleList[0] = '未知'; -$lang->extension->compatibleList[1] = '兼容'; - -$lang->extension->byDownloads = '最多下载'; -$lang->extension->byAddedTime = '最新添加'; -$lang->extension->byUpdatedTime = '最近更新'; -$lang->extension->bySearch = '搜索'; -$lang->extension->byCategory = '分类浏览'; - -$lang->extension->installFailed = '安装失败,错误原因如下:'; -$lang->extension->installFinished = '恭喜您,插件顺利的安装成功!'; -$lang->extension->refreshPage = '刷新页面'; -$lang->extension->uninstallFinished = '插件已经成功卸载'; -$lang->extension->deactivateFinished = '插件已经成功禁用'; -$lang->extension->activateFinished = '插件已经成功激活'; -$lang->extension->eraseFinished = '插件已经成功清除'; -$lang->extension->unremovedFiles = '有一些文件或目录未能删除,需要手工删除'; -$lang->extension->executeCommands = '

          执行下面的命令来修正这些问题:

          '; -$lang->extension->successDownloadedPackage = '成功下载插件'; -$lang->extension->successCopiedFiles = '成功拷贝文件'; -$lang->extension->successInstallDB = '成功安装数据库'; -$lang->extension->viewInstalled = '查看已安装插件'; -$lang->extension->viewAvailable = '查看可安装插件'; -$lang->extension->viewDeactivated = '查看已禁用插件'; - -$lang->extension->errorOccurs = '错误:'; -$lang->extension->errorGetModules = '从www.zentao.net获得插件分类失败。可能是因为网络方面的原因,请检查后重新刷新页面。'; -$lang->extension->errorGetExtensions = '从www.zentao.net获得插件失败。可能是因为网络方面的原因,您可以到
          www.zentao.net手工下载插件,然后上传安装。'; -$lang->extension->errorDownloadPathNotFound = '插件下载存储路径%s不存在。
          linux下面请执行命令:mkdir -p %s来修正。'; -$lang->extension->errorDownloadPathNotWritable = '插件下载存储路径%s不可写。
          linux下面请执行命令:sudo chmod 777 %s来修正。'; -$lang->extension->errorPackageFileExists = '下载路径已经有一个名为的%s附件。

          重新安装,请点击此链接

          '; -$lang->extension->errorDownloadFailed = '下载失败,请重新下载。如果多次重试还不行,请尝试手工下载,然后通过上传功能上传。'; -$lang->extension->errorMd5Checking = '下载文件不完整,请重新下载。如果多次重试还不行,请尝试手工下载,然后通过上传功能上传。'; -$lang->extension->errorExtracted = '包文件 %s 解压缩失败,可能不是一个有效的zip文件。错误信息如下:
          %s'; -$lang->extension->errorCheckIncompatible = '该插件与禅道版本不兼容,安装后可能无法使用。。

          您可以选择 强制安装 或者 取消安装

          '; -$lang->extension->errorFileConflicted = '有以下安装文件冲突:
          %s

          您可以选择 覆盖安装 或者 取消安装

          '; -$lang->extension->errorPackageNotFound = '包文件 %s 没有找到,可能是因为自动下载失败。您可以尝试再次下载。'; -$lang->extension->errorTargetPathNotWritable = '目标路径 %s 不可写。'; -$lang->extension->errorTargetPathNotExists = '目标路径 %s 不存在。'; -$lang->extension->errorInstallDB = '执行数据库语句失败。错误信息如下:%s'; + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->extension->common = '插件管理'; +$lang->extension->browse = '浏览插件'; +$lang->extension->install = '安装插件'; +$lang->extension->installAuto = '自动安装'; +$lang->extension->installForce = '强制安装'; +$lang->extension->uninstall = '卸载'; +$lang->extension->activate = '激活'; +$lang->extension->deactivate = '禁用'; +$lang->extension->obtain = '获得插件'; +$lang->extension->view = '详情'; +$lang->extension->download = '下载插件'; +$lang->extension->downloadAB = '下载'; +$lang->extension->upload = '本地安装'; +$lang->extension->erase = '清除'; +$lang->extension->upgrade = '升级'; +$lang->extension->agreeLicense = '我同意该授权'; + +$lang->extension->installed = '已安装'; +$lang->extension->deactivated = '被禁用'; +$lang->extension->available = '已下载'; + +$lang->extension->id = '编号'; +$lang->extension->name = '名称'; +$lang->extension->code = '插件代号'; +$lang->extension->version = '版本'; +$lang->extension->compatible = '适用版本'; +$lang->extension->latest = '最新版本%s,兼容禅道%s'; +$lang->extension->author = '作者'; +$lang->extension->license = '授权'; +$lang->extension->intro = '详情'; +$lang->extension->abstract = '简介'; +$lang->extension->site = '官网'; +$lang->extension->addedTime = '添加时间'; +$lang->extension->updatedTime = '更新时间'; +$lang->extension->downloads = '下载量'; +$lang->extension->public = '下载方式'; +$lang->extension->compatible = '兼容性'; +$lang->extension->grade = '评分'; + +$lang->extension->publicList[0] = '手工下载'; +$lang->extension->publicList[1] = '直接下载'; + +$lang->extension->compatibleList[0] = '未知'; +$lang->extension->compatibleList[1] = '兼容'; + +$lang->extension->byDownloads = '最多下载'; +$lang->extension->byAddedTime = '最新添加'; +$lang->extension->byUpdatedTime = '最近更新'; +$lang->extension->bySearch = '搜索'; +$lang->extension->byCategory = '分类浏览'; + +$lang->extension->installFailed = '安装失败,错误原因如下:'; +$lang->extension->installFinished = '恭喜您,插件顺利的安装成功!'; +$lang->extension->refreshPage = '刷新页面'; +$lang->extension->uninstallFinished = '插件已经成功卸载'; +$lang->extension->deactivateFinished = '插件已经成功禁用'; +$lang->extension->activateFinished = '插件已经成功激活'; +$lang->extension->eraseFinished = '插件已经成功清除'; +$lang->extension->unremovedFiles = '有一些文件或目录未能删除,需要手工删除'; +$lang->extension->executeCommands = '

          执行下面的命令来修正这些问题:

          '; +$lang->extension->successDownloadedPackage = '成功下载插件'; +$lang->extension->successCopiedFiles = '成功拷贝文件'; +$lang->extension->successInstallDB = '成功安装数据库'; +$lang->extension->viewInstalled = '查看已安装插件'; +$lang->extension->viewAvailable = '查看可安装插件'; +$lang->extension->viewDeactivated = '查看已禁用插件'; + +$lang->extension->errorOccurs = '错误:'; +$lang->extension->errorGetModules = '从www.zentao.net获得插件分类失败。可能是因为网络方面的原因,请检查后重新刷新页面。'; +$lang->extension->errorGetExtensions = '从www.zentao.net获得插件失败。可能是因为网络方面的原因,您可以到
          www.zentao.net手工下载插件,然后上传安装。'; +$lang->extension->errorDownloadPathNotFound = '插件下载存储路径%s不存在。
          linux下面请执行命令:mkdir -p %s来修正。'; +$lang->extension->errorDownloadPathNotWritable = '插件下载存储路径%s不可写。
          linux下面请执行命令:sudo chmod 777 %s来修正。'; +$lang->extension->errorPackageFileExists = '下载路径已经有一个名为的%s附件。

          重新安装,请点击此链接

          '; +$lang->extension->errorDownloadFailed = '下载失败,请重新下载。如果多次重试还不行,请尝试手工下载,然后通过上传功能上传。'; +$lang->extension->errorMd5Checking = '下载文件不完整,请重新下载。如果多次重试还不行,请尝试手工下载,然后通过上传功能上传。'; +$lang->extension->errorExtracted = '包文件 %s 解压缩失败,可能不是一个有效的zip文件。错误信息如下:
          %s'; +$lang->extension->errorCheckIncompatible = '该插件与禅道版本不兼容,安装后可能无法使用。。

          您可以选择 强制安装 或者 取消安装

          '; +$lang->extension->errorFileConflicted = '有以下安装文件冲突:
          %s

          您可以选择 覆盖安装 或者 取消安装

          '; +$lang->extension->errorPackageNotFound = '包文件 %s 没有找到,可能是因为自动下载失败。您可以尝试再次下载。'; +$lang->extension->errorTargetPathNotWritable = '目标路径 %s 不可写。'; +$lang->extension->errorTargetPathNotExists = '目标路径 %s 不存在。'; +$lang->extension->errorInstallDB = '执行数据库语句失败。错误信息如下:%s'; diff --git a/module/extension/lang/zh-tw.php b/module/extension/lang/zh-tw.php index e9ca0c633d..7c41bff16c 100644 --- a/module/extension/lang/zh-tw.php +++ b/module/extension/lang/zh-tw.php @@ -1,93 +1,93 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->extension->common = '插件管理'; -$lang->extension->browse = '瀏覽插件'; -$lang->extension->install = '安裝插件'; -$lang->extension->installAuto = '自動安裝'; -$lang->extension->installForce = '強制安裝'; -$lang->extension->uninstall = '卸載'; -$lang->extension->activate = '激活'; -$lang->extension->deactivate = '禁用'; -$lang->extension->obtain = '獲得插件'; -$lang->extension->view = '詳情'; -$lang->extension->download = '下載插件'; -$lang->extension->downloadAB = '下載'; -$lang->extension->upload = '本地安裝'; -$lang->extension->erase = '清除'; -$lang->extension->upgrade = '升級'; -$lang->extension->agreeLicense = '我同意該授權'; - -$lang->extension->installed = '已安裝'; -$lang->extension->deactivated = '被禁用'; -$lang->extension->available = '已下載'; - -$lang->extension->id = '編號'; -$lang->extension->name = '名稱'; -$lang->extension->code = '插件代號'; -$lang->extension->version = '版本'; -$lang->extension->compatible = '適用版本'; -$lang->extension->latest = '最新版本%s,兼容禪道%s'; -$lang->extension->author = '作者'; -$lang->extension->license = '授權'; -$lang->extension->intro = '詳情'; -$lang->extension->abstract = '簡介'; -$lang->extension->site = '官網'; -$lang->extension->addedTime = '添加時間'; -$lang->extension->updatedTime = '更新時間'; -$lang->extension->downloads = '下載量'; -$lang->extension->public = '下載方式'; -$lang->extension->compatible = '兼容性'; -$lang->extension->grade = '評分'; - -$lang->extension->publicList[0] = '手工下載'; -$lang->extension->publicList[1] = '直接下載'; - -$lang->extension->compatibleList[0] = '未知'; -$lang->extension->compatibleList[1] = '兼容'; - -$lang->extension->byDownloads = '最多下載'; -$lang->extension->byAddedTime = '最新添加'; -$lang->extension->byUpdatedTime = '最近更新'; -$lang->extension->bySearch = '搜索'; -$lang->extension->byCategory = '分類瀏覽'; - -$lang->extension->installFailed = '安裝失敗,錯誤原因如下:'; -$lang->extension->installFinished = '恭喜您,插件順利的安裝成功!'; -$lang->extension->refreshPage = '刷新頁面'; -$lang->extension->uninstallFinished = '插件已經成功卸載'; -$lang->extension->deactivateFinished = '插件已經成功禁用'; -$lang->extension->activateFinished = '插件已經成功激活'; -$lang->extension->eraseFinished = '插件已經成功清除'; -$lang->extension->unremovedFiles = '有一些檔案或目錄未能刪除,需要手工刪除'; -$lang->extension->executeCommands = '

          執行下面的命令來修正這些問題:

          '; -$lang->extension->successDownloadedPackage = '成功下載插件'; -$lang->extension->successCopiedFiles = '成功拷貝檔案'; -$lang->extension->successInstallDB = '成功安裝資料庫'; -$lang->extension->viewInstalled = '查看已安裝插件'; -$lang->extension->viewAvailable = '查看可安裝插件'; -$lang->extension->viewDeactivated = '查看已禁用插件'; - -$lang->extension->errorOccurs = '錯誤:'; -$lang->extension->errorGetModules = '從www.zentao.net獲得插件分類失敗。可能是因為網絡方面的原因,請檢查後重新刷新頁面。'; -$lang->extension->errorGetExtensions = '從www.zentao.net獲得插件失敗。可能是因為網絡方面的原因,您可以到
          www.zentao.net手工下載插件,然後上傳安裝。'; -$lang->extension->errorDownloadPathNotFound = '插件下載存儲路徑%s不存在。
          linux下面請執行命令:mkdir -p %s來修正。'; -$lang->extension->errorDownloadPathNotWritable = '插件下載存儲路徑%s不可寫。
          linux下面請執行命令:sudo chmod 777 %s來修正。'; -$lang->extension->errorPackageFileExists = '下載路徑已經有一個名為的%s附件。

          重新安裝,請點擊此連結

          '; -$lang->extension->errorDownloadFailed = '下載失敗,請重新下載。如果多次重試還不行,請嘗試手工下載,然後通過上傳功能上傳。'; -$lang->extension->errorMd5Checking = '下載檔案不完整,請重新下載。如果多次重試還不行,請嘗試手工下載,然後通過上傳功能上傳。'; -$lang->extension->errorExtracted = '包檔案 %s 解壓縮失敗,可能不是一個有效的zip檔案。錯誤信息如下:
          %s'; -$lang->extension->errorCheckIncompatible = '該插件與禪道版本不兼容,安裝後可能無法使用。。

          您可以選擇 強制安裝 或者 取消安裝

          '; -$lang->extension->errorFileConflicted = '有以下安裝檔案衝突:
          %s

          您可以選擇 覆蓋安裝 或者 取消安裝

          '; -$lang->extension->errorPackageNotFound = '包檔案 %s 沒有找到,可能是因為自動下載失敗。您可以嘗試再次下載。'; -$lang->extension->errorTargetPathNotWritable = '目標路徑 %s 不可寫。'; -$lang->extension->errorTargetPathNotExists = '目標路徑 %s 不存在。'; -$lang->extension->errorInstallDB = '執行資料庫語句失敗。錯誤信息如下:%s'; + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->extension->common = '插件管理'; +$lang->extension->browse = '瀏覽插件'; +$lang->extension->install = '安裝插件'; +$lang->extension->installAuto = '自動安裝'; +$lang->extension->installForce = '強制安裝'; +$lang->extension->uninstall = '卸載'; +$lang->extension->activate = '激活'; +$lang->extension->deactivate = '禁用'; +$lang->extension->obtain = '獲得插件'; +$lang->extension->view = '詳情'; +$lang->extension->download = '下載插件'; +$lang->extension->downloadAB = '下載'; +$lang->extension->upload = '本地安裝'; +$lang->extension->erase = '清除'; +$lang->extension->upgrade = '升級'; +$lang->extension->agreeLicense = '我同意該授權'; + +$lang->extension->installed = '已安裝'; +$lang->extension->deactivated = '被禁用'; +$lang->extension->available = '已下載'; + +$lang->extension->id = '編號'; +$lang->extension->name = '名稱'; +$lang->extension->code = '插件代號'; +$lang->extension->version = '版本'; +$lang->extension->compatible = '適用版本'; +$lang->extension->latest = '最新版本%s,兼容禪道%s'; +$lang->extension->author = '作者'; +$lang->extension->license = '授權'; +$lang->extension->intro = '詳情'; +$lang->extension->abstract = '簡介'; +$lang->extension->site = '官網'; +$lang->extension->addedTime = '添加時間'; +$lang->extension->updatedTime = '更新時間'; +$lang->extension->downloads = '下載量'; +$lang->extension->public = '下載方式'; +$lang->extension->compatible = '兼容性'; +$lang->extension->grade = '評分'; + +$lang->extension->publicList[0] = '手工下載'; +$lang->extension->publicList[1] = '直接下載'; + +$lang->extension->compatibleList[0] = '未知'; +$lang->extension->compatibleList[1] = '兼容'; + +$lang->extension->byDownloads = '最多下載'; +$lang->extension->byAddedTime = '最新添加'; +$lang->extension->byUpdatedTime = '最近更新'; +$lang->extension->bySearch = '搜索'; +$lang->extension->byCategory = '分類瀏覽'; + +$lang->extension->installFailed = '安裝失敗,錯誤原因如下:'; +$lang->extension->installFinished = '恭喜您,插件順利的安裝成功!'; +$lang->extension->refreshPage = '刷新頁面'; +$lang->extension->uninstallFinished = '插件已經成功卸載'; +$lang->extension->deactivateFinished = '插件已經成功禁用'; +$lang->extension->activateFinished = '插件已經成功激活'; +$lang->extension->eraseFinished = '插件已經成功清除'; +$lang->extension->unremovedFiles = '有一些檔案或目錄未能刪除,需要手工刪除'; +$lang->extension->executeCommands = '

          執行下面的命令來修正這些問題:

          '; +$lang->extension->successDownloadedPackage = '成功下載插件'; +$lang->extension->successCopiedFiles = '成功拷貝檔案'; +$lang->extension->successInstallDB = '成功安裝資料庫'; +$lang->extension->viewInstalled = '查看已安裝插件'; +$lang->extension->viewAvailable = '查看可安裝插件'; +$lang->extension->viewDeactivated = '查看已禁用插件'; + +$lang->extension->errorOccurs = '錯誤:'; +$lang->extension->errorGetModules = '從www.zentao.net獲得插件分類失敗。可能是因為網絡方面的原因,請檢查後重新刷新頁面。'; +$lang->extension->errorGetExtensions = '從www.zentao.net獲得插件失敗。可能是因為網絡方面的原因,您可以到
          www.zentao.net手工下載插件,然後上傳安裝。'; +$lang->extension->errorDownloadPathNotFound = '插件下載存儲路徑%s不存在。
          linux下面請執行命令:mkdir -p %s來修正。'; +$lang->extension->errorDownloadPathNotWritable = '插件下載存儲路徑%s不可寫。
          linux下面請執行命令:sudo chmod 777 %s來修正。'; +$lang->extension->errorPackageFileExists = '下載路徑已經有一個名為的%s附件。

          重新安裝,請點擊此連結

          '; +$lang->extension->errorDownloadFailed = '下載失敗,請重新下載。如果多次重試還不行,請嘗試手工下載,然後通過上傳功能上傳。'; +$lang->extension->errorMd5Checking = '下載檔案不完整,請重新下載。如果多次重試還不行,請嘗試手工下載,然後通過上傳功能上傳。'; +$lang->extension->errorExtracted = '包檔案 %s 解壓縮失敗,可能不是一個有效的zip檔案。錯誤信息如下:
          %s'; +$lang->extension->errorCheckIncompatible = '該插件與禪道版本不兼容,安裝後可能無法使用。。

          您可以選擇 強制安裝 或者 取消安裝

          '; +$lang->extension->errorFileConflicted = '有以下安裝檔案衝突:
          %s

          您可以選擇 覆蓋安裝 或者 取消安裝

          '; +$lang->extension->errorPackageNotFound = '包檔案 %s 沒有找到,可能是因為自動下載失敗。您可以嘗試再次下載。'; +$lang->extension->errorTargetPathNotWritable = '目標路徑 %s 不可寫。'; +$lang->extension->errorTargetPathNotExists = '目標路徑 %s 不存在。'; +$lang->extension->errorInstallDB = '執行資料庫語句失敗。錯誤信息如下:%s'; diff --git a/module/extension/model.php b/module/extension/model.php index 464f998b71..1ed5c14871 100644 --- a/module/extension/model.php +++ b/module/extension/model.php @@ -1,754 +1,754 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -class extensionModel extends model -{ - /** - * The extension manager version. Don't change it. - */ - const EXT_MANAGER_VERSION = '1.3'; - - /** - * The api agent(use snoopy). - * - * @var object - * @access public - */ - public $agent; - - /** - * The api root. - * - * @var string - * @access public - */ - public $apiRoot; - - /** - * The construct function. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->setAgent(); - $this->setApiRoot(); - $this->classFile = $this->app->loadClass('file'); - } - - /** - * Set the api agent. - * - * @access public - * @return void - */ - public function setAgent() - { - $this->agent = $this->app->loadClass('snoopy'); - } - - /** - * Set the apiRoot. - * - * @access public - * @return void - */ - public function setApiRoot() - { - $this->apiRoot = $this->config->extension->apiRoot; - } - - /** - * Fetch data from an api. - * - * @param string $url - * @access public - * @return mixed - */ - public function fetchAPI($url) - { - $url .= '?lang=' . str_replace('-', '_', $this->app->getClientLang()) . '&managerVersion=' . self::EXT_MANAGER_VERSION . '&zentaoVersion=' . $this->config->version; - $this->agent->fetch($url); - $result = json_decode($this->agent->results); - - if(!isset($result->status)) return false; - if($result->status != 'success') return false; - if(isset($result->data) and md5($result->data) != $result->md5) return false; - if(isset($result->data)) return json_decode($result->data); - } - - /** - * Get extension modules from the api. - * - * @access public - * @return string|bool - */ - public function getModulesByAPI() - { - $requestType = $this->config->requestType; - $webRoot = helper::safe64Encode($this->config->webRoot); - $apiURL = $this->apiRoot . 'apiGetmodules-' . $requestType . '-' . $webRoot . '.json'; - $data = $this->fetchAPI($apiURL); - if(isset($data->modules)) return $data->modules; - return false; - } - - /** - * Get extensions by some condition. - * - * @param string $type - * @param mixed $param - * @access public - * @return array|bool - */ - public function getExtensionsByAPI($type, $param, $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $apiURL = $this->apiRoot . "apiGetExtensions-$type-$param-$recTotal-$recPerPage-$pageID.json"; - $data = $this->fetchAPI($apiURL); - if(isset($data->extensions)) - { - foreach($data->extensions as $extension) - { - $extension->currentRelease = isset($extension->compatibleRelease) ? $extension->compatibleRelease : $extension->latestRelease; - $extension->currentRelease->compatible = isset($extension->compatibleRelease); - } - return $data; - } - return false; - } - - /** - * Get versions for some extensions. - * - * @param string $extensions - * @access public - * @return array|bool - */ - public function getVersionsByAPI($extensions) - { - $extensions = helper::safe64Encode($extensions); - $apiURL = $this->apiRoot . 'apiGetVersions-' . $extensions . '.json'; - $data = $this->fetchAPI($apiURL); - if(isset($data->versions)) return (array)$data->versions; - return false; - } - - /** - * Download an extension. - * - * @param string $extension - * @param string $downLink - * @access public - * @return void - */ - public function downloadPackage($extension, $downLink) - { - $packageFile = $this->getPackageFile($extension); - $this->agent->fetch($downLink); - file_put_contents($packageFile, $this->agent->results); - } - - /** - * Get extensions by status. - * - * @param string $status - * @access public - * @return array - */ - public function getLocalExtensions($status) - { - $extensions = $this->dao->select('*')->from(TABLE_EXTENSION)->where('status')->eq($status)->fi()->fetchAll('code'); - foreach($extensions as $extension) - { - if($extension->site and stripos(strtolower($extension->site), 'http') === false) $extension->site = 'http://' . $extension->site; - } - return $extensions; - } - - /** - * Get extension info from database. - * - * @param string $extension - * @access public - * @return object - */ - public function getInfoFromDB($extension) - { - return $this->dao->select('*')->from(TABLE_EXTENSION)->where('code')->eq($extension)->fi()->fetch(); - } - - /** - * Get info of an extension from the package file. - * - * @param string $extension - * @access public - * @return object - */ - public function getInfoFromPackage($extension) - { - /* Init the data. */ - $data->name = $extension; - $data->code = $extension; - $data->version = 'unknown'; - $data->author = 'unknown'; - $data->desc = $extension; - $data->site = 'unknown'; - $data->license = 'unknown'; - $data->zentaoVersion = ''; - - $info = $this->parseExtensionCFG($extension); - foreach($info as $key => $value) if(isset($data->$key)) $data->$key = $value; - if(isset($info->zentaoversion)) $data->zentaoVersion = $info->zentaoversion; - - return $data; - } - - /** - * Parse extension's config file. - * - * @param string $extension - * @access public - * @return object - */ - public function parseExtensionCFG($extension) - { - $info = new stdclass(); - - /* First, try ini file. before 2.5 version. */ - $infoFile = "ext/$extension/doc/copyright.txt"; - if(file_exists($infoFile)) return (object)parse_ini_file($infoFile); - - /** - * Then try parse yaml file. since 2.5 version. - */ - - /* Try the yaml of current lang, then try en. */ - $lang = $this->app->getClientLang(); - $infoFile = "ext/$extension/doc/$lang.yaml"; - if(!file_exists($infoFile)) $infoFile = "ext/$extension/doc/en.yaml"; - if(!file_exists($infoFile)) return $info; - - /* Load the yaml file and parse it into object. */ - $this->app->loadClass('spyc', true); - $info = (object)spyc_load(file_get_contents($infoFile)); - if(isset($info->releases)) - { - krsort($info->releases); - $info->version = key($info->releases); - foreach($info->releases[$info->version] as $key => $value) $info->$key = $value; - } - return $info; - } - - /** - * Get the full path of the zip file of a extension. - * - * @param string $extension - * @access public - * @return string - */ - public function getPackageFile($extension) - { - return $this->app->getTmpRoot() . 'extension/' . $extension . '.zip'; - } - - /** - * Get pathes from an extension package. - * - * @param string $extension - * @access public - * @return array - */ - public function getPathesFromPackage($extension) - { - $pathes = array(); - $packageFile = $this->getPackageFile($extension); - - /* Get files from the package file. */ - $this->app->loadClass('pclzip', true); - $zip = new pclzip($packageFile); - $files = $zip->listContent(); - if($files) - { - foreach($files as $file) - { - $file = (object)$file; - if($file->folder) continue; - $file->filename = substr($file->filename, strpos($file->filename, '/') + 1); - $pathes[] = dirname($file->filename); - } - } - - /* Append the pathes to stored the extracted files. */ - $pathes[] = "module/extension/ext/"; - - return array_unique($pathes); - } - - /** - * Get all files from a package. - * - * @param string $extension - * @access public - * @return array - */ - public function getFilesFromPackage($extension) - { - $extensionDir = "ext/$extension/"; - $files = $this->classFile->readDir($extensionDir, array('db', 'doc')); - return $files; - } - - /** - * Get the extension's zentaoVersion - * - * @param string $extenstion - * @access public - * @return string - */ - public function getZentaoVersion($extension) - { - $info = $this->parseExtensionCFG($extension); - if(isset($info->zentaoVersion)) return $info->zentaoVersion; - if(isset($info->zentaoversion)) return $info->zentaoversion; - - return ''; - } - - /** - * Process license. If is opensource return the full text of it. - * - * @param string $license - * @access public - * @return string - */ - public function processLicense($license) - { - if(strlen($license) > 10) return $license; // more then 10 letters, not gpl, lgpl, apache, bsd or mit. - - $licenseFile = dirname(__FILE__) . '/license/' . strtolower($license) . '.txt'; - if(file_exists($licenseFile)) return file_get_contents($licenseFile); - - return $license; - } - - /** - * Get hook file for install or uninstall. - * - * @param string $extension - * @param string $hook preinstall|postinstall|preuninstall|postuninstall - * @access public - * @return string|bool - */ - public function getHookFile($extension, $hook) - { - $hookFile = "ext/$extension/hook/$hook.php"; - if(file_exists($hookFile)) return $hookFile; - return false; - } - - /** - * Get the install db file. - * - * @param string $extension - * @param string $method - * @access public - * @return string - */ - public function getDBFile($extension, $method = 'install') - { - return "ext/$extension/db/$method.sql"; - } - - /** - * Check the download path. - * - * @access public - * @return object the check result. - */ - public function checkDownloadPath() - { - /* Init the return. */ - $return->result = 'ok'; - $return->error = ''; - - $tmpRoot = $this->app->getTmpRoot(); - $downloadPath = $tmpRoot . 'extension'; - - if(!is_dir($downloadPath)) - { - if(is_writable($tmpRoot)) - { - mkdir($downloadPath); - } - else - { - $return->result = 'fail'; - $return->error = sprintf($this->lang->extension->errorDownloadPathNotFound, $downloadPath, $downloadPath); - } - } - elseif(!is_writable($downloadPath)) - { - $return->result = 'fail'; - $return->error = sprintf($this->lang->extension->errorDownloadPathNotWritable, $downloadPath, $downloadPath); - } - return $return; - } - - /** - * Check extension files. - * - * @param string $extension - * @access public - * @return object the check result. - */ - public function checkExtensionPathes($extension) - { - $return->result = 'ok'; - $return->errors = ''; - $return->mkdirCommands = ''; - $return->chmodCommands = ''; - $return->dirs2Created = array(); - - $appRoot = $this->app->getAppRoot(); - $pathes = $this->getPathesFromPackage($extension); - foreach($pathes as $path) - { - if($path == 'db' or $path == 'doc' or $path == 'hook') continue; - $path = $appRoot . $path; - if(is_dir($path)) - { - if(!is_writable($path)) - { - $return->errors .= sprintf($this->lang->extension->errorTargetPathNotWritable, $path) . '
          '; - $return->chmodCommands .= "sudo chmod -R 777 $path
          "; - } - } - else - { - if(!@mkdir($path, 0755, true)) - { - $return->errors .= sprintf($this->lang->extension->errorTargetPathNotExists, $path) . '
          '; - $return->mkdirCommands .= "mkdir -p $path
          "; - $return->chmodCommands .= "sudo chmod -R 777 $path
          "; - } - $return->dirs2Created[] = $path; - } - } - - if($return->errors) $return->result = 'fail'; - $return->mkdirCommands = str_replace('/', DIRECTORY_SEPARATOR, $return->mkdirCommands); - $return->errors .= $this->lang->extension->executeCommands . $return->mkdirCommands; - if(PHP_OS == 'Linux') $return->errors .= $return->chmodCommands; - return $return; - } - - /** - * Check the extension's version is compatibility for zentao version - * - * @param string $version - * @access public - * @return bool - */ - public function checkVersion($version) - { - if($version == 'all') return true; - $version = explode(',', $version); - if(in_array($this->config->version, $version)) return true; - return false; - } - - /** - * Check files in the package conflicts with exists files or not. - * - * @param string $extension - * @param string $type - * @param bool $isCheck - * @access public - * @return object - */ - public function checkFile($extension) - { - $return->result = 'ok'; - $return->error = ''; - - $extensionFiles = $this->getFilesFromPackage($extension); - $appRoot = $this->app->getAppRoot(); - foreach($extensionFiles as $extensionFile) - { - $compareFile = $appRoot . str_replace(realpath("ext/$extension") . '/', '', $extensionFile); - if(!file_exists($compareFile)) continue; - if(md5_file($extensionFile) != md5_file($compareFile)) $return->error .= $compareFile . '
          '; - } - - if($return->error != '') $return->result = 'fail'; - return $return; - } - - /** - * Extract an extension. - * - * @param string $extension - * @access public - * @return object - */ - public function extractPackage($extension) - { - $return->result = 'ok'; - $return->error = ''; - - /* try remove pre extracted files. */ - $extensionPath = "ext/$extension"; - if(is_dir($extensionPath)) $this->classFile->removeDir($extensionPath); - - /* Extract files. */ - $packageFile = $this->getPackageFile($extension); - $this->app->loadClass('pclzip', true); - $zip = new pclzip($packageFile); - $files = $zip->listContent(); - $removePath = $files[0]['filename']; - if($zip->extract(PCLZIP_OPT_PATH, $extensionPath, PCLZIP_OPT_REMOVE_PATH, $removePath) == 0) - { - $return->result = 'fail'; - $return->error = $zip->errorInfo(true); - } - - return $return; - } - - /** - * Copy package files. - * - * @param int $extension - * @access public - * @return array - */ - public function copyPackageFiles($extension) - { - $appRoot = $this->app->getAppRoot(); - $extensionDir = "ext/$extension/"; - $pathes = scandir($extensionDir); - $copiedFiles = array(); - - foreach($pathes as $path) - { - if($path == 'db' or $path == 'doc' or $path == 'hook' or $path == '..' or $path == '.') continue; - $copiedFiles = $this->classFile->copyDir($extensionDir . $path, $appRoot . $path); - } - foreach($copiedFiles as $key => $copiedFile) - { - $copiedFiles[$copiedFile] = md5_file($copiedFile); - unset($copiedFiles[$key]); - } - return $copiedFiles; - } - - /** - * Remove an extension. - * - * @param string $extension - * @access public - * @return array the remove commands need executed manually. - */ - public function removePackage($extension) - { - $extension = $this->getInfoFromDB($extension); - $dirs = json_decode($extension->dirs); - $files = json_decode($extension->files); - $appRoot = $this->app->getAppRoot(); - $removeCommands = array(); - - /* Remove files first. */ - if($files) - { - foreach($files as $file => $savedMD5) - { - $file = $appRoot . $file; - if(!file_exists($file)) continue; - - if(md5_file($file) != $savedMD5) - { - $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $file #changed" : "del $file :changed"; - } - elseif(!@unlink($file)) - { - $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $file" : "del $file"; - } - } - } - - /* Then remove dirs. */ - if($dirs) - { - rsort($dirs); // remove from the lower level directory. - foreach($dirs as $dir) - { - if(!@rmdir($appRoot . $dir)) $removeCommands[] = "rmdir $appRoot$dir"; - } - } - - /* Clean model cache files. */ - $this->cleanModelCache(); - - return $removeCommands; - } - - /** - * Clean model cache files. - * - * @access public - * @return void - */ - public function cleanModelCache() - { - $modelCacheFiles = glob($this->app->getTmpRoot() . 'model/*'); - foreach($modelCacheFiles as $cacheFile) @unlink($cacheFile); - } - - /** - * Erase an extension's package file. - * - * @param string $extension - * @access public - * @return array the remove commands need executed manually. - */ - public function erasePackage($extension) - { - $removeCommands = array(); - - $this->dao->delete()->from(TABLE_EXTENSION)->where('code')->eq($extension)->exec(); - - /* Remove the zip file. */ - $packageFile = $this->getPackageFile($extension); - if(file_exists($packageFile) and !@unlink($packageFile)) - { - $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $packageFile" : "del $packageFile"; - } - - /* Remove the extracted files. */ - $extractedDir = realpath("ext/$extension"); - if($extractedDir != '/' and !$this->classFile->removeDir($extractedDir)) - { - $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $extractedDir" : "rmdir $extractedDir /s"; - } - - return $removeCommands; - } - - /** - * Judge need execute db install or not. - * - * @param string $extension - * @param string $method - * @access public - * @return bool - */ - public function needExecuteDB($extension, $method = 'install') - { - return file_exists($this->getDBFile($extension, $method)); - } - - /** - * Install the db. - * - * @param int $extension - * @access public - * @return object - */ - public function executeDB($extension, $method = 'install') - { - $return->result = 'ok'; - $return->error = ''; - - $dbFile = $this->getDBFile($extension, $method); - if(!file_exists($dbFile)) return $return; - - $sqls = file_get_contents($this->getDBFile($extension, $method)); - $sqls = explode(';', $sqls); - - foreach($sqls as $sql) - { - $sql = trim($sql); - if(empty($sql)) continue; - $sql = str_replace('zt_', $this->config->db->prefix, $sql); - - try - { - $this->dbh->query($sql); - } - catch (PDOException $e) - { - $return->error .= '

          ' . $e->getMessage() . "
          THE SQL IS: $sql

          "; - } - } - if($return->error) $return->result = 'fail'; - return $return; - } - - /** - * Save the extension to database. - * - * @param string $extension the extension code - * @param string $type the extension type - * @access public - * @return void - */ - public function saveExtension($extension, $type) - { - $code = $extension; - $extension = $this->getInfoFromPackage($extension); - $extension->status = 'available'; - $extension->code = $code; - $extension->type = $type; - $this->dao->replace(TABLE_EXTENSION)->data($extension)->exec(); - } - - /** - * Update an extension. - * - * @param string $extension - * @param string $status - * @param array $files - * @access public - * @return void - */ - public function updateExtension($extension, $data) - { - $data = (object)$data; - $appRoot = $this->app->getAppRoot(); - - if(isset($data->dirs)) - { - if($data->dirs) - { - foreach($data->dirs as $key => $dir) - { - $data->dirs[$key] = str_replace($appRoot, '', $dir); - } - } - $data->dirs = json_encode($data->dirs); - } - - if(isset($data->files)) - { - foreach($data->files as $fullFilePath => $md5) - { - $relativeFilePath = str_replace($appRoot, '', $fullFilePath); - $data->files[$relativeFilePath] = $md5; - unset($data->files[$fullFilePath]); - } - $data->files = json_encode($data->files); - } - return $this->dao->update(TABLE_EXTENSION)->data($data)->where('code')->eq($extension)->exec(); - } -} + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +class extensionModel extends model +{ + /** + * The extension manager version. Don't change it. + */ + const EXT_MANAGER_VERSION = '1.3'; + + /** + * The api agent(use snoopy). + * + * @var object + * @access public + */ + public $agent; + + /** + * The api root. + * + * @var string + * @access public + */ + public $apiRoot; + + /** + * The construct function. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->setAgent(); + $this->setApiRoot(); + $this->classFile = $this->app->loadClass('file'); + } + + /** + * Set the api agent. + * + * @access public + * @return void + */ + public function setAgent() + { + $this->agent = $this->app->loadClass('snoopy'); + } + + /** + * Set the apiRoot. + * + * @access public + * @return void + */ + public function setApiRoot() + { + $this->apiRoot = $this->config->extension->apiRoot; + } + + /** + * Fetch data from an api. + * + * @param string $url + * @access public + * @return mixed + */ + public function fetchAPI($url) + { + $url .= '?lang=' . str_replace('-', '_', $this->app->getClientLang()) . '&managerVersion=' . self::EXT_MANAGER_VERSION . '&zentaoVersion=' . $this->config->version; + $this->agent->fetch($url); + $result = json_decode($this->agent->results); + + if(!isset($result->status)) return false; + if($result->status != 'success') return false; + if(isset($result->data) and md5($result->data) != $result->md5) return false; + if(isset($result->data)) return json_decode($result->data); + } + + /** + * Get extension modules from the api. + * + * @access public + * @return string|bool + */ + public function getModulesByAPI() + { + $requestType = $this->config->requestType; + $webRoot = helper::safe64Encode($this->config->webRoot); + $apiURL = $this->apiRoot . 'apiGetmodules-' . $requestType . '-' . $webRoot . '.json'; + $data = $this->fetchAPI($apiURL); + if(isset($data->modules)) return $data->modules; + return false; + } + + /** + * Get extensions by some condition. + * + * @param string $type + * @param mixed $param + * @access public + * @return array|bool + */ + public function getExtensionsByAPI($type, $param, $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $apiURL = $this->apiRoot . "apiGetExtensions-$type-$param-$recTotal-$recPerPage-$pageID.json"; + $data = $this->fetchAPI($apiURL); + if(isset($data->extensions)) + { + foreach($data->extensions as $extension) + { + $extension->currentRelease = isset($extension->compatibleRelease) ? $extension->compatibleRelease : $extension->latestRelease; + $extension->currentRelease->compatible = isset($extension->compatibleRelease); + } + return $data; + } + return false; + } + + /** + * Get versions for some extensions. + * + * @param string $extensions + * @access public + * @return array|bool + */ + public function getVersionsByAPI($extensions) + { + $extensions = helper::safe64Encode($extensions); + $apiURL = $this->apiRoot . 'apiGetVersions-' . $extensions . '.json'; + $data = $this->fetchAPI($apiURL); + if(isset($data->versions)) return (array)$data->versions; + return false; + } + + /** + * Download an extension. + * + * @param string $extension + * @param string $downLink + * @access public + * @return void + */ + public function downloadPackage($extension, $downLink) + { + $packageFile = $this->getPackageFile($extension); + $this->agent->fetch($downLink); + file_put_contents($packageFile, $this->agent->results); + } + + /** + * Get extensions by status. + * + * @param string $status + * @access public + * @return array + */ + public function getLocalExtensions($status) + { + $extensions = $this->dao->select('*')->from(TABLE_EXTENSION)->where('status')->eq($status)->fi()->fetchAll('code'); + foreach($extensions as $extension) + { + if($extension->site and stripos(strtolower($extension->site), 'http') === false) $extension->site = 'http://' . $extension->site; + } + return $extensions; + } + + /** + * Get extension info from database. + * + * @param string $extension + * @access public + * @return object + */ + public function getInfoFromDB($extension) + { + return $this->dao->select('*')->from(TABLE_EXTENSION)->where('code')->eq($extension)->fi()->fetch(); + } + + /** + * Get info of an extension from the package file. + * + * @param string $extension + * @access public + * @return object + */ + public function getInfoFromPackage($extension) + { + /* Init the data. */ + $data->name = $extension; + $data->code = $extension; + $data->version = 'unknown'; + $data->author = 'unknown'; + $data->desc = $extension; + $data->site = 'unknown'; + $data->license = 'unknown'; + $data->zentaoVersion = ''; + + $info = $this->parseExtensionCFG($extension); + foreach($info as $key => $value) if(isset($data->$key)) $data->$key = $value; + if(isset($info->zentaoversion)) $data->zentaoVersion = $info->zentaoversion; + + return $data; + } + + /** + * Parse extension's config file. + * + * @param string $extension + * @access public + * @return object + */ + public function parseExtensionCFG($extension) + { + $info = new stdclass(); + + /* First, try ini file. before 2.5 version. */ + $infoFile = "ext/$extension/doc/copyright.txt"; + if(file_exists($infoFile)) return (object)parse_ini_file($infoFile); + + /** + * Then try parse yaml file. since 2.5 version. + */ + + /* Try the yaml of current lang, then try en. */ + $lang = $this->app->getClientLang(); + $infoFile = "ext/$extension/doc/$lang.yaml"; + if(!file_exists($infoFile)) $infoFile = "ext/$extension/doc/en.yaml"; + if(!file_exists($infoFile)) return $info; + + /* Load the yaml file and parse it into object. */ + $this->app->loadClass('spyc', true); + $info = (object)spyc_load(file_get_contents($infoFile)); + if(isset($info->releases)) + { + krsort($info->releases); + $info->version = key($info->releases); + foreach($info->releases[$info->version] as $key => $value) $info->$key = $value; + } + return $info; + } + + /** + * Get the full path of the zip file of a extension. + * + * @param string $extension + * @access public + * @return string + */ + public function getPackageFile($extension) + { + return $this->app->getTmpRoot() . 'extension/' . $extension . '.zip'; + } + + /** + * Get pathes from an extension package. + * + * @param string $extension + * @access public + * @return array + */ + public function getPathesFromPackage($extension) + { + $pathes = array(); + $packageFile = $this->getPackageFile($extension); + + /* Get files from the package file. */ + $this->app->loadClass('pclzip', true); + $zip = new pclzip($packageFile); + $files = $zip->listContent(); + if($files) + { + foreach($files as $file) + { + $file = (object)$file; + if($file->folder) continue; + $file->filename = substr($file->filename, strpos($file->filename, '/') + 1); + $pathes[] = dirname($file->filename); + } + } + + /* Append the pathes to stored the extracted files. */ + $pathes[] = "module/extension/ext/"; + + return array_unique($pathes); + } + + /** + * Get all files from a package. + * + * @param string $extension + * @access public + * @return array + */ + public function getFilesFromPackage($extension) + { + $extensionDir = "ext/$extension/"; + $files = $this->classFile->readDir($extensionDir, array('db', 'doc')); + return $files; + } + + /** + * Get the extension's zentaoVersion + * + * @param string $extenstion + * @access public + * @return string + */ + public function getZentaoVersion($extension) + { + $info = $this->parseExtensionCFG($extension); + if(isset($info->zentaoVersion)) return $info->zentaoVersion; + if(isset($info->zentaoversion)) return $info->zentaoversion; + + return ''; + } + + /** + * Process license. If is opensource return the full text of it. + * + * @param string $license + * @access public + * @return string + */ + public function processLicense($license) + { + if(strlen($license) > 10) return $license; // more then 10 letters, not gpl, lgpl, apache, bsd or mit. + + $licenseFile = dirname(__FILE__) . '/license/' . strtolower($license) . '.txt'; + if(file_exists($licenseFile)) return file_get_contents($licenseFile); + + return $license; + } + + /** + * Get hook file for install or uninstall. + * + * @param string $extension + * @param string $hook preinstall|postinstall|preuninstall|postuninstall + * @access public + * @return string|bool + */ + public function getHookFile($extension, $hook) + { + $hookFile = "ext/$extension/hook/$hook.php"; + if(file_exists($hookFile)) return $hookFile; + return false; + } + + /** + * Get the install db file. + * + * @param string $extension + * @param string $method + * @access public + * @return string + */ + public function getDBFile($extension, $method = 'install') + { + return "ext/$extension/db/$method.sql"; + } + + /** + * Check the download path. + * + * @access public + * @return object the check result. + */ + public function checkDownloadPath() + { + /* Init the return. */ + $return->result = 'ok'; + $return->error = ''; + + $tmpRoot = $this->app->getTmpRoot(); + $downloadPath = $tmpRoot . 'extension'; + + if(!is_dir($downloadPath)) + { + if(is_writable($tmpRoot)) + { + mkdir($downloadPath); + } + else + { + $return->result = 'fail'; + $return->error = sprintf($this->lang->extension->errorDownloadPathNotFound, $downloadPath, $downloadPath); + } + } + elseif(!is_writable($downloadPath)) + { + $return->result = 'fail'; + $return->error = sprintf($this->lang->extension->errorDownloadPathNotWritable, $downloadPath, $downloadPath); + } + return $return; + } + + /** + * Check extension files. + * + * @param string $extension + * @access public + * @return object the check result. + */ + public function checkExtensionPathes($extension) + { + $return->result = 'ok'; + $return->errors = ''; + $return->mkdirCommands = ''; + $return->chmodCommands = ''; + $return->dirs2Created = array(); + + $appRoot = $this->app->getAppRoot(); + $pathes = $this->getPathesFromPackage($extension); + foreach($pathes as $path) + { + if($path == 'db' or $path == 'doc' or $path == 'hook') continue; + $path = $appRoot . $path; + if(is_dir($path)) + { + if(!is_writable($path)) + { + $return->errors .= sprintf($this->lang->extension->errorTargetPathNotWritable, $path) . '
          '; + $return->chmodCommands .= "sudo chmod -R 777 $path
          "; + } + } + else + { + if(!@mkdir($path, 0755, true)) + { + $return->errors .= sprintf($this->lang->extension->errorTargetPathNotExists, $path) . '
          '; + $return->mkdirCommands .= "mkdir -p $path
          "; + $return->chmodCommands .= "sudo chmod -R 777 $path
          "; + } + $return->dirs2Created[] = $path; + } + } + + if($return->errors) $return->result = 'fail'; + $return->mkdirCommands = str_replace('/', DIRECTORY_SEPARATOR, $return->mkdirCommands); + $return->errors .= $this->lang->extension->executeCommands . $return->mkdirCommands; + if(PHP_OS == 'Linux') $return->errors .= $return->chmodCommands; + return $return; + } + + /** + * Check the extension's version is compatibility for zentao version + * + * @param string $version + * @access public + * @return bool + */ + public function checkVersion($version) + { + if($version == 'all') return true; + $version = explode(',', $version); + if(in_array($this->config->version, $version)) return true; + return false; + } + + /** + * Check files in the package conflicts with exists files or not. + * + * @param string $extension + * @param string $type + * @param bool $isCheck + * @access public + * @return object + */ + public function checkFile($extension) + { + $return->result = 'ok'; + $return->error = ''; + + $extensionFiles = $this->getFilesFromPackage($extension); + $appRoot = $this->app->getAppRoot(); + foreach($extensionFiles as $extensionFile) + { + $compareFile = $appRoot . str_replace(realpath("ext/$extension") . '/', '', $extensionFile); + if(!file_exists($compareFile)) continue; + if(md5_file($extensionFile) != md5_file($compareFile)) $return->error .= $compareFile . '
          '; + } + + if($return->error != '') $return->result = 'fail'; + return $return; + } + + /** + * Extract an extension. + * + * @param string $extension + * @access public + * @return object + */ + public function extractPackage($extension) + { + $return->result = 'ok'; + $return->error = ''; + + /* try remove pre extracted files. */ + $extensionPath = "ext/$extension"; + if(is_dir($extensionPath)) $this->classFile->removeDir($extensionPath); + + /* Extract files. */ + $packageFile = $this->getPackageFile($extension); + $this->app->loadClass('pclzip', true); + $zip = new pclzip($packageFile); + $files = $zip->listContent(); + $removePath = $files[0]['filename']; + if($zip->extract(PCLZIP_OPT_PATH, $extensionPath, PCLZIP_OPT_REMOVE_PATH, $removePath) == 0) + { + $return->result = 'fail'; + $return->error = $zip->errorInfo(true); + } + + return $return; + } + + /** + * Copy package files. + * + * @param int $extension + * @access public + * @return array + */ + public function copyPackageFiles($extension) + { + $appRoot = $this->app->getAppRoot(); + $extensionDir = "ext/$extension/"; + $pathes = scandir($extensionDir); + $copiedFiles = array(); + + foreach($pathes as $path) + { + if($path == 'db' or $path == 'doc' or $path == 'hook' or $path == '..' or $path == '.') continue; + $copiedFiles = $this->classFile->copyDir($extensionDir . $path, $appRoot . $path); + } + foreach($copiedFiles as $key => $copiedFile) + { + $copiedFiles[$copiedFile] = md5_file($copiedFile); + unset($copiedFiles[$key]); + } + return $copiedFiles; + } + + /** + * Remove an extension. + * + * @param string $extension + * @access public + * @return array the remove commands need executed manually. + */ + public function removePackage($extension) + { + $extension = $this->getInfoFromDB($extension); + $dirs = json_decode($extension->dirs); + $files = json_decode($extension->files); + $appRoot = $this->app->getAppRoot(); + $removeCommands = array(); + + /* Remove files first. */ + if($files) + { + foreach($files as $file => $savedMD5) + { + $file = $appRoot . $file; + if(!file_exists($file)) continue; + + if(md5_file($file) != $savedMD5) + { + $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $file #changed" : "del $file :changed"; + } + elseif(!@unlink($file)) + { + $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $file" : "del $file"; + } + } + } + + /* Then remove dirs. */ + if($dirs) + { + rsort($dirs); // remove from the lower level directory. + foreach($dirs as $dir) + { + if(!@rmdir($appRoot . $dir)) $removeCommands[] = "rmdir $appRoot$dir"; + } + } + + /* Clean model cache files. */ + $this->cleanModelCache(); + + return $removeCommands; + } + + /** + * Clean model cache files. + * + * @access public + * @return void + */ + public function cleanModelCache() + { + $modelCacheFiles = glob($this->app->getTmpRoot() . 'model/*'); + foreach($modelCacheFiles as $cacheFile) @unlink($cacheFile); + } + + /** + * Erase an extension's package file. + * + * @param string $extension + * @access public + * @return array the remove commands need executed manually. + */ + public function erasePackage($extension) + { + $removeCommands = array(); + + $this->dao->delete()->from(TABLE_EXTENSION)->where('code')->eq($extension)->exec(); + + /* Remove the zip file. */ + $packageFile = $this->getPackageFile($extension); + if(file_exists($packageFile) and !@unlink($packageFile)) + { + $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $packageFile" : "del $packageFile"; + } + + /* Remove the extracted files. */ + $extractedDir = realpath("ext/$extension"); + if($extractedDir != '/' and !$this->classFile->removeDir($extractedDir)) + { + $removeCommands[] = PHP_OS == 'Linux' ? "rm -fr $extractedDir" : "rmdir $extractedDir /s"; + } + + return $removeCommands; + } + + /** + * Judge need execute db install or not. + * + * @param string $extension + * @param string $method + * @access public + * @return bool + */ + public function needExecuteDB($extension, $method = 'install') + { + return file_exists($this->getDBFile($extension, $method)); + } + + /** + * Install the db. + * + * @param int $extension + * @access public + * @return object + */ + public function executeDB($extension, $method = 'install') + { + $return->result = 'ok'; + $return->error = ''; + + $dbFile = $this->getDBFile($extension, $method); + if(!file_exists($dbFile)) return $return; + + $sqls = file_get_contents($this->getDBFile($extension, $method)); + $sqls = explode(';', $sqls); + + foreach($sqls as $sql) + { + $sql = trim($sql); + if(empty($sql)) continue; + $sql = str_replace('zt_', $this->config->db->prefix, $sql); + + try + { + $this->dbh->query($sql); + } + catch (PDOException $e) + { + $return->error .= '

          ' . $e->getMessage() . "
          THE SQL IS: $sql

          "; + } + } + if($return->error) $return->result = 'fail'; + return $return; + } + + /** + * Save the extension to database. + * + * @param string $extension the extension code + * @param string $type the extension type + * @access public + * @return void + */ + public function saveExtension($extension, $type) + { + $code = $extension; + $extension = $this->getInfoFromPackage($extension); + $extension->status = 'available'; + $extension->code = $code; + $extension->type = $type; + $this->dao->replace(TABLE_EXTENSION)->data($extension)->exec(); + } + + /** + * Update an extension. + * + * @param string $extension + * @param string $status + * @param array $files + * @access public + * @return void + */ + public function updateExtension($extension, $data) + { + $data = (object)$data; + $appRoot = $this->app->getAppRoot(); + + if(isset($data->dirs)) + { + if($data->dirs) + { + foreach($data->dirs as $key => $dir) + { + $data->dirs[$key] = str_replace($appRoot, '', $dir); + } + } + $data->dirs = json_encode($data->dirs); + } + + if(isset($data->files)) + { + foreach($data->files as $fullFilePath => $md5) + { + $relativeFilePath = str_replace($appRoot, '', $fullFilePath); + $data->files[$relativeFilePath] = $md5; + unset($data->files[$fullFilePath]); + } + $data->files = json_encode($data->files); + } + return $this->dao->update(TABLE_EXTENSION)->data($data)->where('code')->eq($extension)->exec(); + } +} diff --git a/module/extension/view/activate.html.php b/module/extension/view/activate.html.php index 182554d07e..cf765f2f0d 100644 --- a/module/extension/view/activate.html.php +++ b/module/extension/view/activate.html.php @@ -1,33 +1,33 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - {$header->title}"; - echo "

          " . html::commonButton($lang->extension->viewInstalled, 'onclick=parent.location.href="' . inlink('browse', 'type=installed') . '"') . '

          '; - } - ?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + {$header->title}"; + echo "

          " . html::commonButton($lang->extension->viewInstalled, 'onclick=parent.location.href="' . inlink('browse', 'type=installed') . '"') . '

          '; + } + ?> +
          + + diff --git a/module/extension/view/browse.html.php b/module/extension/view/browse.html.php index 4a1503063f..acad80a73e 100644 --- a/module/extension/view/browse.html.php +++ b/module/extension/view/browse.html.php @@ -1,52 +1,52 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
          name";?>
          -
          desc;?>
          -
          - extension->version}: {$extension->version} "; - echo "{$lang->extension->author}: {$extension->author} "; - ?> -
          -
          - code"), $lang->extension->deactivate, '', "class='button-c iframe'"); - $activateCode = html::a(inlink('activate', "extension=$extension->code"), $lang->extension->activate, '', "class='button-c iframe'"); - $uninstallCode = html::a(inlink('uninstall', "extension=$extension->code"), $lang->extension->uninstall, '', "class='button-c iframe'"); - $installCode = html::a(inlink('install', "extension=$extension->code"), $lang->extension->install, '', "class='button-c iframe'"); - $eraseCode = html::a(inlink('erase', "extension=$extension->code"), $lang->extension->erase, '', "class='button-c iframe'"); - - if($extension->status == 'installed' and !empty($extension->upgradeLink)) - { - echo html::a($extension->upgradeLink, $lang->extension->upgrade, '', "class='button-c iframe'"); - } - - if($extension->type != 'patch') - { - if($extension->status == 'installed') echo $deactivateCode . $uninstallCode; - if($extension->status == 'deactivated') echo $activateCode . $uninstallCode; - if($extension->status == 'available') echo $installCode . $eraseCode; - } - echo html::a($extension->site, $lang->extension->site, '_blank', 'class=button-c'); - ?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
          name";?>
          +
          desc;?>
          +
          + extension->version}: {$extension->version} "; + echo "{$lang->extension->author}: {$extension->author} "; + ?> +
          +
          + code"), $lang->extension->deactivate, '', "class='button-c iframe'"); + $activateCode = html::a(inlink('activate', "extension=$extension->code"), $lang->extension->activate, '', "class='button-c iframe'"); + $uninstallCode = html::a(inlink('uninstall', "extension=$extension->code"), $lang->extension->uninstall, '', "class='button-c iframe'"); + $installCode = html::a(inlink('install', "extension=$extension->code"), $lang->extension->install, '', "class='button-c iframe'"); + $eraseCode = html::a(inlink('erase', "extension=$extension->code"), $lang->extension->erase, '', "class='button-c iframe'"); + + if($extension->status == 'installed' and !empty($extension->upgradeLink)) + { + echo html::a($extension->upgradeLink, $lang->extension->upgrade, '', "class='button-c iframe'"); + } + + if($extension->type != 'patch') + { + if($extension->status == 'installed') echo $deactivateCode . $uninstallCode; + if($extension->status == 'deactivated') echo $activateCode . $uninstallCode; + if($extension->status == 'available') echo $installCode . $eraseCode; + } + echo html::a($extension->site, $lang->extension->site, '_blank', 'class=button-c'); + ?> +
          + + diff --git a/module/extension/view/checkscore.html.php b/module/extension/view/checkscore.html.php index 5b1059551e..4e863989e2 100644 --- a/module/extension/view/checkscore.html.php +++ b/module/extension/view/checkscore.html.php @@ -1,28 +1,28 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - - {$lang->extension->needSorce}"; - echo "

          $error

          "; - ?> - -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + + {$lang->extension->needSorce}"; + echo "

          $error

          "; + ?> + +
          + + diff --git a/module/extension/view/deactivate.html.php b/module/extension/view/deactivate.html.php index 044b00dc2f..d56306f89a 100644 --- a/module/extension/view/deactivate.html.php +++ b/module/extension/view/deactivate.html.php @@ -1,31 +1,31 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - {$header->title}"; - if($removeCommands) - { - echo "

          {$lang->extension->unremovedFiles}

          "; - echo join($removeCommands, '
          '); - } - echo "

          " . html::commonButton($lang->extension->viewDeactivated, 'onclick=parent.location.href="' . inlink('browse', 'type=deactivated') . '"') . '

          '; - ?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + {$header->title}"; + if($removeCommands) + { + echo "

          {$lang->extension->unremovedFiles}

          "; + echo join($removeCommands, '
          '); + } + echo "

          " . html::commonButton($lang->extension->viewDeactivated, 'onclick=parent.location.href="' . inlink('browse', 'type=deactivated') . '"') . '

          '; + ?> +
          + + diff --git a/module/extension/view/erase.html.php b/module/extension/view/erase.html.php index fc8a2ca608..58978f7183 100644 --- a/module/extension/view/erase.html.php +++ b/module/extension/view/erase.html.php @@ -1,31 +1,31 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - {$header->title}"; - if($removeCommands) - { - echo "

          {$lang->extension->unremovedFiles}

          "; - echo join($removeCommands, '
          '); - } - echo "

          " . html::commonButton($lang->extension->viewAvailable, 'onclick=parent.location.href="' . inlink('browse', 'type=available') . '"') . '

          '; - ?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + {$header->title}"; + if($removeCommands) + { + echo "

          {$lang->extension->unremovedFiles}

          "; + echo join($removeCommands, '
          '); + } + echo "

          " . html::commonButton($lang->extension->viewAvailable, 'onclick=parent.location.href="' . inlink('browse', 'type=available') . '"') . '

          '; + ?> +
          + + diff --git a/module/extension/view/install.html.php b/module/extension/view/install.html.php index 888a207ede..c29314438c 100644 --- a/module/extension/view/install.html.php +++ b/module/extension/view/install.html.php @@ -1,49 +1,49 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - - {$lang->extension->installFailed}"; - echo "

          $error

          "; - echo html::commonButton($lang->extension->refreshPage, 'onclick=location.href=location.href'); - ?> - - {$lang->extension->license}"; - echo html::textarea('license', $license) . '
          '; - echo '

          ' . html::a($agreeLink, $lang->extension->agreeLicense) . '

          '; - ?> - - {$lang->extension->successDownloadedPackage}"; - echo "

          {$lang->extension->successCopiedFiles}

          "; - echo '
            '; - foreach($files as $fileName => $md5) - { - echo "
          • $fileName
          • "; - } - echo '
          '; - echo "

          {$lang->extension->successInstallDB}

          "; - echo "

          {$lang->extension->installFinished}

          "; - echo "

          " . html::commonButton($lang->extension->viewInstalled, 'onclick=parent.location.href="' . inlink('browse') . '"') . '

          '; - ?> - -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + + {$lang->extension->installFailed}"; + echo "

          $error

          "; + echo html::commonButton($lang->extension->refreshPage, 'onclick=location.href=location.href'); + ?> + + {$lang->extension->license}"; + echo html::textarea('license', $license) . '
          '; + echo '

          ' . html::a($agreeLink, $lang->extension->agreeLicense) . '

          '; + ?> + + {$lang->extension->successDownloadedPackage}"; + echo "

          {$lang->extension->successCopiedFiles}

          "; + echo '
            '; + foreach($files as $fileName => $md5) + { + echo "
          • $fileName
          • "; + } + echo '
          '; + echo "

          {$lang->extension->successInstallDB}

          "; + echo "

          {$lang->extension->installFinished}

          "; + echo "

          " . html::commonButton($lang->extension->viewInstalled, 'onclick=parent.location.href="' . inlink('browse') . '"') . '

          '; + ?> + +
          + + diff --git a/module/extension/view/obtain.html.php b/module/extension/view/obtain.html.php index ae754959a7..1fca0f9619 100644 --- a/module/extension/view/obtain.html.php +++ b/module/extension/view/obtain.html.php @@ -1,113 +1,113 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
          -
          extension->obtain;?>
          -
          - " . html::a(inlink('obtain', 'type=byUpdatedTime'), $lang->extension->byUpdatedTime) . '
          '; - echo "" . html::a(inlink('obtain', 'type=byAddedTime'), $lang->extension->byAddedTime) . '
          '; - echo "" . html::a(inlink('obtain', 'type=byDownloads'), $lang->extension->byDownloads) . '
          '; - ?> -
          -
          extension->bySearch;?>
          -
          -
          '> - post->key, "class='text-1'") . html::submitButton($lang->extension->bySearch);?> -
          -
          -
          extension->byCategory;?>
          -
          - extension->errorGetModules);?> -
          -
          - - - currentRelease; - $latestRelease = $extension->latestRelease; - ?> - - - - - -
          -
          name . "($currentRelease->releaseVersion)";?>
          -
          - releaseVersion != $currentRelease->releaseVersion) - { - printf($lang->extension->latest, $latestRelease->viewLink, $latestRelease->releaseVersion, $latestRelease->zentaoVersion); - }?> -
          -
          -
          abstract;?>
          -
          - extension->author}: {$extension->author} "; - echo "{$lang->extension->downloads}: {$extension->downloads} "; - echo "{$lang->extension->compatible}: {$lang->extension->compatibleList[$currentRelease->compatible]} "; - echo "{$lang->extension->grade}: ", html::printStars($extension->stars); - ?> -
          -
          - code&downLink=" . helper::safe64Encode($currentRelease->downLink) . "&md5={$currentRelease->md5}&type=$extension->type&&overridePackage=no&ignoreCompitable=yes"); - echo html::a($extension->viewLink, $lang->extension->view, '', 'class="button-c extension"'); - if($currentRelease->public) - { - if($extension->type != 'computer' and $extension->type != 'mobile') - { - if(isset($installeds[$extension->code])) - { - if($installeds[$extension->code]->version != $extension->latestRelease->releaseVersion) - { - $upgradeLink = inlink('upgrade', "extension=$extension->code&downLink=" . helper::safe64Encode($currentRelease->downLink) . "&md5=$currentRelease->md5&type=$extension->type"); - echo html::a($upgradeLink, $lang->extension->upgrade, '', 'class="iframe button-c"'); - } - else - { - echo html::commonButton($lang->extension->installed, "disabled='disabled' style='color:gray'"); - } - } - else - { - $label = $currentRelease->compatible ? $lang->extension->installAuto : $lang->extension->installForce; - echo html::a($installLink, $label, '', 'class="iframe button-c"'); - } - } - } - echo html::a($currentRelease->downLink, $lang->extension->downloadAB, '', 'class="manual button-c"'); - echo html::a($extension->site, $lang->extension->site, '_blank', 'class=button-c'); - ?> -
          - - show();?> - -
          extension->errorOccurs;?>
          -
          extension->errorGetExtensions;?>
          - -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
          +
          extension->obtain;?>
          +
          + " . html::a(inlink('obtain', 'type=byUpdatedTime'), $lang->extension->byUpdatedTime) . '
          '; + echo "" . html::a(inlink('obtain', 'type=byAddedTime'), $lang->extension->byAddedTime) . '
          '; + echo "" . html::a(inlink('obtain', 'type=byDownloads'), $lang->extension->byDownloads) . '
          '; + ?> +
          +
          extension->bySearch;?>
          +
          +
          '> + post->key, "class='text-1'") . html::submitButton($lang->extension->bySearch);?> +
          +
          +
          extension->byCategory;?>
          +
          + extension->errorGetModules);?> +
          +
          + + + currentRelease; + $latestRelease = $extension->latestRelease; + ?> + + + + + +
          +
          name . "($currentRelease->releaseVersion)";?>
          +
          + releaseVersion != $currentRelease->releaseVersion) + { + printf($lang->extension->latest, $latestRelease->viewLink, $latestRelease->releaseVersion, $latestRelease->zentaoVersion); + }?> +
          +
          +
          abstract;?>
          +
          + extension->author}: {$extension->author} "; + echo "{$lang->extension->downloads}: {$extension->downloads} "; + echo "{$lang->extension->compatible}: {$lang->extension->compatibleList[$currentRelease->compatible]} "; + echo "{$lang->extension->grade}: ", html::printStars($extension->stars); + ?> +
          +
          + code&downLink=" . helper::safe64Encode($currentRelease->downLink) . "&md5={$currentRelease->md5}&type=$extension->type&&overridePackage=no&ignoreCompitable=yes"); + echo html::a($extension->viewLink, $lang->extension->view, '', 'class="button-c extension"'); + if($currentRelease->public) + { + if($extension->type != 'computer' and $extension->type != 'mobile') + { + if(isset($installeds[$extension->code])) + { + if($installeds[$extension->code]->version != $extension->latestRelease->releaseVersion) + { + $upgradeLink = inlink('upgrade', "extension=$extension->code&downLink=" . helper::safe64Encode($currentRelease->downLink) . "&md5=$currentRelease->md5&type=$extension->type"); + echo html::a($upgradeLink, $lang->extension->upgrade, '', 'class="iframe button-c"'); + } + else + { + echo html::commonButton($lang->extension->installed, "disabled='disabled' style='color:gray'"); + } + } + else + { + $label = $currentRelease->compatible ? $lang->extension->installAuto : $lang->extension->installForce; + echo html::a($installLink, $label, '', 'class="iframe button-c"'); + } + } + } + echo html::a($currentRelease->downLink, $lang->extension->downloadAB, '', 'class="manual button-c"'); + echo html::a($extension->site, $lang->extension->site, '_blank', 'class=button-c'); + ?> +
          + + show();?> + +
          extension->errorOccurs;?>
          +
          extension->errorGetExtensions;?>
          + +
          + + diff --git a/module/extension/view/uninstall.html.php b/module/extension/view/uninstall.html.php index b038b89f4d..e6952fdb07 100644 --- a/module/extension/view/uninstall.html.php +++ b/module/extension/view/uninstall.html.php @@ -1,31 +1,31 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - {$header->title}"; - if($removeCommands) - { - echo "

          {$lang->extension->unremovedFiles}

          "; - echo join($removeCommands, '
          '); - } - echo "

          " . html::commonButton($lang->extension->viewAvailable, 'onclick=parent.location.href="' . inlink('browse', 'type=available') . '"') . '

          '; - ?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + {$header->title}"; + if($removeCommands) + { + echo "

          {$lang->extension->unremovedFiles}

          "; + echo join($removeCommands, '
          '); + } + echo "

          " . html::commonButton($lang->extension->viewAvailable, 'onclick=parent.location.href="' . inlink('browse', 'type=available') . '"') . '

          '; + ?> +
          + + diff --git a/module/extension/view/upload.html.php b/module/extension/view/upload.html.php index 42eb9166de..c5d937755f 100644 --- a/module/extension/view/upload.html.php +++ b/module/extension/view/upload.html.php @@ -1,19 +1,19 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - extension->install);?> -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + extension->install);?> +
          + + diff --git a/module/extension/view/waring.htm.php b/module/extension/view/waring.htm.php index 14e744c439..00c2c98eea 100644 --- a/module/extension/view/waring.htm.php +++ b/module/extension/view/waring.htm.php @@ -1,29 +1,29 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          title;?>
          - - {$lang->extension->waringInstall}"; - echo "

          $error

          "; - echo html::commonButton($lang->extension->refreshPage, 'onclick=location.href=location.href'); - ?> - -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          title;?>
          + + {$lang->extension->waringInstall}"; + echo "

          $error

          "; + echo html::commonButton($lang->extension->refreshPage, 'onclick=location.href=location.href'); + ?> + +
          + + diff --git a/module/file/control.php b/module/file/control.php index 6696f32a47..375164803b 100644 --- a/module/file/control.php +++ b/module/file/control.php @@ -1,266 +1,266 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -class file extends control -{ - /** - * Build the upload form. - * - * @param int $fileCount - * @param float $percent - * @access public - * @return void - */ - public function buildForm($fileCount = 2, $percent = 0.9) - { - if(!file_exists($this->file->savePath)) - { - printf($this->lang->file->errorNotExists, $this->file->savePath); - return false; - } - elseif(!is_writable($this->file->savePath)) - { - printf($this->lang->file->errorCanNotWrite, $this->file->savePath, $this->file->savePath); - return false; - } - $this->view->fileCount = $fileCount; - $this->view->percent = $percent; - $this->display(); - } - - /** - * AJAX: get upload request from the web editor. - * - * @access public - * @return void - */ - public function ajaxUpload() - { - $file = $this->file->getUpload('imgFile'); - $file = $file[0]; - if($file) - { - if(@move_uploaded_file($file['tmpname'], $this->file->savePath . $file['pathname'])) - { - $url = $this->file->webPath . $file['pathname']; - - $file['addedBy'] = $this->app->user->account; - $file['addedDate'] = helper::today(); - unset($file['tmpname']); - $this->dao->insert(TABLE_FILE)->data($file)->exec(); - - die(json_encode(array('error' => 0, 'url' => $url))); - } - else - { - $error = strip_tags(sprintf($this->lang->file->errorCanNotWrite, $this->file->savePath, $this->file->savePath)); - die(json_encode(array('error' => 1, 'message' => $error))); - } - } - } - - /** - * Down a file. - * - * @param int $fileID - * @param string $mouse - * @access public - * @return void - */ - public function download($fileID, $mouse = '') - { - $file = $this->file->getById($fileID); - - /* Judge the mode, down or open. */ - $mode = 'down'; - $fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html'; - if(stripos($fileTypes, $file->extension) !== false and $mouse == 'left') $mode = 'open'; - - /* If the mode is open, locate directly. */ - if($mode == 'open') - { - if(file_exists($file->realPath))$this->locate($file->webPath); - $this->app->error("The file you visit $fileID not found.", __FILE__, __LINE__, true); - } - else - { - /* Down the file. */ - if(file_exists($file->realPath)) - { - $fileName = $file->title . '.' . $file->extension; - $fileData = file_get_contents($file->realPath); - $this->sendDownHeader($fileName, $file->extension, $fileData); - } - else - { - $this->app->error("The file you visit $fileID not found.", __FILE__, __LINE__, true); - } - } - } - - /** - * Export as csv format. - * - * @access public - * @return void - */ - public function export2CSV() - { - $this->view->fields = $this->post->fields; - $this->view->rows = $this->post->rows; - $output = $this->parse('file', 'export2csv'); - - /* If the language is zh-cn, convert to gbk. */ - $clientLang = $this->app->getClientLang(); - if($clientLang == 'zh-cn') - { - if(function_exists('mb_convert_encoding')) - { - $output = @mb_convert_encoding($output, 'gbk', 'utf-8'); - } - elseif(function_exists('iconv')) - { - $output = @iconv('utf-8', 'gbk', $output); - } - } - - $this->sendDownHeader($this->post->fileName, 'csv', $output); - } - - /** - * export as xml format - * - * @access public - * @return void - */ - public function export2XML() - { - $this->view->fields = $this->post->fields; - $this->view->rows = $this->post->rows; - - $output = $this->parse('file', 'export2XML'); - - $this->sendDownHeader($this->post->fileName, 'xml', $output); - } - - /** - * export as html format - * - * @access public - * @return void - */ - public function export2HTML() - { - $this->view->fields = $this->post->fields; - $this->view->rows = $this->post->rows; - $this->view->fileName = $this->post->fileName; - $output = $this->parse('file', 'export2Html'); - - $this->sendDownHeader($this->post->fileName, 'html', $output); - } - - /** - * Send the download header to the client. - * - * @param string $fileName - * @param string $extension - * @access public - * @return void - */ - public function sendDownHeader($fileName, $fileType, $content) - { - /* Set the downloading cookie, thus the export form page can use it to judge whether to close the window or not. */ - setcookie('downloading', 1); - - /* Append the extension name auto. */ - $extension = '.' . $fileType; - if(strpos($fileName, $extension) === false) $fileName .= $extension; - - /* urlencode the filename for ie. */ - if(strpos($this->server->http_user_agent, 'MSIE') !== false) $fileName = urlencode($fileName); - - /* Judge the content type. */ - $mimes = $this->config->file->mimes; - $contentType = isset($mimes[$fileType]) ? $mimes[$fileType] : $mimes['default']; - - header("Content-type: $contentType"); - header("Content-Disposition: attachment; filename=\"$fileName\""); - header("Pragma: no-cache"); - header("Expires: 0"); - die($content); - } - - /** - * Delete a file. - * - * @param int $fileID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($fileID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->file->confirmDelete, inlink('delete', "fileID=$fileID&confirm=yes"))); - } - else - { - $file = $this->file->getById($fileID); - $this->dao->delete()->from(TABLE_FILE)->where('id')->eq($fileID)->exec(); - $this->loadModel('action')->create($file->objectType, $file->objectID, 'deletedFile', '', $extra=$file->title); - @unlink($file->realPath); - die(js::reload('parent')); - } - } - - /** - * Print files. - * - * @param array $files - * @param string $fieldset - * @access public - * @return void - */ - public function printFiles($files, $fieldset) - { - $this->view->files = $files; - $this->view->fieldset = $fieldset; - $this->display(); - } - - /** - * Edit file's name. - * - * @param int $fileID - * @access public - * @return void - */ - public function edit($fileID) - { - if($_POST) - { - $this->app->loadLang('action'); - $file = $this->file->getByID($fileID); - $this->dao->update(TABLE_FILE)->set('title')->eq($this->post->fileName)->where('id')->eq($fileID)->exec(); - - $extension = "." . $file->extension; - $actionID = $this->loadModel('action')->create($file->objectType, $file->objectID, 'editfile', '', $this->post->fileName . $extension); - $changes[] = array('field' => 'fileName', 'old' => $file->title . $extension, 'new' => $this->post->fileName . $extension); - $this->action->logHistory($actionID, $changes); - - die(js::reload('parent.parent')); - } - - $this->view->file = $this->file->getById($fileID); - $this->display(); - } -} + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +class file extends control +{ + /** + * Build the upload form. + * + * @param int $fileCount + * @param float $percent + * @access public + * @return void + */ + public function buildForm($fileCount = 2, $percent = 0.9) + { + if(!file_exists($this->file->savePath)) + { + printf($this->lang->file->errorNotExists, $this->file->savePath); + return false; + } + elseif(!is_writable($this->file->savePath)) + { + printf($this->lang->file->errorCanNotWrite, $this->file->savePath, $this->file->savePath); + return false; + } + $this->view->fileCount = $fileCount; + $this->view->percent = $percent; + $this->display(); + } + + /** + * AJAX: get upload request from the web editor. + * + * @access public + * @return void + */ + public function ajaxUpload() + { + $file = $this->file->getUpload('imgFile'); + $file = $file[0]; + if($file) + { + if(@move_uploaded_file($file['tmpname'], $this->file->savePath . $file['pathname'])) + { + $url = $this->file->webPath . $file['pathname']; + + $file['addedBy'] = $this->app->user->account; + $file['addedDate'] = helper::today(); + unset($file['tmpname']); + $this->dao->insert(TABLE_FILE)->data($file)->exec(); + + die(json_encode(array('error' => 0, 'url' => $url))); + } + else + { + $error = strip_tags(sprintf($this->lang->file->errorCanNotWrite, $this->file->savePath, $this->file->savePath)); + die(json_encode(array('error' => 1, 'message' => $error))); + } + } + } + + /** + * Down a file. + * + * @param int $fileID + * @param string $mouse + * @access public + * @return void + */ + public function download($fileID, $mouse = '') + { + $file = $this->file->getById($fileID); + + /* Judge the mode, down or open. */ + $mode = 'down'; + $fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html'; + if(stripos($fileTypes, $file->extension) !== false and $mouse == 'left') $mode = 'open'; + + /* If the mode is open, locate directly. */ + if($mode == 'open') + { + if(file_exists($file->realPath))$this->locate($file->webPath); + $this->app->error("The file you visit $fileID not found.", __FILE__, __LINE__, true); + } + else + { + /* Down the file. */ + if(file_exists($file->realPath)) + { + $fileName = $file->title . '.' . $file->extension; + $fileData = file_get_contents($file->realPath); + $this->sendDownHeader($fileName, $file->extension, $fileData); + } + else + { + $this->app->error("The file you visit $fileID not found.", __FILE__, __LINE__, true); + } + } + } + + /** + * Export as csv format. + * + * @access public + * @return void + */ + public function export2CSV() + { + $this->view->fields = $this->post->fields; + $this->view->rows = $this->post->rows; + $output = $this->parse('file', 'export2csv'); + + /* If the language is zh-cn, convert to gbk. */ + $clientLang = $this->app->getClientLang(); + if($clientLang == 'zh-cn') + { + if(function_exists('mb_convert_encoding')) + { + $output = @mb_convert_encoding($output, 'gbk', 'utf-8'); + } + elseif(function_exists('iconv')) + { + $output = @iconv('utf-8', 'gbk', $output); + } + } + + $this->sendDownHeader($this->post->fileName, 'csv', $output); + } + + /** + * export as xml format + * + * @access public + * @return void + */ + public function export2XML() + { + $this->view->fields = $this->post->fields; + $this->view->rows = $this->post->rows; + + $output = $this->parse('file', 'export2XML'); + + $this->sendDownHeader($this->post->fileName, 'xml', $output); + } + + /** + * export as html format + * + * @access public + * @return void + */ + public function export2HTML() + { + $this->view->fields = $this->post->fields; + $this->view->rows = $this->post->rows; + $this->view->fileName = $this->post->fileName; + $output = $this->parse('file', 'export2Html'); + + $this->sendDownHeader($this->post->fileName, 'html', $output); + } + + /** + * Send the download header to the client. + * + * @param string $fileName + * @param string $extension + * @access public + * @return void + */ + public function sendDownHeader($fileName, $fileType, $content) + { + /* Set the downloading cookie, thus the export form page can use it to judge whether to close the window or not. */ + setcookie('downloading', 1); + + /* Append the extension name auto. */ + $extension = '.' . $fileType; + if(strpos($fileName, $extension) === false) $fileName .= $extension; + + /* urlencode the filename for ie. */ + if(strpos($this->server->http_user_agent, 'MSIE') !== false) $fileName = urlencode($fileName); + + /* Judge the content type. */ + $mimes = $this->config->file->mimes; + $contentType = isset($mimes[$fileType]) ? $mimes[$fileType] : $mimes['default']; + + header("Content-type: $contentType"); + header("Content-Disposition: attachment; filename=\"$fileName\""); + header("Pragma: no-cache"); + header("Expires: 0"); + die($content); + } + + /** + * Delete a file. + * + * @param int $fileID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($fileID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->file->confirmDelete, inlink('delete', "fileID=$fileID&confirm=yes"))); + } + else + { + $file = $this->file->getById($fileID); + $this->dao->delete()->from(TABLE_FILE)->where('id')->eq($fileID)->exec(); + $this->loadModel('action')->create($file->objectType, $file->objectID, 'deletedFile', '', $extra=$file->title); + @unlink($file->realPath); + die(js::reload('parent')); + } + } + + /** + * Print files. + * + * @param array $files + * @param string $fieldset + * @access public + * @return void + */ + public function printFiles($files, $fieldset) + { + $this->view->files = $files; + $this->view->fieldset = $fieldset; + $this->display(); + } + + /** + * Edit file's name. + * + * @param int $fileID + * @access public + * @return void + */ + public function edit($fileID) + { + if($_POST) + { + $this->app->loadLang('action'); + $file = $this->file->getByID($fileID); + $this->dao->update(TABLE_FILE)->set('title')->eq($this->post->fileName)->where('id')->eq($fileID)->exec(); + + $extension = "." . $file->extension; + $actionID = $this->loadModel('action')->create($file->objectType, $file->objectID, 'editfile', '', $this->post->fileName . $extension); + $changes[] = array('field' => 'fileName', 'old' => $file->title . $extension, 'new' => $this->post->fileName . $extension); + $this->action->logHistory($actionID, $changes); + + die(js::reload('parent.parent')); + } + + $this->view->file = $this->file->getById($fileID); + $this->display(); + } +} diff --git a/module/file/lang/en.php b/module/file/lang/en.php index 637b4ff44e..a67e7218df 100644 --- a/module/file/lang/en.php +++ b/module/file/lang/en.php @@ -1,23 +1,23 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->file->common = 'File'; -$lang->file->download = 'Download'; -$lang->file->edit = 'Edit file name'; -$lang->file->inputFileName = 'Input file name'; -$lang->file->delete = 'Delete'; -$lang->file->export2CSV = 'Export CSV'; -$lang->file->ajaxUpload = 'AJAX: upload file from editor'; -$lang->file->label = 'Title: '; - -$lang->file->errorNotExists = "The directory '%s' is no exist"; -$lang->file->errorCanNotWrite = "The directory '%s' is unwritable, please change it's permission. Command in linux:sudo -R chmod 777 '%s'"; -$lang->file->confirmDelete = " Are you sure to delete this file?"; + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->file->common = 'File'; +$lang->file->download = 'Download'; +$lang->file->edit = 'Edit file name'; +$lang->file->inputFileName = 'Input file name'; +$lang->file->delete = 'Delete'; +$lang->file->export2CSV = 'Export CSV'; +$lang->file->ajaxUpload = 'AJAX: upload file from editor'; +$lang->file->label = 'Title: '; + +$lang->file->errorNotExists = "The directory '%s' is no exist"; +$lang->file->errorCanNotWrite = "The directory '%s' is unwritable, please change it's permission. Command in linux:sudo -R chmod 777 '%s'"; +$lang->file->confirmDelete = " Are you sure to delete this file?"; diff --git a/module/file/lang/zh-cn.php b/module/file/lang/zh-cn.php index 4d660244a4..69bcdb0c3d 100644 --- a/module/file/lang/zh-cn.php +++ b/module/file/lang/zh-cn.php @@ -1,23 +1,23 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->file->common = '附件'; -$lang->file->download = '下载附件'; -$lang->file->edit = '编辑附件名称'; -$lang->file->inputFileName = '请输入附件名称'; -$lang->file->delete = '删除附件'; -$lang->file->export2CSV = '导出CSV'; -$lang->file->ajaxUpload = '接口:编辑器上传附件'; -$lang->file->label = '标题:'; - -$lang->file->errorNotExists = "文件夹 '%s' 不存在"; -$lang->file->errorCanNotWrite = "文件夹 '%s' 不可写,请改变文件夹的权限。在linux中输入指令:sudo chmod -R 777 '%s'"; -$lang->file->confirmDelete = " 您确定删除该附件吗?"; + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->file->common = '附件'; +$lang->file->download = '下载附件'; +$lang->file->edit = '编辑附件名称'; +$lang->file->inputFileName = '请输入附件名称'; +$lang->file->delete = '删除附件'; +$lang->file->export2CSV = '导出CSV'; +$lang->file->ajaxUpload = '接口:编辑器上传附件'; +$lang->file->label = '标题:'; + +$lang->file->errorNotExists = "文件夹 '%s' 不存在"; +$lang->file->errorCanNotWrite = "文件夹 '%s' 不可写,请改变文件夹的权限。在linux中输入指令:sudo chmod -R 777 '%s'"; +$lang->file->confirmDelete = " 您确定删除该附件吗?"; diff --git a/module/file/lang/zh-tw.php b/module/file/lang/zh-tw.php index fc8b1333f4..336db4aa8c 100644 --- a/module/file/lang/zh-tw.php +++ b/module/file/lang/zh-tw.php @@ -1,23 +1,23 @@ - - * @package file - * @version $Id: zh-tw.php 2110 2011-09-22 01:22:13Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->file->common = '附件'; -$lang->file->download = '下載附件'; -$lang->file->edit = '編輯附件名稱'; -$lang->file->inputFileName = '請輸入附件名稱'; -$lang->file->delete = '刪除附件'; -$lang->file->export2CSV = '導出CSV'; -$lang->file->ajaxUpload = '介面:編輯器上傳附件'; -$lang->file->label = '標題:'; - -$lang->file->errorNotExists = "檔案夾 '%s' 不存在"; -$lang->file->errorCanNotWrite = "檔案夾 '%s' 不可寫,請改變檔案夾的權限。在linux中輸入指令:sudo chmod -R 777 '%s'"; -$lang->file->confirmDelete = " 您確定刪除該附件嗎?"; + + * @package file + * @version $Id: zh-tw.php 2110 2011-09-22 01:22:13Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->file->common = '附件'; +$lang->file->download = '下載附件'; +$lang->file->edit = '編輯附件名稱'; +$lang->file->inputFileName = '請輸入附件名稱'; +$lang->file->delete = '刪除附件'; +$lang->file->export2CSV = '導出CSV'; +$lang->file->ajaxUpload = '介面:編輯器上傳附件'; +$lang->file->label = '標題:'; + +$lang->file->errorNotExists = "檔案夾 '%s' 不存在"; +$lang->file->errorCanNotWrite = "檔案夾 '%s' 不可寫,請改變檔案夾的權限。在linux中輸入指令:sudo chmod -R 777 '%s'"; +$lang->file->confirmDelete = " 您確定刪除該附件嗎?"; diff --git a/module/file/model.php b/module/file/model.php index 7fba96b5a6..681f1b7d03 100644 --- a/module/file/model.php +++ b/module/file/model.php @@ -1,210 +1,210 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> -now = time(); - $this->setSavePath(); - $this->setWebPath(); - } - - /** - * Get files of an object. - * - * @param string $objectType - * @param string $objectID - * @access public - * @return array - */ - public function getByObject($objectType, $objectID) - { - return $this->dao->select('*')->from(TABLE_FILE)->where('objectType')->eq($objectType)->andWhere('objectID')->eq((int)$objectID)->orderBy('id')->fetchAll(); - } - - /** - * Get info of a file. - * - * @param int $fileID - * @access public - * @return object - */ - public function getById($fileID) - { - $file = $this->dao->findById($fileID)->from(TABLE_FILE)->fetch(); - $file->webPath = $this->webPath . $file->pathname; - $file->realPath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; - return $file; - } - - /** - * Save upload. - * - * @param string $objectType - * @param string $objectID - * @param string $extra - * @access public - * @return array - */ - public function saveUpload($objectType = '', $objectID = '', $extra = '') - { - $fileTitles = array(); - $now = helper::today(); - $files = $this->getUpload(); - - foreach($files as $id => $file) - { - move_uploaded_file($file['tmpname'], $this->savePath . $file['pathname']); - $file['objectType'] = $objectType; - $file['objectID'] = $objectID; - $file['addedBy'] = $this->app->user->account; - $file['addedDate'] = $now; - $file['extra'] = $extra; - unset($file['tmpname']); - $this->dao->insert(TABLE_FILE)->data($file)->exec(); - $fileTitles[$this->dao->lastInsertId()] = $file['title']; - } - return $fileTitles; - } - - /** - * Get counts of uploaded files. - * - * @access public - * @return int - */ - public function getCount() - { - return count($this->getUpload()); - } - - /** - * Get info of uploaded files. - * - * @param string $htmlTagName - * @access public - * @return array - */ - public function getUpload($htmlTagName = 'files') - { - $files = array(); - if(!isset($_FILES[$htmlTagName])) return $files; - - /* If the file var name is an array. */ - if(is_array($_FILES[$htmlTagName]['name'])) - { - extract($_FILES[$htmlTagName]); - foreach($name as $id => $filename) - { - if(empty($filename)) continue; - $file['extension'] = $this->getExtension($filename); - $file['pathname'] = $this->setPathName($id, $file['extension']); - $file['title'] = !empty($_POST['labels'][$id]) ? htmlspecialchars($_POST['labels'][$id]) : str_replace('.' . $file['extension'], '', $filename); - $file['size'] = $size[$id]; - $file['tmpname'] = $tmp_name[$id]; - $files[] = $file; - } - } - else - { - if(empty($_FILES[$htmlTagName]['name'])) return $files; - extract($_FILES[$htmlTagName]); - $file['extension'] = $this->getExtension($name); - $file['pathname'] = $this->setPathName(0, $file['extension']); - $file['title'] = !empty($_POST['labels'][0]) ? htmlspecialchars($_POST['labels'][0]) : substr($name, 0, strpos($name, $file['extension']) - 1); - $file['size'] = $size; - $file['tmpname'] = $tmp_name; - return array($file); - } - return $files; - } - - /** - * Get extension of a file. - * - * @param string $filename - * @access public - * @return string - */ - public function getExtension($filename) - { - $extension = pathinfo($filename, PATHINFO_EXTENSION); - if(empty($extension)) return 'txt'; - if(strpos($this->config->file->dangers, $extension) !== false) return 'txt'; - return $extension; - } - - /** - * Set path name of the uploaded file to be saved. - * - * @param int $fileID - * @param string $extension - * @access public - * @return string - */ - public function setPathName($fileID, $extension) - { - $sessionID = session_id(); - $randString = substr($sessionID, mt_rand(0, strlen($sessionID) - 5), 3); - return date('Ym/dHis', $this->now) . $fileID . mt_rand(0, 10000) . $randString . '.' . $extension; - } - - /** - * Set save path. - * - * @access public - * @return void - */ - public function setSavePath() - { - $savePath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . date('Ym/', $this->now); - if(!file_exists($savePath)) @mkdir($savePath, 0777, true); - $this->savePath = dirname($savePath) . '/'; - } - - /** - * Set the web path of upload files. - * - * @access public - * @return void - */ - public function setWebPath() - { - $this->webPath = $this->app->getWebRoot() . "data/upload/{$this->app->company->id}/"; - } - - /** - * Insert the set image size code. - * - * @param string $content - * @param int $maxSize - * @access public - * @return string - */ - public function setImgSize($content, $maxSize = 0) - { - return str_replace('src="data/upload', 'onload="setImageSize(this,' . $maxSize . ' )" src="data/upload', $content); - } -} + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> +now = time(); + $this->setSavePath(); + $this->setWebPath(); + } + + /** + * Get files of an object. + * + * @param string $objectType + * @param string $objectID + * @access public + * @return array + */ + public function getByObject($objectType, $objectID) + { + return $this->dao->select('*')->from(TABLE_FILE)->where('objectType')->eq($objectType)->andWhere('objectID')->eq((int)$objectID)->orderBy('id')->fetchAll(); + } + + /** + * Get info of a file. + * + * @param int $fileID + * @access public + * @return object + */ + public function getById($fileID) + { + $file = $this->dao->findById($fileID)->from(TABLE_FILE)->fetch(); + $file->webPath = $this->webPath . $file->pathname; + $file->realPath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . $file->pathname; + return $file; + } + + /** + * Save upload. + * + * @param string $objectType + * @param string $objectID + * @param string $extra + * @access public + * @return array + */ + public function saveUpload($objectType = '', $objectID = '', $extra = '') + { + $fileTitles = array(); + $now = helper::today(); + $files = $this->getUpload(); + + foreach($files as $id => $file) + { + move_uploaded_file($file['tmpname'], $this->savePath . $file['pathname']); + $file['objectType'] = $objectType; + $file['objectID'] = $objectID; + $file['addedBy'] = $this->app->user->account; + $file['addedDate'] = $now; + $file['extra'] = $extra; + unset($file['tmpname']); + $this->dao->insert(TABLE_FILE)->data($file)->exec(); + $fileTitles[$this->dao->lastInsertId()] = $file['title']; + } + return $fileTitles; + } + + /** + * Get counts of uploaded files. + * + * @access public + * @return int + */ + public function getCount() + { + return count($this->getUpload()); + } + + /** + * Get info of uploaded files. + * + * @param string $htmlTagName + * @access public + * @return array + */ + public function getUpload($htmlTagName = 'files') + { + $files = array(); + if(!isset($_FILES[$htmlTagName])) return $files; + + /* If the file var name is an array. */ + if(is_array($_FILES[$htmlTagName]['name'])) + { + extract($_FILES[$htmlTagName]); + foreach($name as $id => $filename) + { + if(empty($filename)) continue; + $file['extension'] = $this->getExtension($filename); + $file['pathname'] = $this->setPathName($id, $file['extension']); + $file['title'] = !empty($_POST['labels'][$id]) ? htmlspecialchars($_POST['labels'][$id]) : str_replace('.' . $file['extension'], '', $filename); + $file['size'] = $size[$id]; + $file['tmpname'] = $tmp_name[$id]; + $files[] = $file; + } + } + else + { + if(empty($_FILES[$htmlTagName]['name'])) return $files; + extract($_FILES[$htmlTagName]); + $file['extension'] = $this->getExtension($name); + $file['pathname'] = $this->setPathName(0, $file['extension']); + $file['title'] = !empty($_POST['labels'][0]) ? htmlspecialchars($_POST['labels'][0]) : substr($name, 0, strpos($name, $file['extension']) - 1); + $file['size'] = $size; + $file['tmpname'] = $tmp_name; + return array($file); + } + return $files; + } + + /** + * Get extension of a file. + * + * @param string $filename + * @access public + * @return string + */ + public function getExtension($filename) + { + $extension = pathinfo($filename, PATHINFO_EXTENSION); + if(empty($extension)) return 'txt'; + if(strpos($this->config->file->dangers, $extension) !== false) return 'txt'; + return $extension; + } + + /** + * Set path name of the uploaded file to be saved. + * + * @param int $fileID + * @param string $extension + * @access public + * @return string + */ + public function setPathName($fileID, $extension) + { + $sessionID = session_id(); + $randString = substr($sessionID, mt_rand(0, strlen($sessionID) - 5), 3); + return date('Ym/dHis', $this->now) . $fileID . mt_rand(0, 10000) . $randString . '.' . $extension; + } + + /** + * Set save path. + * + * @access public + * @return void + */ + public function setSavePath() + { + $savePath = $this->app->getAppRoot() . "www/data/upload/{$this->app->company->id}/" . date('Ym/', $this->now); + if(!file_exists($savePath)) @mkdir($savePath, 0777, true); + $this->savePath = dirname($savePath) . '/'; + } + + /** + * Set the web path of upload files. + * + * @access public + * @return void + */ + public function setWebPath() + { + $this->webPath = $this->app->getWebRoot() . "data/upload/{$this->app->company->id}/"; + } + + /** + * Insert the set image size code. + * + * @param string $content + * @param int $maxSize + * @access public + * @return string + */ + public function setImgSize($content, $maxSize = 0) + { + return str_replace('src="data/upload', 'onload="setImageSize(this,' . $maxSize . ' )" src="data/upload', $content); + } +} diff --git a/module/file/view/edit.html.php b/module/file/view/edit.html.php index 254a280546..5a565ab6ad 100644 --- a/module/file/view/edit.html.php +++ b/module/file/view/edit.html.php @@ -1,41 +1,41 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          - - - - - -
          file->inputFileName;?>
          - title) . ".{$file->extension}";?> - -
          -
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          + + + + + +
          file->inputFileName;?>
          + title) . ".{$file->extension}";?> + +
          +
          + diff --git a/module/file/view/export.html.php b/module/file/view/export.html.php index dddb2964f8..63da5a10c5 100644 --- a/module/file/view/export.html.php +++ b/module/file/view/export.html.php @@ -1,51 +1,51 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -

          -
          - - - - - -
          export;?>
          - setFileName;?> - - exportFileTypeList);?> - -
          -
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +

          +
          + + + + + +
          export;?>
          + setFileName;?> + + exportFileTypeList);?> + +
          +
          + diff --git a/module/file/view/export2csv.html.php b/module/file/view/export2csv.html.php index 84593e9de6..51f3e347a5 100644 --- a/module/file/view/export2csv.html.php +++ b/module/file/view/export2csv.html.php @@ -1,24 +1,24 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - $fieldLabel) - { - isset($row->$fieldName) ? print(strip_tags($row->$fieldName)) : print(''); - echo '","'; - } - echo '"' . "\n"; -} + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + $fieldLabel) + { + isset($row->$fieldName) ? print(strip_tags($row->$fieldName)) : print(''); + echo '","'; + } + echo '"' . "\n"; +} diff --git a/module/file/view/export2html.html.php b/module/file/view/export2html.html.php index 16597ccd89..d174cd7155 100644 --- a/module/file/view/export2html.html.php +++ b/module/file/view/export2html.html.php @@ -1,44 +1,44 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -<?php echo $fileName;?> - - - - $fieldLabel\n"; - } - ?> - -\n"; - foreach($fields as $fieldName => $fieldLabel) - { - $fieldValue = isset($row->$fieldName) ? $row->$fieldName : ''; - echo "\n"; - } - echo "\n"; -} -?> -
          $fieldValue
          - - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +<?php echo $fileName;?> + + + + $fieldLabel\n"; + } + ?> + +\n"; + foreach($fields as $fieldName => $fieldLabel) + { + $fieldValue = isset($row->$fieldName) ? $row->$fieldName : ''; + echo "\n"; + } + echo "\n"; +} +?> +
          $fieldValue
          + + diff --git a/module/file/view/export2xml.html.php b/module/file/view/export2xml.html.php index 00db4d3de2..ac8059d1dc 100644 --- a/module/file/view/export2xml.html.php +++ b/module/file/view/export2xml.html.php @@ -1,36 +1,36 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> -\n";?> - - $fieldLabel) -{ - echo " <$fieldName>$fieldLabel\n"; -} -?> - - -\n"; - foreach($fields as $fieldName => $fieldLabel) - { - $fieldValue = isset($row->$fieldName) ? htmlspecialchars($row->$fieldName) : ''; - echo " <$fieldName>$fieldValue\n"; - } - echo " \n"; -} -?> - - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> +\n";?> + + $fieldLabel) +{ + echo " <$fieldName>$fieldLabel\n"; +} +?> + + +\n"; + foreach($fields as $fieldName => $fieldLabel) + { + $fieldValue = isset($row->$fieldName) ? htmlspecialchars($row->$fieldName) : ''; + echo " <$fieldName>$fieldValue\n"; + } + echo " \n"; +} +?> + + diff --git a/module/group/control.php b/module/group/control.php index cf3d6b0500..d0baf0b20f 100644 --- a/module/group/control.php +++ b/module/group/control.php @@ -1,224 +1,224 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -class group extends control -{ - /** - * Construct function. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('company')->setMenu(); - $this->loadModel('user'); - } - - /** - * Browse groups. - * - * @param int $companyID - * @access public - * @return void - */ - public function browse($companyID = 0) - { - if($companyID == 0) $companyID = $this->app->company->id; - - $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->browse; - $position[] = $this->lang->group->browse; - - $groups = $this->group->getList($companyID); - $groupUsers = array(); - foreach($groups as $group) $groupUsers[$group->id] = $this->group->getUserPairs($group->id); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->groups = $groups; - $this->view->groupUsers = $groupUsers; - - $this->display(); - } - - /** - * Create a group. - * - * @access public - * @return void - */ - public function create() - { - if(!empty($_POST)) - { - $this->group->create(); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('group', 'browse'), 'parent')); - } - - $this->view->header->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->create; - $this->view->position[] = $this->lang->group->create; - $this->display(); - } - - /** - * Edit a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function edit($groupID) - { - if(!empty($_POST)) - { - $this->group->update($groupID); - die(js::locate($this->createLink('group', 'browse'), 'parent')); - } - - $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->edit; - $position[] = $this->lang->group->edit; - $this->view->header = $header; - $this->view->position = $position; - $this->view->group = $this->group->getById($groupID); - - $this->display(); - } - - /** - * Copy a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function copy($groupID) - { - if(!empty($_POST)) - { - $this->group->copy($groupID); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('group', 'browse'), 'parent')); - } - - $this->view->header->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->copy; - $this->view->position[] = $this->lang->group->copy; - $this->view->group = $this->group->getById($groupID); - $this->display(); - } - - /** - * Manage privleges of a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function managePriv($type = 'byGroup', $param = 0) - { - if($type == 'byGroup') $groupID = $param; - $this->view->type = $type; - foreach($this->lang->resource as $moduleName => $action) $this->app->loadLang($moduleName); - - if(!empty($_POST)) - { - if($type == 'byGroup') $result = $this->group->updatePrivByGroup($groupID); - if($type == 'byModule') $result = $this->group->updatePrivByModule(); - print(js::alert($result ? $this->lang->group->successSaved : $this->lang->group->errorNotSaved)); - exit; - } - - if($type == 'byGroup') - { - $group = $this->group->getById($groupID); - $groupPrivs = $this->group->getPrivs($groupID); - - $this->view->header->title = $this->lang->company->common . $this->lang->colon . $group->name . $this->lang->colon . $this->lang->group->managePriv; - $this->view->position[] = $group->name . $this->lang->colon . $this->lang->group->managePriv; - - $this->view->group = $group; - $this->view->changelogs = $this->lang->changelog; - $this->view->groupPrivs = $groupPrivs; - - } - elseif($type == 'byModule') - { - $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->group->managePriv; - $this->view->position[] = $this->lang->group->managePriv; - - foreach($this->lang->resource as $module => $moduleActions) - { - $modules[$module] = $this->lang->$module->common; - foreach($moduleActions as $action) - { - $actions[$module][$action] = $this->lang->$module->$action; - } - } - $this->view->groups = $this->group->getPairs(); - $this->view->modules = $modules; - $this->view->actions = $actions; - } - $this->display(); - } - - /** - * Manage members of a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function manageMember($groupID) - { - if(!empty($_POST)) - { - $this->group->updateUser($groupID); - die(js::locate($this->createLink('group', 'browse'), 'parent')); - } - $group = $this->group->getById($groupID); - $groupUsers = $this->group->getUserPairs($groupID); - $allUsers = $this->user->getPairs('noclosed|noempty|noletter'); - $otherUsers = array_diff_assoc($allUsers, $groupUsers); - - $header['title'] = $this->lang->company->common . $this->lang->colon . $group->name . $this->lang->colon . $this->lang->group->manageMember; - $position[] = $group->name . $this->lang->colon . $this->lang->group->manageMember; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->group = $group; - $this->view->groupUsers = $groupUsers; - $this->view->otherUsers = $otherUsers; - - $this->display(); - } - - /** - * Delete a group. - * - * @param int $groupID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($groupID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->group->confirmDelete, $this->createLink('group', 'delete', "groupID=$groupID&confirm=yes"))); - } - else - { - $this->group->delete($groupID); - die(js::locate($this->createLink('group', 'browse'), 'parent')); - } - } -} + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +class group extends control +{ + /** + * Construct function. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('company')->setMenu(); + $this->loadModel('user'); + } + + /** + * Browse groups. + * + * @param int $companyID + * @access public + * @return void + */ + public function browse($companyID = 0) + { + if($companyID == 0) $companyID = $this->app->company->id; + + $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->browse; + $position[] = $this->lang->group->browse; + + $groups = $this->group->getList($companyID); + $groupUsers = array(); + foreach($groups as $group) $groupUsers[$group->id] = $this->group->getUserPairs($group->id); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->groups = $groups; + $this->view->groupUsers = $groupUsers; + + $this->display(); + } + + /** + * Create a group. + * + * @access public + * @return void + */ + public function create() + { + if(!empty($_POST)) + { + $this->group->create(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('group', 'browse'), 'parent')); + } + + $this->view->header->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->create; + $this->view->position[] = $this->lang->group->create; + $this->display(); + } + + /** + * Edit a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function edit($groupID) + { + if(!empty($_POST)) + { + $this->group->update($groupID); + die(js::locate($this->createLink('group', 'browse'), 'parent')); + } + + $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->edit; + $position[] = $this->lang->group->edit; + $this->view->header = $header; + $this->view->position = $position; + $this->view->group = $this->group->getById($groupID); + + $this->display(); + } + + /** + * Copy a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function copy($groupID) + { + if(!empty($_POST)) + { + $this->group->copy($groupID); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('group', 'browse'), 'parent')); + } + + $this->view->header->title = $this->lang->company->orgView . $this->lang->colon . $this->lang->group->copy; + $this->view->position[] = $this->lang->group->copy; + $this->view->group = $this->group->getById($groupID); + $this->display(); + } + + /** + * Manage privleges of a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function managePriv($type = 'byGroup', $param = 0) + { + if($type == 'byGroup') $groupID = $param; + $this->view->type = $type; + foreach($this->lang->resource as $moduleName => $action) $this->app->loadLang($moduleName); + + if(!empty($_POST)) + { + if($type == 'byGroup') $result = $this->group->updatePrivByGroup($groupID); + if($type == 'byModule') $result = $this->group->updatePrivByModule(); + print(js::alert($result ? $this->lang->group->successSaved : $this->lang->group->errorNotSaved)); + exit; + } + + if($type == 'byGroup') + { + $group = $this->group->getById($groupID); + $groupPrivs = $this->group->getPrivs($groupID); + + $this->view->header->title = $this->lang->company->common . $this->lang->colon . $group->name . $this->lang->colon . $this->lang->group->managePriv; + $this->view->position[] = $group->name . $this->lang->colon . $this->lang->group->managePriv; + + $this->view->group = $group; + $this->view->changelogs = $this->lang->changelog; + $this->view->groupPrivs = $groupPrivs; + + } + elseif($type == 'byModule') + { + $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->group->managePriv; + $this->view->position[] = $this->lang->group->managePriv; + + foreach($this->lang->resource as $module => $moduleActions) + { + $modules[$module] = $this->lang->$module->common; + foreach($moduleActions as $action) + { + $actions[$module][$action] = $this->lang->$module->$action; + } + } + $this->view->groups = $this->group->getPairs(); + $this->view->modules = $modules; + $this->view->actions = $actions; + } + $this->display(); + } + + /** + * Manage members of a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function manageMember($groupID) + { + if(!empty($_POST)) + { + $this->group->updateUser($groupID); + die(js::locate($this->createLink('group', 'browse'), 'parent')); + } + $group = $this->group->getById($groupID); + $groupUsers = $this->group->getUserPairs($groupID); + $allUsers = $this->user->getPairs('noclosed|noempty|noletter'); + $otherUsers = array_diff_assoc($allUsers, $groupUsers); + + $header['title'] = $this->lang->company->common . $this->lang->colon . $group->name . $this->lang->colon . $this->lang->group->manageMember; + $position[] = $group->name . $this->lang->colon . $this->lang->group->manageMember; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->group = $group; + $this->view->groupUsers = $groupUsers; + $this->view->otherUsers = $otherUsers; + + $this->display(); + } + + /** + * Delete a group. + * + * @param int $groupID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($groupID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->group->confirmDelete, $this->createLink('group', 'delete', "groupID=$groupID&confirm=yes"))); + } + else + { + $this->group->delete($groupID); + die(js::locate($this->createLink('group', 'browse'), 'parent')); + } + } +} diff --git a/module/group/lang/en.php b/module/group/lang/en.php index d5acc2021b..369583b86f 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -1,57 +1,57 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->group->common = 'Group'; -$lang->group->browse = 'Browse'; -$lang->group->create = 'Create'; -$lang->group->edit = 'Edit'; -$lang->group->copy = 'Copy'; -$lang->group->delete = 'Delete'; -$lang->group->managePriv = 'Privilege'; -$lang->group->managePrivByGroup = 'Privilege'; -$lang->group->managePrivByModule = 'Manage privilege by module'; -$lang->group->manageMember = 'Members'; -$lang->group->linkMember = 'Add members'; -$lang->group->unlinkMember = 'Remove member'; -$lang->group->confirmDelete = 'Are you sure to delete this group?'; -$lang->group->successSaved = 'Success saved.'; -$lang->group->errorNotSaved = 'Not saved, please make sure you have selected some actions and groups.'; - -$lang->group->id = 'Id'; -$lang->group->name = 'Name'; -$lang->group->desc = 'Desc'; -$lang->group->users = 'Users'; -$lang->group->module = 'Module'; -$lang->group->method = 'Method'; -$lang->group->priv = 'Priviledge'; -$lang->group->checkall = 'Select all'; -$lang->group->option = 'Option'; -$lang->group->inside = 'Group users'; -$lang->group->outside = 'Other users'; - -$lang->group->copyOptions['copyPriv'] = 'Copy priviledge'; -$lang->group->copyOptions['copyUser'] = 'Copy user'; - -$lang->group->versions[''] = 'Show methods added in every release'; -$lang->group->versions['3.0.beta1'] = '3.0.beta1'; -$lang->group->versions['2.4'] = '2.4'; -$lang->group->versions['2.3'] = '2.3'; -$lang->group->versions['2.2'] = '2.2'; -$lang->group->versions['2.1'] = '2.1'; -$lang->group->versions['2.0'] = '2.0'; -$lang->group->versions['1.5'] = '1.5'; -$lang->group->versions['1.4'] = '1.4'; -$lang->group->versions['1.3'] = '1.3'; -$lang->group->versions['1.2'] = '1.2'; -$lang->group->versions['1.1'] = '1.1'; -$lang->group->versions['1.0.1'] = '1.0.1'; - -include (dirname(__FILE__) . '/resource.php'); + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->group->common = 'Group'; +$lang->group->browse = 'Browse'; +$lang->group->create = 'Create'; +$lang->group->edit = 'Edit'; +$lang->group->copy = 'Copy'; +$lang->group->delete = 'Delete'; +$lang->group->managePriv = 'Privilege'; +$lang->group->managePrivByGroup = 'Privilege'; +$lang->group->managePrivByModule = 'Manage privilege by module'; +$lang->group->manageMember = 'Members'; +$lang->group->linkMember = 'Add members'; +$lang->group->unlinkMember = 'Remove member'; +$lang->group->confirmDelete = 'Are you sure to delete this group?'; +$lang->group->successSaved = 'Success saved.'; +$lang->group->errorNotSaved = 'Not saved, please make sure you have selected some actions and groups.'; + +$lang->group->id = 'Id'; +$lang->group->name = 'Name'; +$lang->group->desc = 'Desc'; +$lang->group->users = 'Users'; +$lang->group->module = 'Module'; +$lang->group->method = 'Method'; +$lang->group->priv = 'Priviledge'; +$lang->group->checkall = 'Select all'; +$lang->group->option = 'Option'; +$lang->group->inside = 'Group users'; +$lang->group->outside = 'Other users'; + +$lang->group->copyOptions['copyPriv'] = 'Copy priviledge'; +$lang->group->copyOptions['copyUser'] = 'Copy user'; + +$lang->group->versions[''] = 'Show methods added in every release'; +$lang->group->versions['3.0.beta1'] = '3.0.beta1'; +$lang->group->versions['2.4'] = '2.4'; +$lang->group->versions['2.3'] = '2.3'; +$lang->group->versions['2.2'] = '2.2'; +$lang->group->versions['2.1'] = '2.1'; +$lang->group->versions['2.0'] = '2.0'; +$lang->group->versions['1.5'] = '1.5'; +$lang->group->versions['1.4'] = '1.4'; +$lang->group->versions['1.3'] = '1.3'; +$lang->group->versions['1.2'] = '1.2'; +$lang->group->versions['1.1'] = '1.1'; +$lang->group->versions['1.0.1'] = '1.0.1'; + +include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 2d2920d132..0d43b1158d 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1,358 +1,358 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ - -/* Index module. */ -$lang->resource->index->index = 'index'; - -/* My module. */ -$lang->resource->my->index = 'index'; -$lang->resource->my->todo = 'todo'; -$lang->resource->my->task = 'task'; -$lang->resource->my->bug = 'bug'; -$lang->resource->my->testTask = 'testTask'; -$lang->resource->my->testCase = 'testCase'; -$lang->resource->my->story = 'story'; -$lang->resource->my->project = 'project'; -$lang->resource->my->profile = 'profile'; -$lang->resource->my->dynamic = 'dynamic'; -$lang->resource->my->editProfile = 'editProfile'; - -/* Todo. */ -$lang->resource->todo->create = 'create'; -$lang->resource->todo->edit = 'edit'; -$lang->resource->todo->view = 'view'; -$lang->resource->todo->delete = 'delete'; -$lang->resource->todo->export = 'export'; -$lang->resource->todo->mark = 'mark'; -$lang->resource->todo->import2Today = 'import2Today'; - -/* Product. */ -$lang->resource->product->index = 'index'; -$lang->resource->product->browse = 'browse'; -$lang->resource->product->create = 'create'; -$lang->resource->product->view = 'view'; -$lang->resource->product->edit = 'edit'; -$lang->resource->product->delete = 'delete'; -$lang->resource->product->roadmap= 'roadmap'; -$lang->resource->product->doc = 'doc'; -$lang->resource->product->dynamic= 'dynamic'; -$lang->resource->product->project= 'project'; -$lang->resource->product->ajaxGetProjects = 'ajaxGetProjects'; -$lang->resource->product->ajaxGetPlans = 'ajaxGetPlans'; - -/* Story. */ -$lang->resource->story->create = 'create'; -$lang->resource->story->batchCreate = 'batchCreate'; -$lang->resource->story->edit = 'edit'; -$lang->resource->story->export = 'export'; -$lang->resource->story->delete = 'delete'; -$lang->resource->story->view = 'view'; -$lang->resource->story->change = 'lblChange'; -$lang->resource->story->review = 'lblReview'; -$lang->resource->story->close = 'lblClose'; -$lang->resource->story->activate = 'lblActivate'; -$lang->resource->story->tasks = 'tasks'; -$lang->resource->story->report = 'reportChart'; -$lang->resource->story->ajaxGetProjectStories = 'ajaxGetProjectStories'; -$lang->resource->story->ajaxGetProductStories = 'ajaxGetProductStories'; - -/* Product plan. */ -$lang->resource->productplan->browse = 'browse'; -$lang->resource->productplan->create = 'create'; -$lang->resource->productplan->edit = 'edit'; -$lang->resource->productplan->delete = 'delete'; -$lang->resource->productplan->view = 'view'; -$lang->resource->productplan->linkStory = 'linkStory'; -$lang->resource->productplan->unlinkStory = 'unlinkStory'; - -/* Release. */ -$lang->resource->release->browse = 'browse'; -$lang->resource->release->create = 'create'; -$lang->resource->release->edit = 'edit'; -$lang->resource->release->delete = 'delete'; -$lang->resource->release->view = 'view'; -$lang->resource->release->ajaxGetStoriesAndBugs = 'ajaxGetStoriesAndBugs'; - -/* Project. */ -$lang->resource->project->index = 'index'; -$lang->resource->project->view = 'view'; -$lang->resource->project->browse = 'browse'; -$lang->resource->project->create = 'create'; -$lang->resource->project->edit = 'edit'; -$lang->resource->project->delete = 'delete'; -$lang->resource->project->task = 'task'; -$lang->resource->project->grouptask = 'groupTask'; -$lang->resource->project->importtask = 'importTask'; -$lang->resource->project->importBug = 'importBug'; -$lang->resource->project->story = 'story'; -$lang->resource->project->build = 'build'; -$lang->resource->project->testtask = 'testtask'; -$lang->resource->project->bug = 'bug'; -$lang->resource->project->burn = 'burn'; -$lang->resource->project->computeBurn = 'computeBurn'; -$lang->resource->project->burnData = 'burnData'; -$lang->resource->project->team = 'team'; -$lang->resource->project->doc = 'doc'; -$lang->resource->project->dynamic = 'dynamic'; -$lang->resource->project->manageProducts = 'manageProducts'; -//$lang->resource->project->manageChilds = 'manageChilds'; -$lang->resource->project->manageMembers = 'manageMembers'; -$lang->resource->project->unlinkMember = 'unlinkMember'; -$lang->resource->project->linkStory = 'linkStory'; -$lang->resource->project->unlinkStory = 'unlinkStory'; -$lang->resource->project->ajaxGetProducts= 'ajaxGetProducts'; - -/* Task. */ -$lang->resource->task->create = 'create'; -$lang->resource->task->batchCreate = 'batchCreate'; -$lang->resource->task->edit = 'edit'; -$lang->resource->task->assignTo = 'assign'; -$lang->resource->task->start = 'start'; -$lang->resource->task->finish = 'finish'; -$lang->resource->task->cancel = 'cancel'; -$lang->resource->task->close = 'close'; -$lang->resource->task->batchClose = 'batchClose'; -$lang->resource->task->activate = 'activate'; -$lang->resource->task->delete = 'delete'; -$lang->resource->task->view = 'view'; -$lang->resource->task->export = 'export'; -$lang->resource->task->confirmStoryChange = 'confirmStoryChange'; -$lang->resource->task->ajaxGetUserTasks = 'ajaxGetUserTasks'; -$lang->resource->task->ajaxGetProjectTasks = 'ajaxGetProjectTasks'; -$lang->resource->task->report = 'reportChart'; - -/* Build. */ -$lang->resource->build->create = 'create'; -$lang->resource->build->edit = 'edit'; -$lang->resource->build->delete = 'delete'; -$lang->resource->build->view = 'view'; -$lang->resource->build->ajaxGetProductBuilds = 'ajaxGetProductBuilds'; -$lang->resource->build->ajaxGetProjectBuilds = 'ajaxGetProjectBuilds'; - -/* QA. */ -$lang->resource->qa->index = 'index'; - -/* Bug. */ -$lang->resource->bug->index = 'index'; -$lang->resource->bug->browse = 'browse'; -$lang->resource->bug->create = 'create'; -$lang->resource->bug->confirmBug = 'confirmBug'; -$lang->resource->bug->view = 'view'; -$lang->resource->bug->edit = 'edit'; -$lang->resource->bug->resolve = 'resolve'; -$lang->resource->bug->activate = 'activate'; -$lang->resource->bug->close = 'close'; -$lang->resource->bug->report = 'reportChart'; -$lang->resource->bug->export = 'export'; -$lang->resource->bug->confirmStoryChange = 'confirmStoryChange'; -$lang->resource->bug->delete = 'delete'; -$lang->resource->bug->saveTemplate = 'saveTemplate'; -$lang->resource->bug->deleteTemplate = 'deleteTemplate'; -$lang->resource->bug->customFields = 'customFields'; -$lang->resource->bug->ajaxGetUserBugs = 'ajaxGetUserBugs'; -$lang->resource->bug->ajaxGetModuleOwner = 'ajaxGetModuleOwner'; - -/* Test case. */ -$lang->resource->testcase->index = 'index'; -$lang->resource->testcase->browse = 'browse'; -$lang->resource->testcase->create = 'create'; -$lang->resource->testcase->batchCreate = 'batchCreate'; -$lang->resource->testcase->view = 'view'; -$lang->resource->testcase->edit = 'edit'; -$lang->resource->testcase->delete = 'delete'; -$lang->resource->testcase->export = 'export'; -$lang->resource->testcase->confirmStoryChange = 'confirmStoryChange'; - -/* Test task. */ -$lang->resource->testtask->index = 'index'; -$lang->resource->testtask->create = 'create'; -$lang->resource->testtask->browse = 'browse'; -$lang->resource->testtask->view = 'view'; -$lang->resource->testtask->cases = 'lblCases'; -$lang->resource->testtask->edit = 'edit'; -$lang->resource->testtask->delete = 'delete'; -$lang->resource->testtask->batchAssign = 'batchAssign'; -$lang->resource->testtask->linkcase = 'linkCase'; -$lang->resource->testtask->unlinkcase = 'lblUnlinkCase'; -$lang->resource->testtask->runcase = 'lblRunCase'; -$lang->resource->testtask->results = 'lblResults'; - -/* Doc. */ -$lang->resource->doc->index = 'index'; -$lang->resource->doc->browse = 'browse'; -$lang->resource->doc->createLib = 'createLib'; -$lang->resource->doc->editLib = 'editLib'; -$lang->resource->doc->deleteLib = 'deleteLib'; -$lang->resource->doc->create = 'create'; -$lang->resource->doc->view = 'view'; -$lang->resource->doc->edit = 'edit'; -$lang->resource->doc->delete = 'delete'; - -/* Subversion. */ -$lang->resource->svn->diff = 'diff'; -$lang->resource->svn->cat = 'cat'; -$lang->resource->svn->apiSync = 'apiSync'; - -/* Company. */ -$lang->resource->company->index = 'index'; -$lang->resource->company->browse = 'browse'; -$lang->resource->company->edit = 'edit'; -$lang->resource->company->dynamic= 'dynamic'; - -/* Department. */ -$lang->resource->dept->browse = 'browse'; -$lang->resource->dept->updateOrder = 'updateOrder'; -$lang->resource->dept->manageChild = 'manageChild'; -$lang->resource->dept->delete = 'delete'; - -/* Group. */ -$lang->resource->group->browse = 'browse'; -$lang->resource->group->create = 'create'; -$lang->resource->group->edit = 'edit'; -$lang->resource->group->copy = 'copy'; -$lang->resource->group->delete = 'delete'; -$lang->resource->group->managePriv = 'managePriv'; -$lang->resource->group->manageMember = 'manageMember'; - -/* User. */ -$lang->resource->user->create = 'create'; -$lang->resource->user->view = 'view'; -$lang->resource->user->edit = 'edit'; -$lang->resource->user->delete = 'delete'; -$lang->resource->user->todo = 'todo'; -$lang->resource->user->task = 'task'; -$lang->resource->user->bug = 'bug'; -$lang->resource->user->project = 'project'; -$lang->resource->user->dynamic = 'dynamic'; -$lang->resource->user->profile = 'profile'; -$lang->resource->user->ajaxGetUser = 'ajaxGetUser'; - -/* Tree. */ -$lang->resource->tree->browse = 'browse'; -$lang->resource->tree->updateOrder = 'updateOrder'; -$lang->resource->tree->manageChild = 'manageChild'; -$lang->resource->tree->edit = 'edit'; -$lang->resource->tree->delete = 'delete'; -$lang->resource->tree->ajaxGetOptionMenu = 'ajaxGetOptionMenu'; -$lang->resource->tree->ajaxGetSonModules = 'ajaxGetSonModules'; - -/* Search. */ -$lang->resource->search->buildForm = 'buildForm'; -$lang->resource->search->buildQuery = 'buildQuery'; -$lang->resource->search->saveQuery = 'saveQuery'; -$lang->resource->search->deleteQuery = 'deleteQuery'; -$lang->resource->search->select = 'select'; - -/* Admin. */ -$lang->resource->admin->index = 'index'; - -/* Extension. */ -$lang->resource->extension->browse = 'browse'; -$lang->resource->extension->obtain = 'obtain'; -$lang->resource->extension->install = 'install'; -$lang->resource->extension->uninstall = 'uninstall'; -$lang->resource->extension->activate = 'activate'; -$lang->resource->extension->deactivate = 'deactivate'; -$lang->resource->extension->upload = 'upload'; -$lang->resource->extension->erase = 'erase'; -$lang->resource->extension->upgrade = 'upgrade'; - -/* Others. */ -$lang->resource->api->getModel = 'getModel'; -$lang->resource->file->download = 'download'; -$lang->resource->file->edit = 'edit'; -$lang->resource->file->delete = 'delete'; -$lang->resource->file->ajaxUpload = 'ajaxUpload'; -$lang->resource->misc->ping = 'ping'; -$lang->resource->action->trash = 'trash'; -$lang->resource->action->undelete = 'undelete'; - -/* Every version of new privilege. */ -$lang->changelog['1.0.1'][] = 'project-computeBurn'; - -$lang->changelog['1.1'][] = 'search-saveQuery'; -$lang->changelog['1.1'][] = 'search-deleteQuery'; - -$lang->changelog['1.2'][] = 'product-doc'; -$lang->changelog['1.2'][] = 'project-doc'; -$lang->changelog['1.2'][] = 'project-ajaxGetProducts'; -$lang->changelog['1.2'][] = 'bug-saveTemplate'; -$lang->changelog['1.2'][] = 'bug-deleteTemplate'; -$lang->changelog['1.2'][] = 'bug-customFields'; -$lang->changelog['1.2'][] = 'bug-ajaxGetModuleOwner'; -$lang->changelog['1.2'][] = 'doc-index'; -$lang->changelog['1.2'][] = 'doc-browse'; -$lang->changelog['1.2'][] = 'doc-createLib'; -$lang->changelog['1.2'][] = 'doc-editLib'; -$lang->changelog['1.2'][] = 'doc-deleteLib'; -$lang->changelog['1.2'][] = 'doc-create'; -$lang->changelog['1.2'][] = 'doc-view'; -$lang->changelog['1.2'][] = 'doc-edit'; -$lang->changelog['1.2'][] = 'doc-delete'; -$lang->changelog['1.2'][] = 'doc-deleteFile'; - -$lang->changelog['1.3'][] = 'task-start'; -$lang->changelog['1.3'][] = 'task-complete'; -$lang->changelog['1.3'][] = 'task-cancel'; -$lang->changelog['1.3'][] = 'tree-ajaxGetSonModules'; -$lang->changelog['1.3'][] = 'file-delete'; -$lang->changelog['1.3'][] = 'file-ajaxUpload'; - -$lang->changelog['1.4'][] = 'my-testTask'; -$lang->changelog['1.4'][] = 'my-testCase'; -$lang->changelog['1.4'][] = 'task-finish'; -$lang->changelog['1.4'][] = 'task-close'; -$lang->changelog['1.4'][] = 'task-activate'; -$lang->changelog['1.4'][] = 'search-select'; - -$lang->changelog['1.5'][] = 'task-batchClose'; - -$lang->changelog['2.0'][] = 'my-dynamic'; -$lang->changelog['2.0'][] = 'bug-export'; -$lang->changelog['2.0'][] = 'story-export'; -$lang->changelog['2.0'][] = 'story-reportChart'; -$lang->changelog['2.0'][] = 'task-export'; -$lang->changelog['2.0'][] = 'task-reportChart'; -$lang->changelog['2.0'][] = 'taskcase-export'; -$lang->changelog['2.0'][] = 'company-dynamic'; -$lang->changelog['2.0'][] = 'user-dynamic'; -$lang->changelog['2.0'][] = 'extension-browse'; -$lang->changelog['2.0'][] = 'extension-obtain'; -$lang->changelog['2.0'][] = 'extension-install'; -$lang->changelog['2.0'][] = 'extension-uninstall'; -$lang->changelog['2.0'][] = 'extension-activate'; -$lang->changelog['2.0'][] = 'extension-deactivate'; -$lang->changelog['2.0'][] = 'extension-upload'; -$lang->changelog['2.0'][] = 'extension-erase'; - -$lang->changelog['2.1'][] = 'extension-upgrade'; - -$lang->changelog['2.2'][] = 'file-edit'; - -$lang->changelog['2.3'][] = 'product-dynamic'; -$lang->changelog['2.3'][] = 'project-dynamic'; -$lang->changelog['2.3'][] = 'project-importBug'; -$lang->changelog['2.3'][] = 'story-batchCreate'; -$lang->changelog['2.3'][] = 'task-batchCreate'; -$lang->changelog['2.3'][] = 'testcase-batchCreate'; -$lang->changelog['2.3'][] = 'bug-confirmBug'; -$lang->changelog['2.3'][] = 'svn-diff'; -$lang->changelog['2.3'][] = 'svn-cat'; -$lang->changelog['2.3'][] = 'svn-apiSync'; - -$lang->changelog['2.4'][] = 'user-ajaxGetUser'; -$lang->changelog['2.4'][] = 'task-assign'; -$lang->changelog['2.4'][] = 'project-testtask'; -$lang->changelog['2.4'][] = 'todo-export'; -$lang->changelog['2.4'][] = 'product-project'; - -$lang->changelog['3.0.beta1'][] = 'release-ajaxGetStoriesAndBugs'; + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ + +/* Index module. */ +$lang->resource->index->index = 'index'; + +/* My module. */ +$lang->resource->my->index = 'index'; +$lang->resource->my->todo = 'todo'; +$lang->resource->my->task = 'task'; +$lang->resource->my->bug = 'bug'; +$lang->resource->my->testTask = 'testTask'; +$lang->resource->my->testCase = 'testCase'; +$lang->resource->my->story = 'story'; +$lang->resource->my->project = 'project'; +$lang->resource->my->profile = 'profile'; +$lang->resource->my->dynamic = 'dynamic'; +$lang->resource->my->editProfile = 'editProfile'; + +/* Todo. */ +$lang->resource->todo->create = 'create'; +$lang->resource->todo->edit = 'edit'; +$lang->resource->todo->view = 'view'; +$lang->resource->todo->delete = 'delete'; +$lang->resource->todo->export = 'export'; +$lang->resource->todo->mark = 'mark'; +$lang->resource->todo->import2Today = 'import2Today'; + +/* Product. */ +$lang->resource->product->index = 'index'; +$lang->resource->product->browse = 'browse'; +$lang->resource->product->create = 'create'; +$lang->resource->product->view = 'view'; +$lang->resource->product->edit = 'edit'; +$lang->resource->product->delete = 'delete'; +$lang->resource->product->roadmap= 'roadmap'; +$lang->resource->product->doc = 'doc'; +$lang->resource->product->dynamic= 'dynamic'; +$lang->resource->product->project= 'project'; +$lang->resource->product->ajaxGetProjects = 'ajaxGetProjects'; +$lang->resource->product->ajaxGetPlans = 'ajaxGetPlans'; + +/* Story. */ +$lang->resource->story->create = 'create'; +$lang->resource->story->batchCreate = 'batchCreate'; +$lang->resource->story->edit = 'edit'; +$lang->resource->story->export = 'export'; +$lang->resource->story->delete = 'delete'; +$lang->resource->story->view = 'view'; +$lang->resource->story->change = 'lblChange'; +$lang->resource->story->review = 'lblReview'; +$lang->resource->story->close = 'lblClose'; +$lang->resource->story->activate = 'lblActivate'; +$lang->resource->story->tasks = 'tasks'; +$lang->resource->story->report = 'reportChart'; +$lang->resource->story->ajaxGetProjectStories = 'ajaxGetProjectStories'; +$lang->resource->story->ajaxGetProductStories = 'ajaxGetProductStories'; + +/* Product plan. */ +$lang->resource->productplan->browse = 'browse'; +$lang->resource->productplan->create = 'create'; +$lang->resource->productplan->edit = 'edit'; +$lang->resource->productplan->delete = 'delete'; +$lang->resource->productplan->view = 'view'; +$lang->resource->productplan->linkStory = 'linkStory'; +$lang->resource->productplan->unlinkStory = 'unlinkStory'; + +/* Release. */ +$lang->resource->release->browse = 'browse'; +$lang->resource->release->create = 'create'; +$lang->resource->release->edit = 'edit'; +$lang->resource->release->delete = 'delete'; +$lang->resource->release->view = 'view'; +$lang->resource->release->ajaxGetStoriesAndBugs = 'ajaxGetStoriesAndBugs'; + +/* Project. */ +$lang->resource->project->index = 'index'; +$lang->resource->project->view = 'view'; +$lang->resource->project->browse = 'browse'; +$lang->resource->project->create = 'create'; +$lang->resource->project->edit = 'edit'; +$lang->resource->project->delete = 'delete'; +$lang->resource->project->task = 'task'; +$lang->resource->project->grouptask = 'groupTask'; +$lang->resource->project->importtask = 'importTask'; +$lang->resource->project->importBug = 'importBug'; +$lang->resource->project->story = 'story'; +$lang->resource->project->build = 'build'; +$lang->resource->project->testtask = 'testtask'; +$lang->resource->project->bug = 'bug'; +$lang->resource->project->burn = 'burn'; +$lang->resource->project->computeBurn = 'computeBurn'; +$lang->resource->project->burnData = 'burnData'; +$lang->resource->project->team = 'team'; +$lang->resource->project->doc = 'doc'; +$lang->resource->project->dynamic = 'dynamic'; +$lang->resource->project->manageProducts = 'manageProducts'; +//$lang->resource->project->manageChilds = 'manageChilds'; +$lang->resource->project->manageMembers = 'manageMembers'; +$lang->resource->project->unlinkMember = 'unlinkMember'; +$lang->resource->project->linkStory = 'linkStory'; +$lang->resource->project->unlinkStory = 'unlinkStory'; +$lang->resource->project->ajaxGetProducts= 'ajaxGetProducts'; + +/* Task. */ +$lang->resource->task->create = 'create'; +$lang->resource->task->batchCreate = 'batchCreate'; +$lang->resource->task->edit = 'edit'; +$lang->resource->task->assignTo = 'assign'; +$lang->resource->task->start = 'start'; +$lang->resource->task->finish = 'finish'; +$lang->resource->task->cancel = 'cancel'; +$lang->resource->task->close = 'close'; +$lang->resource->task->batchClose = 'batchClose'; +$lang->resource->task->activate = 'activate'; +$lang->resource->task->delete = 'delete'; +$lang->resource->task->view = 'view'; +$lang->resource->task->export = 'export'; +$lang->resource->task->confirmStoryChange = 'confirmStoryChange'; +$lang->resource->task->ajaxGetUserTasks = 'ajaxGetUserTasks'; +$lang->resource->task->ajaxGetProjectTasks = 'ajaxGetProjectTasks'; +$lang->resource->task->report = 'reportChart'; + +/* Build. */ +$lang->resource->build->create = 'create'; +$lang->resource->build->edit = 'edit'; +$lang->resource->build->delete = 'delete'; +$lang->resource->build->view = 'view'; +$lang->resource->build->ajaxGetProductBuilds = 'ajaxGetProductBuilds'; +$lang->resource->build->ajaxGetProjectBuilds = 'ajaxGetProjectBuilds'; + +/* QA. */ +$lang->resource->qa->index = 'index'; + +/* Bug. */ +$lang->resource->bug->index = 'index'; +$lang->resource->bug->browse = 'browse'; +$lang->resource->bug->create = 'create'; +$lang->resource->bug->confirmBug = 'confirmBug'; +$lang->resource->bug->view = 'view'; +$lang->resource->bug->edit = 'edit'; +$lang->resource->bug->resolve = 'resolve'; +$lang->resource->bug->activate = 'activate'; +$lang->resource->bug->close = 'close'; +$lang->resource->bug->report = 'reportChart'; +$lang->resource->bug->export = 'export'; +$lang->resource->bug->confirmStoryChange = 'confirmStoryChange'; +$lang->resource->bug->delete = 'delete'; +$lang->resource->bug->saveTemplate = 'saveTemplate'; +$lang->resource->bug->deleteTemplate = 'deleteTemplate'; +$lang->resource->bug->customFields = 'customFields'; +$lang->resource->bug->ajaxGetUserBugs = 'ajaxGetUserBugs'; +$lang->resource->bug->ajaxGetModuleOwner = 'ajaxGetModuleOwner'; + +/* Test case. */ +$lang->resource->testcase->index = 'index'; +$lang->resource->testcase->browse = 'browse'; +$lang->resource->testcase->create = 'create'; +$lang->resource->testcase->batchCreate = 'batchCreate'; +$lang->resource->testcase->view = 'view'; +$lang->resource->testcase->edit = 'edit'; +$lang->resource->testcase->delete = 'delete'; +$lang->resource->testcase->export = 'export'; +$lang->resource->testcase->confirmStoryChange = 'confirmStoryChange'; + +/* Test task. */ +$lang->resource->testtask->index = 'index'; +$lang->resource->testtask->create = 'create'; +$lang->resource->testtask->browse = 'browse'; +$lang->resource->testtask->view = 'view'; +$lang->resource->testtask->cases = 'lblCases'; +$lang->resource->testtask->edit = 'edit'; +$lang->resource->testtask->delete = 'delete'; +$lang->resource->testtask->batchAssign = 'batchAssign'; +$lang->resource->testtask->linkcase = 'linkCase'; +$lang->resource->testtask->unlinkcase = 'lblUnlinkCase'; +$lang->resource->testtask->runcase = 'lblRunCase'; +$lang->resource->testtask->results = 'lblResults'; + +/* Doc. */ +$lang->resource->doc->index = 'index'; +$lang->resource->doc->browse = 'browse'; +$lang->resource->doc->createLib = 'createLib'; +$lang->resource->doc->editLib = 'editLib'; +$lang->resource->doc->deleteLib = 'deleteLib'; +$lang->resource->doc->create = 'create'; +$lang->resource->doc->view = 'view'; +$lang->resource->doc->edit = 'edit'; +$lang->resource->doc->delete = 'delete'; + +/* Subversion. */ +$lang->resource->svn->diff = 'diff'; +$lang->resource->svn->cat = 'cat'; +$lang->resource->svn->apiSync = 'apiSync'; + +/* Company. */ +$lang->resource->company->index = 'index'; +$lang->resource->company->browse = 'browse'; +$lang->resource->company->edit = 'edit'; +$lang->resource->company->dynamic= 'dynamic'; + +/* Department. */ +$lang->resource->dept->browse = 'browse'; +$lang->resource->dept->updateOrder = 'updateOrder'; +$lang->resource->dept->manageChild = 'manageChild'; +$lang->resource->dept->delete = 'delete'; + +/* Group. */ +$lang->resource->group->browse = 'browse'; +$lang->resource->group->create = 'create'; +$lang->resource->group->edit = 'edit'; +$lang->resource->group->copy = 'copy'; +$lang->resource->group->delete = 'delete'; +$lang->resource->group->managePriv = 'managePriv'; +$lang->resource->group->manageMember = 'manageMember'; + +/* User. */ +$lang->resource->user->create = 'create'; +$lang->resource->user->view = 'view'; +$lang->resource->user->edit = 'edit'; +$lang->resource->user->delete = 'delete'; +$lang->resource->user->todo = 'todo'; +$lang->resource->user->task = 'task'; +$lang->resource->user->bug = 'bug'; +$lang->resource->user->project = 'project'; +$lang->resource->user->dynamic = 'dynamic'; +$lang->resource->user->profile = 'profile'; +$lang->resource->user->ajaxGetUser = 'ajaxGetUser'; + +/* Tree. */ +$lang->resource->tree->browse = 'browse'; +$lang->resource->tree->updateOrder = 'updateOrder'; +$lang->resource->tree->manageChild = 'manageChild'; +$lang->resource->tree->edit = 'edit'; +$lang->resource->tree->delete = 'delete'; +$lang->resource->tree->ajaxGetOptionMenu = 'ajaxGetOptionMenu'; +$lang->resource->tree->ajaxGetSonModules = 'ajaxGetSonModules'; + +/* Search. */ +$lang->resource->search->buildForm = 'buildForm'; +$lang->resource->search->buildQuery = 'buildQuery'; +$lang->resource->search->saveQuery = 'saveQuery'; +$lang->resource->search->deleteQuery = 'deleteQuery'; +$lang->resource->search->select = 'select'; + +/* Admin. */ +$lang->resource->admin->index = 'index'; + +/* Extension. */ +$lang->resource->extension->browse = 'browse'; +$lang->resource->extension->obtain = 'obtain'; +$lang->resource->extension->install = 'install'; +$lang->resource->extension->uninstall = 'uninstall'; +$lang->resource->extension->activate = 'activate'; +$lang->resource->extension->deactivate = 'deactivate'; +$lang->resource->extension->upload = 'upload'; +$lang->resource->extension->erase = 'erase'; +$lang->resource->extension->upgrade = 'upgrade'; + +/* Others. */ +$lang->resource->api->getModel = 'getModel'; +$lang->resource->file->download = 'download'; +$lang->resource->file->edit = 'edit'; +$lang->resource->file->delete = 'delete'; +$lang->resource->file->ajaxUpload = 'ajaxUpload'; +$lang->resource->misc->ping = 'ping'; +$lang->resource->action->trash = 'trash'; +$lang->resource->action->undelete = 'undelete'; + +/* Every version of new privilege. */ +$lang->changelog['1.0.1'][] = 'project-computeBurn'; + +$lang->changelog['1.1'][] = 'search-saveQuery'; +$lang->changelog['1.1'][] = 'search-deleteQuery'; + +$lang->changelog['1.2'][] = 'product-doc'; +$lang->changelog['1.2'][] = 'project-doc'; +$lang->changelog['1.2'][] = 'project-ajaxGetProducts'; +$lang->changelog['1.2'][] = 'bug-saveTemplate'; +$lang->changelog['1.2'][] = 'bug-deleteTemplate'; +$lang->changelog['1.2'][] = 'bug-customFields'; +$lang->changelog['1.2'][] = 'bug-ajaxGetModuleOwner'; +$lang->changelog['1.2'][] = 'doc-index'; +$lang->changelog['1.2'][] = 'doc-browse'; +$lang->changelog['1.2'][] = 'doc-createLib'; +$lang->changelog['1.2'][] = 'doc-editLib'; +$lang->changelog['1.2'][] = 'doc-deleteLib'; +$lang->changelog['1.2'][] = 'doc-create'; +$lang->changelog['1.2'][] = 'doc-view'; +$lang->changelog['1.2'][] = 'doc-edit'; +$lang->changelog['1.2'][] = 'doc-delete'; +$lang->changelog['1.2'][] = 'doc-deleteFile'; + +$lang->changelog['1.3'][] = 'task-start'; +$lang->changelog['1.3'][] = 'task-complete'; +$lang->changelog['1.3'][] = 'task-cancel'; +$lang->changelog['1.3'][] = 'tree-ajaxGetSonModules'; +$lang->changelog['1.3'][] = 'file-delete'; +$lang->changelog['1.3'][] = 'file-ajaxUpload'; + +$lang->changelog['1.4'][] = 'my-testTask'; +$lang->changelog['1.4'][] = 'my-testCase'; +$lang->changelog['1.4'][] = 'task-finish'; +$lang->changelog['1.4'][] = 'task-close'; +$lang->changelog['1.4'][] = 'task-activate'; +$lang->changelog['1.4'][] = 'search-select'; + +$lang->changelog['1.5'][] = 'task-batchClose'; + +$lang->changelog['2.0'][] = 'my-dynamic'; +$lang->changelog['2.0'][] = 'bug-export'; +$lang->changelog['2.0'][] = 'story-export'; +$lang->changelog['2.0'][] = 'story-reportChart'; +$lang->changelog['2.0'][] = 'task-export'; +$lang->changelog['2.0'][] = 'task-reportChart'; +$lang->changelog['2.0'][] = 'taskcase-export'; +$lang->changelog['2.0'][] = 'company-dynamic'; +$lang->changelog['2.0'][] = 'user-dynamic'; +$lang->changelog['2.0'][] = 'extension-browse'; +$lang->changelog['2.0'][] = 'extension-obtain'; +$lang->changelog['2.0'][] = 'extension-install'; +$lang->changelog['2.0'][] = 'extension-uninstall'; +$lang->changelog['2.0'][] = 'extension-activate'; +$lang->changelog['2.0'][] = 'extension-deactivate'; +$lang->changelog['2.0'][] = 'extension-upload'; +$lang->changelog['2.0'][] = 'extension-erase'; + +$lang->changelog['2.1'][] = 'extension-upgrade'; + +$lang->changelog['2.2'][] = 'file-edit'; + +$lang->changelog['2.3'][] = 'product-dynamic'; +$lang->changelog['2.3'][] = 'project-dynamic'; +$lang->changelog['2.3'][] = 'project-importBug'; +$lang->changelog['2.3'][] = 'story-batchCreate'; +$lang->changelog['2.3'][] = 'task-batchCreate'; +$lang->changelog['2.3'][] = 'testcase-batchCreate'; +$lang->changelog['2.3'][] = 'bug-confirmBug'; +$lang->changelog['2.3'][] = 'svn-diff'; +$lang->changelog['2.3'][] = 'svn-cat'; +$lang->changelog['2.3'][] = 'svn-apiSync'; + +$lang->changelog['2.4'][] = 'user-ajaxGetUser'; +$lang->changelog['2.4'][] = 'task-assign'; +$lang->changelog['2.4'][] = 'project-testtask'; +$lang->changelog['2.4'][] = 'todo-export'; +$lang->changelog['2.4'][] = 'product-project'; + +$lang->changelog['3.0.beta1'][] = 'release-ajaxGetStoriesAndBugs'; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index 4289251962..bf6c48798b 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -1,57 +1,57 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->group->common = '权限分组'; -$lang->group->browse = '浏览分组'; -$lang->group->create = '新增分组'; -$lang->group->edit = '编辑分组'; -$lang->group->copy = '复制分组'; -$lang->group->delete = '删除分组'; -$lang->group->managePriv = '权限维护'; -$lang->group->managePrivByGroup = '权限维护'; -$lang->group->managePrivByModule = '按模块分配权限'; -$lang->group->manageMember = '成员维护'; -$lang->group->linkMember = '关联用户'; -$lang->group->unlinkMember = '移除用户'; -$lang->group->confirmDelete = '您确定删除该用户分组吗?'; -$lang->group->successSaved = '成功保存'; -$lang->group->errorNotSaved = '没有保存,请确认选择了权限数据。'; - -$lang->group->id = '编号'; -$lang->group->name = '分组名称'; -$lang->group->desc = '分组描述'; -$lang->group->users = '用户列表'; -$lang->group->module = '模块'; -$lang->group->method = '方法'; -$lang->group->priv = '权限'; -$lang->group->checkall = '全选'; -$lang->group->option = '选项'; -$lang->group->inside = '组内用户'; -$lang->group->outside = '组外用户'; - -$lang->group->copyOptions['copyPriv'] = '复制权限'; -$lang->group->copyOptions['copyUser'] = '复制用户'; - -$lang->group->versions[''] = '显示各版本新增权限'; -$lang->group->versions['3.0.beta1'] = '禅道3.0.beta1'; -$lang->group->versions['2.4'] = '禅道2.4'; -$lang->group->versions['2.3'] = '禅道2.3'; -$lang->group->versions['2.2'] = '禅道2.2'; -$lang->group->versions['2.1'] = '禅道2.1'; -$lang->group->versions['2.0'] = '禅道2.0'; -$lang->group->versions['1.5'] = '禅道1.5'; -$lang->group->versions['1.4'] = '禅道1.4'; -$lang->group->versions['1.3'] = '禅道1.3'; -$lang->group->versions['1.2'] = '禅道1.2'; -$lang->group->versions['1.1'] = '禅道1.1'; -$lang->group->versions['1.0.1'] = '禅道1.0.1'; - -include (dirname(__FILE__) . '/resource.php'); + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->group->common = '权限分组'; +$lang->group->browse = '浏览分组'; +$lang->group->create = '新增分组'; +$lang->group->edit = '编辑分组'; +$lang->group->copy = '复制分组'; +$lang->group->delete = '删除分组'; +$lang->group->managePriv = '权限维护'; +$lang->group->managePrivByGroup = '权限维护'; +$lang->group->managePrivByModule = '按模块分配权限'; +$lang->group->manageMember = '成员维护'; +$lang->group->linkMember = '关联用户'; +$lang->group->unlinkMember = '移除用户'; +$lang->group->confirmDelete = '您确定删除该用户分组吗?'; +$lang->group->successSaved = '成功保存'; +$lang->group->errorNotSaved = '没有保存,请确认选择了权限数据。'; + +$lang->group->id = '编号'; +$lang->group->name = '分组名称'; +$lang->group->desc = '分组描述'; +$lang->group->users = '用户列表'; +$lang->group->module = '模块'; +$lang->group->method = '方法'; +$lang->group->priv = '权限'; +$lang->group->checkall = '全选'; +$lang->group->option = '选项'; +$lang->group->inside = '组内用户'; +$lang->group->outside = '组外用户'; + +$lang->group->copyOptions['copyPriv'] = '复制权限'; +$lang->group->copyOptions['copyUser'] = '复制用户'; + +$lang->group->versions[''] = '显示各版本新增权限'; +$lang->group->versions['3.0.beta1'] = '禅道3.0.beta1'; +$lang->group->versions['2.4'] = '禅道2.4'; +$lang->group->versions['2.3'] = '禅道2.3'; +$lang->group->versions['2.2'] = '禅道2.2'; +$lang->group->versions['2.1'] = '禅道2.1'; +$lang->group->versions['2.0'] = '禅道2.0'; +$lang->group->versions['1.5'] = '禅道1.5'; +$lang->group->versions['1.4'] = '禅道1.4'; +$lang->group->versions['1.3'] = '禅道1.3'; +$lang->group->versions['1.2'] = '禅道1.2'; +$lang->group->versions['1.1'] = '禅道1.1'; +$lang->group->versions['1.0.1'] = '禅道1.0.1'; + +include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/zh-tw.php b/module/group/lang/zh-tw.php index 12074398e9..0494df34ad 100644 --- a/module/group/lang/zh-tw.php +++ b/module/group/lang/zh-tw.php @@ -1,57 +1,57 @@ - - * @package group - * @version $Id: zh-tw.php 2530 2012-01-04 05:38:07Z wwccss $ - * @link http://www.zentao.net - */ -$lang->group->common = '權限分組'; -$lang->group->browse = '瀏覽分組'; -$lang->group->create = '新增分組'; -$lang->group->edit = '編輯分組'; -$lang->group->copy = '複製分組'; -$lang->group->delete = '刪除分組'; -$lang->group->managePriv = '權限維護'; -$lang->group->managePrivByGroup = '權限維護'; -$lang->group->managePrivByModule = '按模組分配權限'; -$lang->group->manageMember = '成員維護'; -$lang->group->linkMember = '關聯用戶'; -$lang->group->unlinkMember = '移除用戶'; -$lang->group->confirmDelete = '您確定刪除該用戶分組嗎?'; -$lang->group->successSaved = '成功保存'; -$lang->group->errorNotSaved = '沒有保存,請確認選擇了權限數據。'; - -$lang->group->id = '編號'; -$lang->group->name = '分組名稱'; -$lang->group->desc = '分組描述'; -$lang->group->users = '用戶列表'; -$lang->group->module = '模組'; -$lang->group->method = '方法'; -$lang->group->priv = '權限'; -$lang->group->checkall = '全選'; -$lang->group->option = '選項'; -$lang->group->inside = '組內用戶'; -$lang->group->outside = '組外用戶'; - -$lang->group->copyOptions['copyPriv'] = '複製權限'; -$lang->group->copyOptions['copyUser'] = '複製用戶'; - -$lang->group->versions[''] = '顯示各版本新增權限'; -$lang->group->versions['3.0.beta1'] = '禪道3.0.beta1'; -$lang->group->versions['2.4'] = '禪道2.4'; -$lang->group->versions['2.3'] = '禪道2.3'; -$lang->group->versions['2.2'] = '禪道2.2'; -$lang->group->versions['2.1'] = '禪道2.1'; -$lang->group->versions['2.0'] = '禪道2.0'; -$lang->group->versions['1.5'] = '禪道1.5'; -$lang->group->versions['1.4'] = '禪道1.4'; -$lang->group->versions['1.3'] = '禪道1.3'; -$lang->group->versions['1.2'] = '禪道1.2'; -$lang->group->versions['1.1'] = '禪道1.1'; -$lang->group->versions['1.0.1'] = '禪道1.0.1'; - -include (dirname(__FILE__) . '/resource.php'); + + * @package group + * @version $Id: zh-tw.php 2530 2012-01-04 05:38:07Z wwccss $ + * @link http://www.zentao.net + */ +$lang->group->common = '權限分組'; +$lang->group->browse = '瀏覽分組'; +$lang->group->create = '新增分組'; +$lang->group->edit = '編輯分組'; +$lang->group->copy = '複製分組'; +$lang->group->delete = '刪除分組'; +$lang->group->managePriv = '權限維護'; +$lang->group->managePrivByGroup = '權限維護'; +$lang->group->managePrivByModule = '按模組分配權限'; +$lang->group->manageMember = '成員維護'; +$lang->group->linkMember = '關聯用戶'; +$lang->group->unlinkMember = '移除用戶'; +$lang->group->confirmDelete = '您確定刪除該用戶分組嗎?'; +$lang->group->successSaved = '成功保存'; +$lang->group->errorNotSaved = '沒有保存,請確認選擇了權限數據。'; + +$lang->group->id = '編號'; +$lang->group->name = '分組名稱'; +$lang->group->desc = '分組描述'; +$lang->group->users = '用戶列表'; +$lang->group->module = '模組'; +$lang->group->method = '方法'; +$lang->group->priv = '權限'; +$lang->group->checkall = '全選'; +$lang->group->option = '選項'; +$lang->group->inside = '組內用戶'; +$lang->group->outside = '組外用戶'; + +$lang->group->copyOptions['copyPriv'] = '複製權限'; +$lang->group->copyOptions['copyUser'] = '複製用戶'; + +$lang->group->versions[''] = '顯示各版本新增權限'; +$lang->group->versions['3.0.beta1'] = '禪道3.0.beta1'; +$lang->group->versions['2.4'] = '禪道2.4'; +$lang->group->versions['2.3'] = '禪道2.3'; +$lang->group->versions['2.2'] = '禪道2.2'; +$lang->group->versions['2.1'] = '禪道2.1'; +$lang->group->versions['2.0'] = '禪道2.0'; +$lang->group->versions['1.5'] = '禪道1.5'; +$lang->group->versions['1.4'] = '禪道1.4'; +$lang->group->versions['1.3'] = '禪道1.3'; +$lang->group->versions['1.2'] = '禪道1.2'; +$lang->group->versions['1.1'] = '禪道1.1'; +$lang->group->versions['1.0.1'] = '禪道1.0.1'; + +include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/model.php b/module/group/model.php index 7684da8449..43f661ff07 100644 --- a/module/group/model.php +++ b/module/group/model.php @@ -1,251 +1,251 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> -specialChars('name, desc')->get(); - return $this->dao->insert(TABLE_GROUP)->data($group)->batchCheck($this->config->group->create->requiredFields, 'notempty')->exec(); - } - - /** - * Update a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function update($groupID) - { - $group = fixer::input('post')->specialChars('name, desc')->get(); - return $this->dao->update(TABLE_GROUP)->data($group)->batchCheck($this->config->group->edit->requiredFields, 'notempty')->where('id')->eq($groupID)->exec(); - } - - /** - * Copy a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function copy($groupID) - { - $group = fixer::input('post')->specialChars('name, desc')->remove('options')->get(); - $this->dao->insert(TABLE_GROUP)->data($group)->check('name', 'unique')->check('name', 'notempty')->exec(); - if($this->post->options == false) return; - if(!dao::isError()) - { - $newGroupID = $this->dao->lastInsertID(); - $options = join(',', $this->post->options); - if(strpos($options, 'copyPriv') !== false) $this->copyPriv($groupID, $newGroupID); - if(strpos($options, 'copyUser') !== false) $this->copyUser($groupID, $newGroupID); - } - } - - /** - * Copy privileges. - * - * @param string $fromGroup - * @param string $toGroup - * @access private - * @return void - */ - private function copyPriv($fromGroup, $toGroup) - { - $privs = $this->dao->findByGroup($fromGroup)->from(TABLE_GROUPPRIV)->fetchAll(); - foreach($privs as $priv) - { - $priv->group = $toGroup; - $this->dao->insert(TABLE_GROUPPRIV)->data($priv)->exec(); - } - } - - /** - * Copy user. - * - * @param string $fromGroup - * @param string $toGroup - * @access private - * @return void - */ - private function copyUser($fromGroup, $toGroup) - { - $users = $this->dao->findByGroup($fromGroup)->from(TABLE_USERGROUP)->fetchAll(); - foreach($users as $user) - { - $user->group = $toGroup; - $this->dao->insert(TABLE_USERGROUP)->data($user)->exec(); - } - } - - /** - * Get group lists. - * - * @param int $companyID - * @access public - * @return array - */ - public function getList($companyID) - { - return $this->dao->findByCompany($companyID)->from(TABLE_GROUP)->fetchAll(); - } - - /** - * Get group pairs. - * - * @access public - * @return array - */ - public function getPairs() - { - return $this->dao->findByCompany($this->app->company->id)->fields('id, name')->from(TABLE_GROUP)->fetchPairs(); - } - - /** - * Get group by id. - * - * @param int $groupID - * @access public - * @return object - */ - public function getByID($groupID) - { - return $this->dao->findById($groupID)->from(TABLE_GROUP)->fetch(); - } - - /** - * Get privileges of a groups. - * - * @param int $groupID - * @access public - * @return array - */ - public function getPrivs($groupID) - { - $privs = array(); - $stmt = $this->dao->select('module, method')->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->orderBy('module')->query(); - while($priv = $stmt->fetch()) $privs[$priv->module][$priv->method] = $priv->method; - return $privs; - } - - /** - * Get user pairs of a group. - * - * @param int $groupID - * @access public - * @return array - */ - public function getUserPairs($groupID) - { - return $this->dao->select('t2.account, t2.realname') - ->from(TABLE_USERGROUP)->alias('t1') - ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') - ->where('`group`')->eq((int)$groupID) - ->andWhere('t2.deleted')->eq(0) - ->andWhere('t2.company')->eq($this->app->company->id) - ->orderBy('t2.account') - ->fetchPairs(); - } - - /** - * Delete a group. - * - * @param int $groupID - * @access public - * @return void - */ - public function delete($groupID) - { - $this->dao->delete()->from(TABLE_GROUP)->where('id')->eq($groupID)->exec(); - $this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->exec(); - $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->exec(); - } - - /** - * Update privilege of a group. - * - * @param int $groupID - * @access public - * @return bool - */ - public function updatePrivByGroup($groupID) - { - /* Delete old. */ - $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->exec(); - - /* Insert new. */ - foreach($this->post->actions as $moduleName => $moduleActions) - { - foreach($moduleActions as $actionName) - { - $data->group = $groupID; - $data->module = $moduleName; - $data->method = $actionName; - $this->dao->insert(TABLE_GROUPPRIV)->data($data)->exec(); - } - } - return true; - } - - /** - * Update privilege by module. - * - * @access public - * @return void - */ - public function updatePrivByModule() - { - if($this->post->module == false or $this->post->actions == false or $this->post->groups == false) return false; - - foreach($this->post->actions as $action) - { - foreach($this->post->groups as $group) - { - $data->group = $group; - $data->module = $this->post->module; - $data->method = $action; - $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); - } - } - return true; - } - - /** - * Update users. - * - * @param int $groupID - * @access public - * @return void - */ - public function updateUser($groupID) - { - /* Delete old. */ - $this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->exec(); - - /* Insert new. */ - if($this->post->members == false) return; - foreach($this->post->members as $account) - { - $data->account = $account; - $data->group = $groupID; - $this->dao->insert(TABLE_USERGROUP)->data($data)->exec(); - } - } -} + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> +specialChars('name, desc')->get(); + return $this->dao->insert(TABLE_GROUP)->data($group)->batchCheck($this->config->group->create->requiredFields, 'notempty')->exec(); + } + + /** + * Update a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function update($groupID) + { + $group = fixer::input('post')->specialChars('name, desc')->get(); + return $this->dao->update(TABLE_GROUP)->data($group)->batchCheck($this->config->group->edit->requiredFields, 'notempty')->where('id')->eq($groupID)->exec(); + } + + /** + * Copy a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function copy($groupID) + { + $group = fixer::input('post')->specialChars('name, desc')->remove('options')->get(); + $this->dao->insert(TABLE_GROUP)->data($group)->check('name', 'unique')->check('name', 'notempty')->exec(); + if($this->post->options == false) return; + if(!dao::isError()) + { + $newGroupID = $this->dao->lastInsertID(); + $options = join(',', $this->post->options); + if(strpos($options, 'copyPriv') !== false) $this->copyPriv($groupID, $newGroupID); + if(strpos($options, 'copyUser') !== false) $this->copyUser($groupID, $newGroupID); + } + } + + /** + * Copy privileges. + * + * @param string $fromGroup + * @param string $toGroup + * @access private + * @return void + */ + private function copyPriv($fromGroup, $toGroup) + { + $privs = $this->dao->findByGroup($fromGroup)->from(TABLE_GROUPPRIV)->fetchAll(); + foreach($privs as $priv) + { + $priv->group = $toGroup; + $this->dao->insert(TABLE_GROUPPRIV)->data($priv)->exec(); + } + } + + /** + * Copy user. + * + * @param string $fromGroup + * @param string $toGroup + * @access private + * @return void + */ + private function copyUser($fromGroup, $toGroup) + { + $users = $this->dao->findByGroup($fromGroup)->from(TABLE_USERGROUP)->fetchAll(); + foreach($users as $user) + { + $user->group = $toGroup; + $this->dao->insert(TABLE_USERGROUP)->data($user)->exec(); + } + } + + /** + * Get group lists. + * + * @param int $companyID + * @access public + * @return array + */ + public function getList($companyID) + { + return $this->dao->findByCompany($companyID)->from(TABLE_GROUP)->fetchAll(); + } + + /** + * Get group pairs. + * + * @access public + * @return array + */ + public function getPairs() + { + return $this->dao->findByCompany($this->app->company->id)->fields('id, name')->from(TABLE_GROUP)->fetchPairs(); + } + + /** + * Get group by id. + * + * @param int $groupID + * @access public + * @return object + */ + public function getByID($groupID) + { + return $this->dao->findById($groupID)->from(TABLE_GROUP)->fetch(); + } + + /** + * Get privileges of a groups. + * + * @param int $groupID + * @access public + * @return array + */ + public function getPrivs($groupID) + { + $privs = array(); + $stmt = $this->dao->select('module, method')->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->orderBy('module')->query(); + while($priv = $stmt->fetch()) $privs[$priv->module][$priv->method] = $priv->method; + return $privs; + } + + /** + * Get user pairs of a group. + * + * @param int $groupID + * @access public + * @return array + */ + public function getUserPairs($groupID) + { + return $this->dao->select('t2.account, t2.realname') + ->from(TABLE_USERGROUP)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') + ->where('`group`')->eq((int)$groupID) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t2.company')->eq($this->app->company->id) + ->orderBy('t2.account') + ->fetchPairs(); + } + + /** + * Delete a group. + * + * @param int $groupID + * @access public + * @return void + */ + public function delete($groupID) + { + $this->dao->delete()->from(TABLE_GROUP)->where('id')->eq($groupID)->exec(); + $this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->exec(); + $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->exec(); + } + + /** + * Update privilege of a group. + * + * @param int $groupID + * @access public + * @return bool + */ + public function updatePrivByGroup($groupID) + { + /* Delete old. */ + $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->exec(); + + /* Insert new. */ + foreach($this->post->actions as $moduleName => $moduleActions) + { + foreach($moduleActions as $actionName) + { + $data->group = $groupID; + $data->module = $moduleName; + $data->method = $actionName; + $this->dao->insert(TABLE_GROUPPRIV)->data($data)->exec(); + } + } + return true; + } + + /** + * Update privilege by module. + * + * @access public + * @return void + */ + public function updatePrivByModule() + { + if($this->post->module == false or $this->post->actions == false or $this->post->groups == false) return false; + + foreach($this->post->actions as $action) + { + foreach($this->post->groups as $group) + { + $data->group = $group; + $data->module = $this->post->module; + $data->method = $action; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); + } + } + return true; + } + + /** + * Update users. + * + * @param int $groupID + * @access public + * @return void + */ + public function updateUser($groupID) + { + /* Delete old. */ + $this->dao->delete()->from(TABLE_USERGROUP)->where('`group`')->eq($groupID)->exec(); + + /* Insert new. */ + if($this->post->members == false) return; + foreach($this->post->members as $account) + { + $data->account = $account; + $data->group = $groupID; + $this->dao->insert(TABLE_USERGROUP)->data($data)->exec(); + } + } +} diff --git a/module/group/view/browse.html.php b/module/group/view/browse.html.php index 983ba41a46..fd325a9b1e 100644 --- a/module/group/view/browse.html.php +++ b/module/group/view/browse.html.php @@ -1,50 +1,50 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          group->browse;?>
          -
          group->create);?>
          -
          group->id;?>group->name;?>group->desc;?>group->users;?>actions;?>
          id;?>name;?>desc;?>id] as $user) echo "$user";?> - id", $lang->group->managePrivByGroup);?> - id", $lang->group->manageMember);?> - id", $lang->edit);?> - id", $lang->copy);?> - id", $lang->delete, "hiddenwin");?> -
          group->managePrivByModule, inlink('managePriv', 'type=byModule'));?>
          - + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          group->browse;?>
          +
          group->create);?>
          +
          group->id;?>group->name;?>group->desc;?>group->users;?>actions;?>
          id;?>name;?>desc;?>id] as $user) echo "$user";?> + id", $lang->group->managePrivByGroup);?> + id", $lang->group->manageMember);?> + id", $lang->edit);?> + id", $lang->copy);?> + id", $lang->delete, "hiddenwin");?> +
          group->managePrivByModule, inlink('managePriv', 'type=byModule'));?>
          + diff --git a/module/group/view/copy.html.php b/module/group/view/copy.html.php index 6d03c56a03..553892a363 100644 --- a/module/group/view/copy.html.php +++ b/module/group/view/copy.html.php @@ -1,32 +1,32 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - -
          group->copy;?>
          group->name;?>name, "class='text-1'");?>
          group->desc;?>desc, "rows='5' class='area-1'");?>
          group->option;?>group->copyOptions);?>
          -
          - + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + +
          group->copy;?>
          group->name;?>name, "class='text-1'");?>
          group->desc;?>desc, "rows='5' class='area-1'");?>
          group->option;?>group->copyOptions);?>
          +
          + diff --git a/module/group/view/create.html.php b/module/group/view/create.html.php index 30dd3d663a..c049270002 100644 --- a/module/group/view/create.html.php +++ b/module/group/view/create.html.php @@ -1,28 +1,28 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - -
          group->create;?>
          group->name;?>
          group->desc;?>
          -
          - + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + +
          group->create;?>
          group->name;?>
          group->desc;?>
          +
          + diff --git a/module/group/view/edit.html.php b/module/group/view/edit.html.php index 481899c78c..88dfbae365 100644 --- a/module/group/view/edit.html.php +++ b/module/group/view/edit.html.php @@ -1,28 +1,28 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - -
          group->edit;?>
          group->name;?>name, "class='text-1'");?>
          group->desc;?>desc, "rows='5' class='area-1'");?>
          -
          - + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + +
          group->edit;?>
          group->name;?>name, "class='text-1'");?>
          group->desc;?>desc, "rows='5' class='area-1'");?>
          +
          + diff --git a/module/group/view/managemember.html.php b/module/group/view/managemember.html.php index e76755f2bd..b0c75001f7 100644 --- a/module/group/view/managemember.html.php +++ b/module/group/view/managemember.html.php @@ -1,47 +1,47 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - -
          name . $lang->colon . $lang->group->manageMember;?>
          group->inside;?> - $realname):?> -
          ' . html::checkbox('members', array($account => $realname), $account) . '';?>
          - "; $i ++;?> - -
          group->outside;?> - $realname):?> -
          ' . html::checkbox('members', array($account => $realname), '') . '';?>
          - "; $i ++;?> - -
          - goback, $this->createLink('group', 'browse')); - echo html::hidden('foo'); // Just a var, to make sure $_POST is not empty. - ?> -
          -
          - + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + +
          name . $lang->colon . $lang->group->manageMember;?>
          group->inside;?> + $realname):?> +
          ' . html::checkbox('members', array($account => $realname), $account) . '';?>
          + "; $i ++;?> + +
          group->outside;?> + $realname):?> +
          ' . html::checkbox('members', array($account => $realname), '') . '';?>
          + "; $i ++;?> + +
          + goback, $this->createLink('group', 'browse')); + echo html::hidden('foo'); // Just a var, to make sure $_POST is not empty. + ?> +
          +
          + diff --git a/module/group/view/managepriv.html.php b/module/group/view/managepriv.html.php index 2955ae9191..33240ca990 100644 --- a/module/group/view/managepriv.html.php +++ b/module/group/view/managepriv.html.php @@ -1,17 +1,17 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ +?> + - * @package group - * @version $Id: managepriv.html.php 1517 2011-03-07 10:02:57Z wwccss $ - * @link http://www.zentao.net - */ -?> -
          - - - - - - - resource as $moduleName => $moduleActions):?> - '> - - - - - - - -
          name . $lang->colon . $lang->group->managePriv;?> - - lang->group->versions, '', "onchange=showPriv(this.value)"); - ?> - -
          group->module;?>group->method;?>
          lang->$moduleName->common;?> - - - $actionLabel):?> -
          - /> - >$moduleName->$actionLabel;?> -
          - "; $i ++;?> - -
          group->checkall;?> - save); - echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); - echo html::hidden('foo'); // Just a hidden var, to make sure $_POST is not empty. - ?> -
          -
          - + + * @package group + * @version $Id: managepriv.html.php 1517 2011-03-07 10:02:57Z wwccss $ + * @link http://www.zentao.net + */ +?> +
          + + + + + + + resource as $moduleName => $moduleActions):?> + '> + + + + + + + +
          name . $lang->colon . $lang->group->managePriv;?> + + lang->group->versions, '', "onchange=showPriv(this.value)"); + ?> + +
          group->module;?>group->method;?>
          lang->$moduleName->common;?> + + + $actionLabel):?> +
          + /> + >$moduleName->$actionLabel;?> +
          + "; $i ++;?> + +
          group->checkall;?> + save); + echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); + echo html::hidden('foo'); // Just a hidden var, to make sure $_POST is not empty. + ?> +
          +
          + diff --git a/module/group/view/privbymodule.html.php b/module/group/view/privbymodule.html.php index a124c382c1..89030c1b89 100644 --- a/module/group/view/privbymodule.html.php +++ b/module/group/view/privbymodule.html.php @@ -1,45 +1,45 @@ - - * @package group - * @version $Id: managepriv.html.php 1517 2011-03-07 10:02:57Z wwccss $ - * @link http://www.zentao.net - */ -?> -
          - - - - - - - - - - - - - - - -
          group->managePriv;?>
          group->module;?>group->method;?>group->common;?>
          - $moduleActions) - { - echo html::select('actions[]', $moduleActions, '', "multiple='multiple' class='$class {$module}Actions'"); - $class = 'hidden'; - } - ?> -
          - save); - echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); - echo html::hidden('foo'); // Just make $_POST not empty.. - ?> -
          -
          + + * @package group + * @version $Id: managepriv.html.php 1517 2011-03-07 10:02:57Z wwccss $ + * @link http://www.zentao.net + */ +?> +
          + + + + + + + + + + + + + + + +
          group->managePriv;?>
          group->module;?>group->method;?>group->common;?>
          + $moduleActions) + { + echo html::select('actions[]', $moduleActions, '', "multiple='multiple' class='$class {$module}Actions'"); + $class = 'hidden'; + } + ?> +
          + save); + echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); + echo html::hidden('foo'); // Just make $_POST not empty.. + ?> +
          +
          diff --git a/module/help/control.php b/module/help/control.php index c6e8e61c99..8232219f31 100644 --- a/module/help/control.php +++ b/module/help/control.php @@ -1,46 +1,46 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -class help extends control -{ - /** - * Get the help info of a field.. - * - * @param string $module - * @param string $method - * @param string $field - * @param string $clientLang - * @access public - * @return void - */ - public function field($module, $method, $field) - { - $clientLang = $this->app->getClientLang(); - include "./lang/field.$clientLang.php"; - - $fieldName = ''; - $fieldNote = $this->lang->help->noHelpYet; - if(isset($help->$module->$field)) - { - $fieldHelp = explode('|', $help->$module->$field); - $fieldName = $fieldHelp[0]; - if(isset($fieldHelp[1])) $fieldNote = $fieldHelp[1]; - } - elseif($field == 'labels') - { - list($fieldName, $fieldNote) = explode('|', $help->file->labels); - } - $this->view->header->title = $fieldName; - $this->view->fieldName = $fieldName; - $this->view->fieldNote = $fieldNote; - $this->display(); - } -} + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +class help extends control +{ + /** + * Get the help info of a field.. + * + * @param string $module + * @param string $method + * @param string $field + * @param string $clientLang + * @access public + * @return void + */ + public function field($module, $method, $field) + { + $clientLang = $this->app->getClientLang(); + include "./lang/field.$clientLang.php"; + + $fieldName = ''; + $fieldNote = $this->lang->help->noHelpYet; + if(isset($help->$module->$field)) + { + $fieldHelp = explode('|', $help->$module->$field); + $fieldName = $fieldHelp[0]; + if(isset($fieldHelp[1])) $fieldNote = $fieldHelp[1]; + } + elseif($field == 'labels') + { + list($fieldName, $fieldNote) = explode('|', $help->file->labels); + } + $this->view->header->title = $fieldName; + $this->view->fieldName = $fieldName; + $this->view->fieldNote = $fieldNote; + $this->display(); + } +} diff --git a/module/help/model.php b/module/help/model.php index 4a2bda14b7..2bda8b8238 100644 --- a/module/help/model.php +++ b/module/help/model.php @@ -1,15 +1,15 @@ - - * @package help - * @version $Id$ - * @link http://www.zentao.net - */ -class helpModel extends model -{ -} - + + * @package help + * @version $Id$ + * @link http://www.zentao.net + */ +class helpModel extends model +{ +} + diff --git a/module/help/view/field.html.php b/module/help/view/field.html.php index 580d219640..fd95904a08 100644 --- a/module/help/view/field.html.php +++ b/module/help/view/field.html.php @@ -1,19 +1,19 @@ - - * @package help - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          ' . $fieldName . '' . ($fieldName ? $lang->arrow : '') . $fieldNote?>
          - + * @package help + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          ' . $fieldName . '' . ($fieldName ? $lang->arrow : '') . $fieldNote?>
          + - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -class index extends control -{ - /** - * Construct function, load project, product. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - } - - /** - * The index page of whole zentao system. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('my', 'index')); - } - - /** - * Just test the extension engine. - * - * @access public - * @return void - */ - public function testext() - { - echo $this->fetch('misc', 'getsid'); - } -} + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +class index extends control +{ + /** + * Construct function, load project, product. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * The index page of whole zentao system. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('my', 'index')); + } + + /** + * Just test the extension engine. + * + * @access public + * @return void + */ + public function testext() + { + echo $this->fetch('misc', 'getsid'); + } +} diff --git a/module/index/model.php b/module/index/model.php index 162b5bd63a..f934a1bd0a 100644 --- a/module/index/model.php +++ b/module/index/model.php @@ -1,15 +1,15 @@ - - * @package index - * @version $Id$ - */ -?> - + * @package index + * @version $Id$ + */ +?> + - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -class install extends control -{ - /** - * Construct function. - * - * @access public - * @return void - */ - public function __construct() - { - if(!defined('IN_INSTALL')) die(); - parent::__construct(); - $this->config->webRoot = $this->install->getWebRoot(); - } - - /** - * Index page of install module. - * - * @access public - * @return void - */ - public function index() - { - if(!isset($this->config->installed) or !$this->config->installed) $this->session->set('installing', true); - - $this->view->header->title = $this->lang->install->welcome; - - if($release = $this->install->getLatestRelease()) $this->view->latestRelease = $release; - - $this->display(); - } - - /** - * Check the system. - * - * @access public - * @return void - */ - public function step1() - { - $this->view->header->title = $this->lang->install->checking; - $this->view->phpVersion = $this->install->getPhpVersion(); - $this->view->phpResult = $this->install->checkPHP(); - $this->view->pdoResult = $this->install->checkPDO(); - $this->view->pdoMySQLResult = $this->install->checkPDOMySQL(); - $this->view->jsonResult = $this->install->checkJSON(); - $this->view->tmpRootInfo = $this->install->getTmpRoot(); - $this->view->tmpRootResult = $this->install->checkTmpRoot(); - $this->view->dataRootInfo = $this->install->getDataRoot(); - $this->view->dataRootResult = $this->install->checkDataRoot(); - $this->view->iniInfo = $this->install->getIniInfo(); - $this->display(); - } - - /** - * Set configs. - * - * @access public - * @return void - */ - public function step2() - { - $this->view->header->title = $this->lang->install->setConfig; - $this->display(); - } - - /** - * Create the config file. - * - * @access public - * @return void - */ - public function step3() - { - if(!empty($_POST)) - { - $return = $this->install->checkConfig(); - if($return->result == 'ok') - { - $this->view = (object)$_POST; - $this->view->app = $this->app; - $this->view->lang = $this->lang; - $this->view->config = $this->config; - $this->view->domain = $this->server->HTTP_HOST; - $this->view->header->title = $this->lang->install->saveConfig; - $this->display(); - } - else - { - $this->view->header->title = $this->lang->install->saveConfig; - $this->view->error = $return->error; - $this->display(); - } - } - else - { - $this->locate($this->createLink('install')); - } - } - - /** - * Create company, admin. - * - * @access public - * @return void - */ - public function step4() - { - if(!empty($_POST)) - { - $this->install->grantPriv(); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('setting')->updateVersion($this->config->version); - $this->setting->setSN(); - echo (js::alert($this->lang->install->success)); - unset($_SESSION['installing']); - session_destroy(); - die(js::locate('index.php', 'parent')); - } - - $this->view->header->title = $this->lang->install->getPriv; - if(!isset($this->config->installed) or !$this->config->installed) - { - $this->view->error = $this->lang->install->errorNotSaveConfig; - $this->display(); - } - else - { - $this->view->pmsDomain = $this->server->HTTP_HOST; - $this->display(); - } - } -} + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +class install extends control +{ + /** + * Construct function. + * + * @access public + * @return void + */ + public function __construct() + { + if(!defined('IN_INSTALL')) die(); + parent::__construct(); + $this->config->webRoot = $this->install->getWebRoot(); + } + + /** + * Index page of install module. + * + * @access public + * @return void + */ + public function index() + { + if(!isset($this->config->installed) or !$this->config->installed) $this->session->set('installing', true); + + $this->view->header->title = $this->lang->install->welcome; + + if($release = $this->install->getLatestRelease()) $this->view->latestRelease = $release; + + $this->display(); + } + + /** + * Check the system. + * + * @access public + * @return void + */ + public function step1() + { + $this->view->header->title = $this->lang->install->checking; + $this->view->phpVersion = $this->install->getPhpVersion(); + $this->view->phpResult = $this->install->checkPHP(); + $this->view->pdoResult = $this->install->checkPDO(); + $this->view->pdoMySQLResult = $this->install->checkPDOMySQL(); + $this->view->jsonResult = $this->install->checkJSON(); + $this->view->tmpRootInfo = $this->install->getTmpRoot(); + $this->view->tmpRootResult = $this->install->checkTmpRoot(); + $this->view->dataRootInfo = $this->install->getDataRoot(); + $this->view->dataRootResult = $this->install->checkDataRoot(); + $this->view->iniInfo = $this->install->getIniInfo(); + $this->display(); + } + + /** + * Set configs. + * + * @access public + * @return void + */ + public function step2() + { + $this->view->header->title = $this->lang->install->setConfig; + $this->display(); + } + + /** + * Create the config file. + * + * @access public + * @return void + */ + public function step3() + { + if(!empty($_POST)) + { + $return = $this->install->checkConfig(); + if($return->result == 'ok') + { + $this->view = (object)$_POST; + $this->view->app = $this->app; + $this->view->lang = $this->lang; + $this->view->config = $this->config; + $this->view->domain = $this->server->HTTP_HOST; + $this->view->header->title = $this->lang->install->saveConfig; + $this->display(); + } + else + { + $this->view->header->title = $this->lang->install->saveConfig; + $this->view->error = $return->error; + $this->display(); + } + } + else + { + $this->locate($this->createLink('install')); + } + } + + /** + * Create company, admin. + * + * @access public + * @return void + */ + public function step4() + { + if(!empty($_POST)) + { + $this->install->grantPriv(); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('setting')->updateVersion($this->config->version); + $this->setting->setSN(); + echo (js::alert($this->lang->install->success)); + unset($_SESSION['installing']); + session_destroy(); + die(js::locate('index.php', 'parent')); + } + + $this->view->header->title = $this->lang->install->getPriv; + if(!isset($this->config->installed) or !$this->config->installed) + { + $this->view->error = $this->lang->install->errorNotSaveConfig; + $this->display(); + } + else + { + $this->view->pmsDomain = $this->server->HTTP_HOST; + $this->display(); + } + } +} diff --git a/module/install/lang/en.php b/module/install/lang/en.php index d03f19a022..571ca89f68 100644 --- a/module/install/lang/en.php +++ b/module/install/lang/en.php @@ -1,105 +1,105 @@ - - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->install->common = 'Install'; -$lang->install->next = 'Next'; -$lang->install->pre = 'Back'; -$lang->install->reload = 'Reload'; -$lang->install->error = 'Error '; - -$lang->install->start = 'Start install'; -$lang->install->keepInstalling = 'Keep install this version'; -$lang->install->seeLatestRelease = 'See the latest release.'; -$lang->install->welcome = 'Welcome to use ZenTaoPMS.'; -$lang->install->desc = <<Nature EasySoft Network Tecnology Co.ltd, QingDao, China。 -The official website of ZenTaoPMS is http://en.zentao.net -twitter:zentaopms - -The version of current release is %s。 -EOT; - - - -$lang->install->newReleased= "Notice:There is a new version %s, released on %s。"; -$lang->install->choice = 'You can '; -$lang->install->checking = 'System checking'; -$lang->install->ok = 'OK(√)'; -$lang->install->fail = 'Failed(×)'; -$lang->install->loaded = 'Loaded'; -$lang->install->unloaded = 'Not loaded'; -$lang->install->exists = 'Exists '; -$lang->install->notExists = 'Not exists '; -$lang->install->writable = 'Writable '; -$lang->install->notWritable= 'Not writable '; -$lang->install->phpINI = 'PHP ini file'; -$lang->install->checkItem = 'Items'; -$lang->install->current = 'Current'; -$lang->install->result = 'Result'; -$lang->install->action = 'How to fix'; - -$lang->install->phpVersion = 'PHP version'; -$lang->install->phpFail = 'Must > 5.2.0'; - -$lang->install->pdo = 'PDO extension'; -$lang->install->pdoFail = 'Edit the php.ini file to load PDO extsion.'; -$lang->install->pdoMySQL = 'PDO_MySQL extension'; -$lang->install->pdoMySQLFail = 'Edit the php.ini file to load PDO_MySQL extsion.'; -$lang->install->json = 'JSON extension'; -$lang->install->jsonFail = 'Edit the php.ini file to load JSON extension'; -$lang->install->tmpRoot = 'Temp directory'; -$lang->install->dataRoot = 'Upload directory.'; -$lang->install->mkdir = '

          Should creat the directory %s。
          Under linux, can try
          mkdir -p %s

          '; -$lang->install->chmod = 'Should change the permission of "%s".
          Under linux, can try
          chmod o=rwx -R %s'; - -$lang->install->settingDB = 'Set database'; -$lang->install->webRoot = 'ZenTaoPMS path'; -$lang->install->requestType = 'URL type'; -$lang->install->defaultLang = 'Default Language'; -$lang->install->dbHost = 'Database host'; -$lang->install->dbHostNote = 'If localhost can not connect, try 127.0.0.1'; -$lang->install->dbPort = 'Host port'; -$lang->install->dbUser = 'Database user'; -$lang->install->dbPassword = 'Database password'; -$lang->install->dbName = 'Database name'; -$lang->install->dbPrefix = 'Table prefix'; -$lang->install->createDB = 'Auto create database'; -$lang->install->clearDB = 'Clear data if database exists.'; - -$lang->install->requestTypes['GET'] = 'GET'; -$lang->install->requestTypes['PATH_INFO'] = 'PATH_INFO'; - -$lang->install->errorConnectDB = 'Database connect failed.'; -$lang->install->errorCreateDB = 'Database create failed.'; -$lang->install->errorDBExists = 'Database alread exists, to continue install, check the clear db box.'; -$lang->install->errorCreateTable = 'Table create failed.'; - -$lang->install->setConfig = 'Create config file'; -$lang->install->key = 'Item'; -$lang->install->value = 'Value'; -$lang->install->saveConfig = 'Save config'; -$lang->install->save2File = '
          Try to save the config auto, but failed.
          Copy the text of the textareaand save to " %s ".'; -$lang->install->saved2File = 'The config file has saved to "%s ".'; -$lang->install->errorNotSaveConfig = "Hasn't save the config file. "; - -$lang->install->getPriv = 'Set admin'; -$lang->install->company = 'Company name'; -$lang->install->pms = 'ZenTaoPMS domain'; -$lang->install->pmsNote = 'The domain name or ip address of ZenTaoPMS, no http://'; -$lang->install->account = 'Administrator'; -$lang->install->password = 'Admin password'; -$lang->install->errorEmptyPassword = "Can't be empty"; - -$lang->install->success = "Success installed, please login into ZenTaoPMS, create groups and grant priviledges."; + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->install->common = 'Install'; +$lang->install->next = 'Next'; +$lang->install->pre = 'Back'; +$lang->install->reload = 'Reload'; +$lang->install->error = 'Error '; + +$lang->install->start = 'Start install'; +$lang->install->keepInstalling = 'Keep install this version'; +$lang->install->seeLatestRelease = 'See the latest release.'; +$lang->install->welcome = 'Welcome to use ZenTaoPMS.'; +$lang->install->desc = <<Nature EasySoft Network Tecnology Co.ltd, QingDao, China。 +The official website of ZenTaoPMS is http://en.zentao.net +twitter:zentaopms + +The version of current release is %s。 +EOT; + + + +$lang->install->newReleased= "Notice:There is a new version %s, released on %s。"; +$lang->install->choice = 'You can '; +$lang->install->checking = 'System checking'; +$lang->install->ok = 'OK(√)'; +$lang->install->fail = 'Failed(×)'; +$lang->install->loaded = 'Loaded'; +$lang->install->unloaded = 'Not loaded'; +$lang->install->exists = 'Exists '; +$lang->install->notExists = 'Not exists '; +$lang->install->writable = 'Writable '; +$lang->install->notWritable= 'Not writable '; +$lang->install->phpINI = 'PHP ini file'; +$lang->install->checkItem = 'Items'; +$lang->install->current = 'Current'; +$lang->install->result = 'Result'; +$lang->install->action = 'How to fix'; + +$lang->install->phpVersion = 'PHP version'; +$lang->install->phpFail = 'Must > 5.2.0'; + +$lang->install->pdo = 'PDO extension'; +$lang->install->pdoFail = 'Edit the php.ini file to load PDO extsion.'; +$lang->install->pdoMySQL = 'PDO_MySQL extension'; +$lang->install->pdoMySQLFail = 'Edit the php.ini file to load PDO_MySQL extsion.'; +$lang->install->json = 'JSON extension'; +$lang->install->jsonFail = 'Edit the php.ini file to load JSON extension'; +$lang->install->tmpRoot = 'Temp directory'; +$lang->install->dataRoot = 'Upload directory.'; +$lang->install->mkdir = '

          Should creat the directory %s。
          Under linux, can try
          mkdir -p %s

          '; +$lang->install->chmod = 'Should change the permission of "%s".
          Under linux, can try
          chmod o=rwx -R %s'; + +$lang->install->settingDB = 'Set database'; +$lang->install->webRoot = 'ZenTaoPMS path'; +$lang->install->requestType = 'URL type'; +$lang->install->defaultLang = 'Default Language'; +$lang->install->dbHost = 'Database host'; +$lang->install->dbHostNote = 'If localhost can not connect, try 127.0.0.1'; +$lang->install->dbPort = 'Host port'; +$lang->install->dbUser = 'Database user'; +$lang->install->dbPassword = 'Database password'; +$lang->install->dbName = 'Database name'; +$lang->install->dbPrefix = 'Table prefix'; +$lang->install->createDB = 'Auto create database'; +$lang->install->clearDB = 'Clear data if database exists.'; + +$lang->install->requestTypes['GET'] = 'GET'; +$lang->install->requestTypes['PATH_INFO'] = 'PATH_INFO'; + +$lang->install->errorConnectDB = 'Database connect failed.'; +$lang->install->errorCreateDB = 'Database create failed.'; +$lang->install->errorDBExists = 'Database alread exists, to continue install, check the clear db box.'; +$lang->install->errorCreateTable = 'Table create failed.'; + +$lang->install->setConfig = 'Create config file'; +$lang->install->key = 'Item'; +$lang->install->value = 'Value'; +$lang->install->saveConfig = 'Save config'; +$lang->install->save2File = '
          Try to save the config auto, but failed.
          Copy the text of the textareaand save to " %s ".'; +$lang->install->saved2File = 'The config file has saved to "%s ".'; +$lang->install->errorNotSaveConfig = "Hasn't save the config file. "; + +$lang->install->getPriv = 'Set admin'; +$lang->install->company = 'Company name'; +$lang->install->pms = 'ZenTaoPMS domain'; +$lang->install->pmsNote = 'The domain name or ip address of ZenTaoPMS, no http://'; +$lang->install->account = 'Administrator'; +$lang->install->password = 'Admin password'; +$lang->install->errorEmptyPassword = "Can't be empty"; + +$lang->install->success = "Success installed, please login into ZenTaoPMS, create groups and grant priviledges."; diff --git a/module/install/lang/zh-cn.php b/module/install/lang/zh-cn.php index 3be915ef4b..7a503f8dc8 100644 --- a/module/install/lang/zh-cn.php +++ b/module/install/lang/zh-cn.php @@ -1,106 +1,106 @@ - - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->install->common = '安装'; -$lang->install->next = '下一步'; -$lang->install->pre = '返回'; -$lang->install->reload = '刷新'; -$lang->install->error = '错误 '; - -$lang->install->start = '开始安装'; -$lang->install->keepInstalling = '继续安装当前版本'; -$lang->install->seeLatestRelease = '看看最新的版本'; -$lang->install->welcome = '欢迎使用禅道项目管理软件!'; -$lang->install->desc = <<青岛易软天创网络科技有限公司开发。 -官方网站:http://www.zentao.net -技术支持: http://www.zentao.net/ask/ -新浪微博:t.sina.com.cn/zentaopms -腾讯微博:t.qq.com/zentaopms - -您现在正在安装的版本是 %s。 -EOT; - -$lang->install->newReleased= "提示:官网网站已有最新版本%s, 发布日期于 %s。"; -$lang->install->choice = '您可以选择:'; -$lang->install->checking = '系统检查'; -$lang->install->ok = '检查通过(√)'; -$lang->install->fail = '检查失败(×)'; -$lang->install->loaded = '已加载'; -$lang->install->unloaded = '未加载'; -$lang->install->exists = '目录存在 '; -$lang->install->notExists = '目录不存在 '; -$lang->install->writable = '目录可写 '; -$lang->install->notWritable= '目录不可写 '; -$lang->install->phpINI = 'PHP配置文件'; -$lang->install->checkItem = '检查项'; -$lang->install->current = '当前配置'; -$lang->install->result = '检查结果'; -$lang->install->action = '如何修改'; - -$lang->install->phpVersion = 'PHP版本'; -$lang->install->phpFail = 'PHP版本必须大于5.2.0'; - -$lang->install->pdo = 'PDO扩展'; -$lang->install->pdoFail = '修改PHP配置文件,加载PDO扩展。'; -$lang->install->pdoMySQL = 'PDO_MySQL扩展'; -$lang->install->pdoMySQLFail = '修改PHP配置文件,加载pdo_mysql扩展。'; -$lang->install->json = 'JSON扩展'; -$lang->install->jsonFail = '修改PHP配置文件,加载JSON扩展。'; -$lang->install->tmpRoot = '临时文件目录'; -$lang->install->dataRoot = '上传文件目录'; -$lang->install->mkdir = '

          需要创建目录%s。
          linux下面命令为:
          mkdir -p %s

          '; -$lang->install->chmod = '需要修改目录 "%s" 的权限。
          linux下面命令为:
          chmod o=rwx -R %s'; - -$lang->install->settingDB = '设置数据库'; -$lang->install->webRoot = 'PMS所在网站目录'; -$lang->install->requestType = 'URL方式'; -$lang->install->defaultLang = '默认语言'; -$lang->install->dbHost = '数据库服务器'; -$lang->install->dbHostNote = '如果localhost无法访问,尝试使用127.0.0.1'; -$lang->install->dbPort = '服务器端口'; -$lang->install->dbUser = '数据库用户名'; -$lang->install->dbPassword = '数据库密码'; -$lang->install->dbName = 'PMS使用的库'; -$lang->install->dbPrefix = '建表使用的前缀'; -$lang->install->createDB = '自动创建数据库'; -$lang->install->clearDB = '清空现有数据'; - -$lang->install->requestTypes['GET'] = '普通方式'; -$lang->install->requestTypes['PATH_INFO'] = '静态友好方式'; - -$lang->install->errorConnectDB = '数据库连接失败 '; -$lang->install->errorCreateDB = '数据库创建失败'; -$lang->install->errorDBExists = '数据库已经存在,继续安装请选择清空数据'; -$lang->install->errorCreateTable = '创建表失败'; - -$lang->install->setConfig = '生成配置文件'; -$lang->install->key = '配置项'; -$lang->install->value = '值'; -$lang->install->saveConfig = '保存配置文件'; -$lang->install->save2File = '
          尝试写入配置文件,失败!
          拷贝上面文本框中的内容,将其保存到 " %s "中。您以后还可继续修改此配置文件。'; -$lang->install->saved2File = '配置信息已经成功保存到" %s "中。您后面还可继续修改此文件。'; -$lang->install->errorNotSaveConfig = '还没有保存配置文件'; - -$lang->install->getPriv = '设置帐号'; -$lang->install->company = '公司名称'; -$lang->install->pms = 'PMS地址'; -$lang->install->pmsNote = '即通过什么地址可以访问到禅道项目管理,设置域名或者IP地址即可,不需要http'; -$lang->install->account = '管理员帐号'; -$lang->install->password = '管理员密码'; -$lang->install->errorEmptyPassword = '密码不能为空'; - -$lang->install->success = "安装成功!请删除install.php,登录禅道管理系统,设置用户及分组!"; - + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->install->common = '安装'; +$lang->install->next = '下一步'; +$lang->install->pre = '返回'; +$lang->install->reload = '刷新'; +$lang->install->error = '错误 '; + +$lang->install->start = '开始安装'; +$lang->install->keepInstalling = '继续安装当前版本'; +$lang->install->seeLatestRelease = '看看最新的版本'; +$lang->install->welcome = '欢迎使用禅道项目管理软件!'; +$lang->install->desc = <<青岛易软天创网络科技有限公司开发。 +官方网站:http://www.zentao.net +技术支持: http://www.zentao.net/ask/ +新浪微博:t.sina.com.cn/zentaopms +腾讯微博:t.qq.com/zentaopms + +您现在正在安装的版本是 %s。 +EOT; + +$lang->install->newReleased= "提示:官网网站已有最新版本%s, 发布日期于 %s。"; +$lang->install->choice = '您可以选择:'; +$lang->install->checking = '系统检查'; +$lang->install->ok = '检查通过(√)'; +$lang->install->fail = '检查失败(×)'; +$lang->install->loaded = '已加载'; +$lang->install->unloaded = '未加载'; +$lang->install->exists = '目录存在 '; +$lang->install->notExists = '目录不存在 '; +$lang->install->writable = '目录可写 '; +$lang->install->notWritable= '目录不可写 '; +$lang->install->phpINI = 'PHP配置文件'; +$lang->install->checkItem = '检查项'; +$lang->install->current = '当前配置'; +$lang->install->result = '检查结果'; +$lang->install->action = '如何修改'; + +$lang->install->phpVersion = 'PHP版本'; +$lang->install->phpFail = 'PHP版本必须大于5.2.0'; + +$lang->install->pdo = 'PDO扩展'; +$lang->install->pdoFail = '修改PHP配置文件,加载PDO扩展。'; +$lang->install->pdoMySQL = 'PDO_MySQL扩展'; +$lang->install->pdoMySQLFail = '修改PHP配置文件,加载pdo_mysql扩展。'; +$lang->install->json = 'JSON扩展'; +$lang->install->jsonFail = '修改PHP配置文件,加载JSON扩展。'; +$lang->install->tmpRoot = '临时文件目录'; +$lang->install->dataRoot = '上传文件目录'; +$lang->install->mkdir = '

          需要创建目录%s。
          linux下面命令为:
          mkdir -p %s

          '; +$lang->install->chmod = '需要修改目录 "%s" 的权限。
          linux下面命令为:
          chmod o=rwx -R %s'; + +$lang->install->settingDB = '设置数据库'; +$lang->install->webRoot = 'PMS所在网站目录'; +$lang->install->requestType = 'URL方式'; +$lang->install->defaultLang = '默认语言'; +$lang->install->dbHost = '数据库服务器'; +$lang->install->dbHostNote = '如果localhost无法访问,尝试使用127.0.0.1'; +$lang->install->dbPort = '服务器端口'; +$lang->install->dbUser = '数据库用户名'; +$lang->install->dbPassword = '数据库密码'; +$lang->install->dbName = 'PMS使用的库'; +$lang->install->dbPrefix = '建表使用的前缀'; +$lang->install->createDB = '自动创建数据库'; +$lang->install->clearDB = '清空现有数据'; + +$lang->install->requestTypes['GET'] = '普通方式'; +$lang->install->requestTypes['PATH_INFO'] = '静态友好方式'; + +$lang->install->errorConnectDB = '数据库连接失败 '; +$lang->install->errorCreateDB = '数据库创建失败'; +$lang->install->errorDBExists = '数据库已经存在,继续安装请选择清空数据'; +$lang->install->errorCreateTable = '创建表失败'; + +$lang->install->setConfig = '生成配置文件'; +$lang->install->key = '配置项'; +$lang->install->value = '值'; +$lang->install->saveConfig = '保存配置文件'; +$lang->install->save2File = '
          尝试写入配置文件,失败!
          拷贝上面文本框中的内容,将其保存到 " %s "中。您以后还可继续修改此配置文件。'; +$lang->install->saved2File = '配置信息已经成功保存到" %s "中。您后面还可继续修改此文件。'; +$lang->install->errorNotSaveConfig = '还没有保存配置文件'; + +$lang->install->getPriv = '设置帐号'; +$lang->install->company = '公司名称'; +$lang->install->pms = 'PMS地址'; +$lang->install->pmsNote = '即通过什么地址可以访问到禅道项目管理,设置域名或者IP地址即可,不需要http'; +$lang->install->account = '管理员帐号'; +$lang->install->password = '管理员密码'; +$lang->install->errorEmptyPassword = '密码不能为空'; + +$lang->install->success = "安装成功!请删除install.php,登录禅道管理系统,设置用户及分组!"; + diff --git a/module/install/lang/zh-tw.php b/module/install/lang/zh-tw.php index 4c56cc0d68..1b556a84b6 100644 --- a/module/install/lang/zh-tw.php +++ b/module/install/lang/zh-tw.php @@ -1,106 +1,106 @@ - - * @package install - * @version $Id: zh-tw.php 2503 2012-01-02 06:10:54Z wwccss $ - * @link http://www.zentao.net - */ -$lang->install->common = '安裝'; -$lang->install->next = '下一步'; -$lang->install->pre = '返回'; -$lang->install->reload = '刷新'; -$lang->install->error = '錯誤 '; - -$lang->install->start = '開始安裝'; -$lang->install->keepInstalling = '繼續安裝當前版本'; -$lang->install->seeLatestRelease = '看看最新的版本'; -$lang->install->welcome = '歡迎使用禪道項目管理軟件!'; -$lang->install->desc = <<青島易軟天創網絡科技有限公司開發。 -官方網站:http://www.zentao.net -技術支持: http://www.zentao.net/ask/ -新浪微博:t.sina.com.cn/zentaopms -騰訊微博:t.qq.com/zentaopms - -您現在正在安裝的版本是 %s。 -EOT; - -$lang->install->newReleased= "提示:官網網站已有最新版本%s, 發佈日期于 %s。"; -$lang->install->choice = '您可以選擇:'; -$lang->install->checking = '系統檢查'; -$lang->install->ok = '檢查通過(√)'; -$lang->install->fail = '檢查失敗(×)'; -$lang->install->loaded = '已加載'; -$lang->install->unloaded = '未加載'; -$lang->install->exists = '目錄存在 '; -$lang->install->notExists = '目錄不存在 '; -$lang->install->writable = '目錄可寫 '; -$lang->install->notWritable= '目錄不可寫 '; -$lang->install->phpINI = 'PHP配置檔案'; -$lang->install->checkItem = '檢查項'; -$lang->install->current = '當前配置'; -$lang->install->result = '檢查結果'; -$lang->install->action = '如何修改'; - -$lang->install->phpVersion = 'PHP版本'; -$lang->install->phpFail = 'PHP版本必須大於5.2.0'; - -$lang->install->pdo = 'PDO擴展'; -$lang->install->pdoFail = '修改PHP配置檔案,加載PDO擴展。'; -$lang->install->pdoMySQL = 'PDO_MySQL擴展'; -$lang->install->pdoMySQLFail = '修改PHP配置檔案,加載pdo_mysql擴展。'; -$lang->install->json = 'JSON擴展'; -$lang->install->jsonFail = '修改PHP配置檔案,加載JSON擴展。'; -$lang->install->tmpRoot = '臨時檔案目錄'; -$lang->install->dataRoot = '上傳檔案目錄'; -$lang->install->mkdir = '

          需要創建目錄%s。
          linux下面命令為:
          mkdir -p %s

          '; -$lang->install->chmod = '需要修改目錄 "%s" 的權限。
          linux下面命令為:
          chmod o=rwx -R %s'; - -$lang->install->settingDB = '設置資料庫'; -$lang->install->webRoot = 'PMS所在網站目錄'; -$lang->install->requestType = 'URL方式'; -$lang->install->defaultLang = '預設語言'; -$lang->install->dbHost = '資料庫伺服器'; -$lang->install->dbHostNote = '如果localhost無法訪問,嘗試使用127.0.0.1'; -$lang->install->dbPort = '伺服器連接埠'; -$lang->install->dbUser = '資料庫用戶名'; -$lang->install->dbPassword = '資料庫密碼'; -$lang->install->dbName = 'PMS使用的庫'; -$lang->install->dbPrefix = '建表使用的首碼'; -$lang->install->createDB = '自動創建資料庫'; -$lang->install->clearDB = '清空現有數據'; - -$lang->install->requestTypes['GET'] = '普通方式'; -$lang->install->requestTypes['PATH_INFO'] = '靜態友好方式'; - -$lang->install->errorConnectDB = '資料庫連接失敗 '; -$lang->install->errorCreateDB = '資料庫創建失敗'; -$lang->install->errorDBExists = '資料庫已經存在,繼續安裝請選擇清空數據'; -$lang->install->errorCreateTable = '創建表失敗'; - -$lang->install->setConfig = '生成配置檔案'; -$lang->install->key = '配置項'; -$lang->install->value = '值'; -$lang->install->saveConfig = '保存配置檔案'; -$lang->install->save2File = '
          嘗試寫入配置檔案,失敗!
          拷貝上面文本框中的內容,將其保存到 " %s "中。您以後還可繼續修改此配置檔案。'; -$lang->install->saved2File = '配置信息已經成功保存到" %s "中。您後面還可繼續修改此檔案。'; -$lang->install->errorNotSaveConfig = '還沒有保存配置檔案'; - -$lang->install->getPriv = '設置帳號'; -$lang->install->company = '公司名稱'; -$lang->install->pms = 'PMS地址'; -$lang->install->pmsNote = '即通過什麼地址可以訪問到禪道項目管理,設置域名或者IP地址即可,不需要http'; -$lang->install->account = '管理員帳號'; -$lang->install->password = '管理員密碼'; -$lang->install->errorEmptyPassword = '密碼不能為空'; - -$lang->install->success = "安裝成功!請刪除install.php,登錄禪道管理系統,設置用戶及分組!"; - + + * @package install + * @version $Id: zh-tw.php 2503 2012-01-02 06:10:54Z wwccss $ + * @link http://www.zentao.net + */ +$lang->install->common = '安裝'; +$lang->install->next = '下一步'; +$lang->install->pre = '返回'; +$lang->install->reload = '刷新'; +$lang->install->error = '錯誤 '; + +$lang->install->start = '開始安裝'; +$lang->install->keepInstalling = '繼續安裝當前版本'; +$lang->install->seeLatestRelease = '看看最新的版本'; +$lang->install->welcome = '歡迎使用禪道項目管理軟件!'; +$lang->install->desc = <<青島易軟天創網絡科技有限公司開發。 +官方網站:http://www.zentao.net +技術支持: http://www.zentao.net/ask/ +新浪微博:t.sina.com.cn/zentaopms +騰訊微博:t.qq.com/zentaopms + +您現在正在安裝的版本是 %s。 +EOT; + +$lang->install->newReleased= "提示:官網網站已有最新版本%s, 發佈日期于 %s。"; +$lang->install->choice = '您可以選擇:'; +$lang->install->checking = '系統檢查'; +$lang->install->ok = '檢查通過(√)'; +$lang->install->fail = '檢查失敗(×)'; +$lang->install->loaded = '已加載'; +$lang->install->unloaded = '未加載'; +$lang->install->exists = '目錄存在 '; +$lang->install->notExists = '目錄不存在 '; +$lang->install->writable = '目錄可寫 '; +$lang->install->notWritable= '目錄不可寫 '; +$lang->install->phpINI = 'PHP配置檔案'; +$lang->install->checkItem = '檢查項'; +$lang->install->current = '當前配置'; +$lang->install->result = '檢查結果'; +$lang->install->action = '如何修改'; + +$lang->install->phpVersion = 'PHP版本'; +$lang->install->phpFail = 'PHP版本必須大於5.2.0'; + +$lang->install->pdo = 'PDO擴展'; +$lang->install->pdoFail = '修改PHP配置檔案,加載PDO擴展。'; +$lang->install->pdoMySQL = 'PDO_MySQL擴展'; +$lang->install->pdoMySQLFail = '修改PHP配置檔案,加載pdo_mysql擴展。'; +$lang->install->json = 'JSON擴展'; +$lang->install->jsonFail = '修改PHP配置檔案,加載JSON擴展。'; +$lang->install->tmpRoot = '臨時檔案目錄'; +$lang->install->dataRoot = '上傳檔案目錄'; +$lang->install->mkdir = '

          需要創建目錄%s。
          linux下面命令為:
          mkdir -p %s

          '; +$lang->install->chmod = '需要修改目錄 "%s" 的權限。
          linux下面命令為:
          chmod o=rwx -R %s'; + +$lang->install->settingDB = '設置資料庫'; +$lang->install->webRoot = 'PMS所在網站目錄'; +$lang->install->requestType = 'URL方式'; +$lang->install->defaultLang = '預設語言'; +$lang->install->dbHost = '資料庫伺服器'; +$lang->install->dbHostNote = '如果localhost無法訪問,嘗試使用127.0.0.1'; +$lang->install->dbPort = '伺服器連接埠'; +$lang->install->dbUser = '資料庫用戶名'; +$lang->install->dbPassword = '資料庫密碼'; +$lang->install->dbName = 'PMS使用的庫'; +$lang->install->dbPrefix = '建表使用的首碼'; +$lang->install->createDB = '自動創建資料庫'; +$lang->install->clearDB = '清空現有數據'; + +$lang->install->requestTypes['GET'] = '普通方式'; +$lang->install->requestTypes['PATH_INFO'] = '靜態友好方式'; + +$lang->install->errorConnectDB = '資料庫連接失敗 '; +$lang->install->errorCreateDB = '資料庫創建失敗'; +$lang->install->errorDBExists = '資料庫已經存在,繼續安裝請選擇清空數據'; +$lang->install->errorCreateTable = '創建表失敗'; + +$lang->install->setConfig = '生成配置檔案'; +$lang->install->key = '配置項'; +$lang->install->value = '值'; +$lang->install->saveConfig = '保存配置檔案'; +$lang->install->save2File = '
          嘗試寫入配置檔案,失敗!
          拷貝上面文本框中的內容,將其保存到 " %s "中。您以後還可繼續修改此配置檔案。'; +$lang->install->saved2File = '配置信息已經成功保存到" %s "中。您後面還可繼續修改此檔案。'; +$lang->install->errorNotSaveConfig = '還沒有保存配置檔案'; + +$lang->install->getPriv = '設置帳號'; +$lang->install->company = '公司名稱'; +$lang->install->pms = 'PMS地址'; +$lang->install->pmsNote = '即通過什麼地址可以訪問到禪道項目管理,設置域名或者IP地址即可,不需要http'; +$lang->install->account = '管理員帳號'; +$lang->install->password = '管理員密碼'; +$lang->install->errorEmptyPassword = '密碼不能為空'; + +$lang->install->success = "安裝成功!請刪除install.php,登錄禪道管理系統,設置用戶及分組!"; + diff --git a/module/install/model.php b/module/install/model.php index f755cd9335..9790934e7c 100644 --- a/module/install/model.php +++ b/module/install/model.php @@ -1,373 +1,373 @@ - - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->loadClass('snoopy'); - if(@$snoopy->fetchText('http://www.zentao.net/misc-getlatestrelease.json')) - { - $result = json_decode($snoopy->results); - if(isset($result->release) and $this->config->version != $result->release->version) - { - return $result->release; - } - } - return false; - } - - /** - * Check php version. - * - * @access public - * @return string ok|fail - */ - public function checkPHP() - { - return $result = version_compare(PHP_VERSION, '5.2.0') >= 0 ? 'ok' : 'fail'; - } - - /** - * Check PDO. - * - * @access public - * @return string ok|fail - */ - public function checkPDO() - { - return $result = extension_loaded('pdo') ? 'ok' : 'fail'; - } - - /** - * Check PDO::MySQL - * - * @access public - * @return string ok|fail - */ - public function checkPDOMySQL() - { - return $result = extension_loaded('pdo_mysql') ? 'ok' : 'fail'; - } - - /** - * Check json extension. - * - * @access public - * @return string ok|fail - */ - public function checkJSON() - { - return $result = extension_loaded('json') ? 'ok' : 'fail'; - } - - /** - * Get tempRoot info. - * - * @access public - * @return array - */ - public function getTmpRoot() - { - $result['path'] = $this->app->getTmpRoot(); - $result['exists'] = is_dir($result['path']); - $result['writable']= is_writable($result['path']); - return $result; - } - - /** - * Check tmpRoot. - * - * @access public - * @return string ok|fail - */ - public function checkTmpRoot() - { - $tmpRoot = $this->app->getTmpRoot(); - return $result = (is_dir($tmpRoot) and is_writable($tmpRoot)) ? 'ok' : 'fail'; - } - - /** - * Get data root - * - * @access public - * @return array - */ - public function getDataRoot() - { - $result['path'] = $this->app->getAppRoot() . 'www' . $this->app->getPathFix() . 'data'; - $result['exists'] = is_dir($result['path']); - $result['writable']= is_writable($result['path']); - return $result; - } - - /** - * Check the data root. - * - * @access public - * @return string ok|fail - */ - public function checkDataRoot() - { - $dataRoot = $this->app->getAppRoot() . 'www' . $this->app->getPathFix() . 'data'; - return $result = (is_dir($dataRoot) and is_writable($dataRoot)) ? 'ok' : 'fail'; - } - - /** - * Get the php.ini info. - * - * @access public - * @return string - */ - public function getIniInfo() - { - $iniInfo = ''; - ob_start(); - phpinfo(1); - $lines = explode("\n", strip_tags(ob_get_contents())); - ob_end_clean(); - foreach($lines as $line) if(strpos($line, 'ini') !== false) $iniInfo .= $line . "\n"; - return $iniInfo; - } - - /** - * Get web root. - * - * @access public - * @return string - */ - public function getWebRoot() - { - return rtrim(str_replace('\\', '/', pathinfo($_SERVER['PHP_SELF'], PATHINFO_DIRNAME)), '/') . '/'; - } - - /** - * Check config ok or not. - * - * @access public - * @return array - */ - public function checkConfig() - { - $return->result = 'ok'; - - /* Connect to database. */ - $this->setDBParam(); - $this->dbh = $this->connectDB(); - if(!is_object($this->dbh)) - { - $return->result = 'fail'; - $return->error = $this->lang->install->errorConnectDB . $this->dbh; - return $return; - } - - /* Get mysql version. */ - $version = $this->getMysqlVersion(); - - /* If database no exits, try create it. */ - if(!$this->dbExists()) - { - if(!$this->createDB($version)) - { - $return->result = 'fail'; - $return->error = $this->lang->install->errorCreateDB; - return $return; - } - } - elseif($this->post->clearDB == false) - { - $return->result = 'fail'; - $return->error = $this->lang->install->errorDBExists; - return $return; - } - - /* Create tables. */ - if(!$this->createTable($version)) - { - $return->result = 'fail'; - $return->error = $this->lang->install->errorCreateTable; - return $return; - } - return $return; - } - - /** - * Set database params. - * - * @access public - * @return void - */ - public function setDBParam() - { - $this->config->db->host = $this->post->dbHost; - $this->config->db->name = $this->post->dbName; - $this->config->db->user = $this->post->dbUser; - $this->config->db->password = $this->post->dbPassword; - $this->config->db->port = $this->post->dbPort; - $this->config->db->prefix = $this->post->dbPrefix; - - } - - /** - * Connect to database. - * - * @access public - * @return object - */ - public function connectDB() - { - $dsn = "mysql:host={$this->config->db->host}; port={$this->config->db->port}"; - try - { - $dbh = new PDO($dsn, $this->config->db->user, $this->config->db->password); - $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); - $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $dbh->exec("SET NAMES {$this->config->db->encoding}"); - return $dbh; - } - catch (PDOException $exception) - { - return $exception->getMessage(); - } - } - - /** - * Check db exits or not. - * - * @access public - * @return bool - */ - public function dbExists() - { - $sql = "SHOW DATABASES like '{$this->config->db->name}'"; - return $this->dbh->query($sql)->fetch(); - } - - /** - * Get mysql version. - * - * @access public - * @return string - */ - public function getMysqlVersion() - { - $sql = "SELECT VERSION() AS version"; - $result = $this->dbh->query($sql)->fetch(); - return substr($result->version, 0, 3); - } - - /** - * Create database. - * - * @param string $version - * @access public - * @return bool - */ - public function createDB($version) - { - $sql = "CREATE DATABASE `{$this->config->db->name}`"; - if($version > 4.1) $sql .= " DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"; - return $this->dbh->query($sql); - } - - /** - * Create tables. - * - * @param string $version - * @access public - * @return bool - */ - public function createTable($version) - { - $dbFile = $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'zentao.sql'; - $tables = explode(';', file_get_contents($dbFile)); - foreach($tables as $table) - { - $table = trim($table); - if(empty($table)) continue; - - if(strpos($table, 'CREATE') !== false and $version <= 4.1) - { - $table = str_replace('DEFAULT CHARSET=utf8', '', $table); - } - elseif(strpos($table, 'DROP') !== false and $this->post->clearDB != false) - { - $table = str_replace('--', '', $table); - } - $table = str_replace('`zt_', $this->config->db->name . '.`zt_', $table); - $table = str_replace('zt_', $this->config->db->prefix, $table); - if(!$this->dbh->query($table)) return false; - } - return true; - } - - /** - * Create a comapny, set admin. - * - * @access public - * @return void - */ - public function grantPriv() - { - if($this->post->password == '') die(js::error($this->lang->install->errorEmptyPassword)); - - /* Insert a company. */ - $company->name = $this->post->company; - $company->pms = $this->post->pms; - $company->admins = ",{$this->post->account},"; - $this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->batchCheck('name, pms', 'notempty')->check('pms', 'unique')->exec(); - - if(!dao::isError()) - { - /* Set admin. */ - $companyID = $this->dbh->lastInsertID(); - $admin->account = $this->post->account; - $admin->realname = $this->post->account; - $admin->password = md5($this->post->password); - $admin->company = $companyID; - $this->dao->insert(TABLE_USER)->data($admin)->autoCheck()->check('account', 'notempty')->exec(); - - /* Update the group and groupPriv table. */ - $this->dao->update(TABLE_GROUP)->set('company')->eq($companyID)->exec($autoCompany = false); - $this->dao->update(TABLE_GROUPPRIV)->set('company')->eq($companyID)->exec($autoCompany = false); - } - } -} + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +?> +app->loadClass('snoopy'); + if(@$snoopy->fetchText('http://www.zentao.net/misc-getlatestrelease.json')) + { + $result = json_decode($snoopy->results); + if(isset($result->release) and $this->config->version != $result->release->version) + { + return $result->release; + } + } + return false; + } + + /** + * Check php version. + * + * @access public + * @return string ok|fail + */ + public function checkPHP() + { + return $result = version_compare(PHP_VERSION, '5.2.0') >= 0 ? 'ok' : 'fail'; + } + + /** + * Check PDO. + * + * @access public + * @return string ok|fail + */ + public function checkPDO() + { + return $result = extension_loaded('pdo') ? 'ok' : 'fail'; + } + + /** + * Check PDO::MySQL + * + * @access public + * @return string ok|fail + */ + public function checkPDOMySQL() + { + return $result = extension_loaded('pdo_mysql') ? 'ok' : 'fail'; + } + + /** + * Check json extension. + * + * @access public + * @return string ok|fail + */ + public function checkJSON() + { + return $result = extension_loaded('json') ? 'ok' : 'fail'; + } + + /** + * Get tempRoot info. + * + * @access public + * @return array + */ + public function getTmpRoot() + { + $result['path'] = $this->app->getTmpRoot(); + $result['exists'] = is_dir($result['path']); + $result['writable']= is_writable($result['path']); + return $result; + } + + /** + * Check tmpRoot. + * + * @access public + * @return string ok|fail + */ + public function checkTmpRoot() + { + $tmpRoot = $this->app->getTmpRoot(); + return $result = (is_dir($tmpRoot) and is_writable($tmpRoot)) ? 'ok' : 'fail'; + } + + /** + * Get data root + * + * @access public + * @return array + */ + public function getDataRoot() + { + $result['path'] = $this->app->getAppRoot() . 'www' . $this->app->getPathFix() . 'data'; + $result['exists'] = is_dir($result['path']); + $result['writable']= is_writable($result['path']); + return $result; + } + + /** + * Check the data root. + * + * @access public + * @return string ok|fail + */ + public function checkDataRoot() + { + $dataRoot = $this->app->getAppRoot() . 'www' . $this->app->getPathFix() . 'data'; + return $result = (is_dir($dataRoot) and is_writable($dataRoot)) ? 'ok' : 'fail'; + } + + /** + * Get the php.ini info. + * + * @access public + * @return string + */ + public function getIniInfo() + { + $iniInfo = ''; + ob_start(); + phpinfo(1); + $lines = explode("\n", strip_tags(ob_get_contents())); + ob_end_clean(); + foreach($lines as $line) if(strpos($line, 'ini') !== false) $iniInfo .= $line . "\n"; + return $iniInfo; + } + + /** + * Get web root. + * + * @access public + * @return string + */ + public function getWebRoot() + { + return rtrim(str_replace('\\', '/', pathinfo($_SERVER['PHP_SELF'], PATHINFO_DIRNAME)), '/') . '/'; + } + + /** + * Check config ok or not. + * + * @access public + * @return array + */ + public function checkConfig() + { + $return->result = 'ok'; + + /* Connect to database. */ + $this->setDBParam(); + $this->dbh = $this->connectDB(); + if(!is_object($this->dbh)) + { + $return->result = 'fail'; + $return->error = $this->lang->install->errorConnectDB . $this->dbh; + return $return; + } + + /* Get mysql version. */ + $version = $this->getMysqlVersion(); + + /* If database no exits, try create it. */ + if(!$this->dbExists()) + { + if(!$this->createDB($version)) + { + $return->result = 'fail'; + $return->error = $this->lang->install->errorCreateDB; + return $return; + } + } + elseif($this->post->clearDB == false) + { + $return->result = 'fail'; + $return->error = $this->lang->install->errorDBExists; + return $return; + } + + /* Create tables. */ + if(!$this->createTable($version)) + { + $return->result = 'fail'; + $return->error = $this->lang->install->errorCreateTable; + return $return; + } + return $return; + } + + /** + * Set database params. + * + * @access public + * @return void + */ + public function setDBParam() + { + $this->config->db->host = $this->post->dbHost; + $this->config->db->name = $this->post->dbName; + $this->config->db->user = $this->post->dbUser; + $this->config->db->password = $this->post->dbPassword; + $this->config->db->port = $this->post->dbPort; + $this->config->db->prefix = $this->post->dbPrefix; + + } + + /** + * Connect to database. + * + * @access public + * @return object + */ + public function connectDB() + { + $dsn = "mysql:host={$this->config->db->host}; port={$this->config->db->port}"; + try + { + $dbh = new PDO($dsn, $this->config->db->user, $this->config->db->password); + $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $dbh->exec("SET NAMES {$this->config->db->encoding}"); + return $dbh; + } + catch (PDOException $exception) + { + return $exception->getMessage(); + } + } + + /** + * Check db exits or not. + * + * @access public + * @return bool + */ + public function dbExists() + { + $sql = "SHOW DATABASES like '{$this->config->db->name}'"; + return $this->dbh->query($sql)->fetch(); + } + + /** + * Get mysql version. + * + * @access public + * @return string + */ + public function getMysqlVersion() + { + $sql = "SELECT VERSION() AS version"; + $result = $this->dbh->query($sql)->fetch(); + return substr($result->version, 0, 3); + } + + /** + * Create database. + * + * @param string $version + * @access public + * @return bool + */ + public function createDB($version) + { + $sql = "CREATE DATABASE `{$this->config->db->name}`"; + if($version > 4.1) $sql .= " DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"; + return $this->dbh->query($sql); + } + + /** + * Create tables. + * + * @param string $version + * @access public + * @return bool + */ + public function createTable($version) + { + $dbFile = $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'zentao.sql'; + $tables = explode(';', file_get_contents($dbFile)); + foreach($tables as $table) + { + $table = trim($table); + if(empty($table)) continue; + + if(strpos($table, 'CREATE') !== false and $version <= 4.1) + { + $table = str_replace('DEFAULT CHARSET=utf8', '', $table); + } + elseif(strpos($table, 'DROP') !== false and $this->post->clearDB != false) + { + $table = str_replace('--', '', $table); + } + $table = str_replace('`zt_', $this->config->db->name . '.`zt_', $table); + $table = str_replace('zt_', $this->config->db->prefix, $table); + if(!$this->dbh->query($table)) return false; + } + return true; + } + + /** + * Create a comapny, set admin. + * + * @access public + * @return void + */ + public function grantPriv() + { + if($this->post->password == '') die(js::error($this->lang->install->errorEmptyPassword)); + + /* Insert a company. */ + $company->name = $this->post->company; + $company->pms = $this->post->pms; + $company->admins = ",{$this->post->account},"; + $this->dao->insert(TABLE_COMPANY)->data($company)->autoCheck()->batchCheck('name, pms', 'notempty')->check('pms', 'unique')->exec(); + + if(!dao::isError()) + { + /* Set admin. */ + $companyID = $this->dbh->lastInsertID(); + $admin->account = $this->post->account; + $admin->realname = $this->post->account; + $admin->password = md5($this->post->password); + $admin->company = $companyID; + $this->dao->insert(TABLE_USER)->data($admin)->autoCheck()->check('account', 'notempty')->exec(); + + /* Update the group and groupPriv table. */ + $this->dao->update(TABLE_GROUP)->set('company')->eq($companyID)->exec($autoCompany = false); + $this->dao->update(TABLE_GROUPPRIV)->set('company')->eq($companyID)->exec($autoCompany = false); + } + } +} diff --git a/module/install/view/index.html.php b/module/install/view/index.html.php index 9dc9dd5e4e..b7bd31f7ac 100644 --- a/module/install/view/index.html.php +++ b/module/install/view/index.html.php @@ -1,33 +1,33 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - - - - - -
          install->welcome;?>
          install->desc, $config->version));?>
          - -

          createLink('install', 'step1'), $lang->install->start);?>

          - - install->newReleased, $latestRelease);?> -

          - install->choice; - echo html::a($latestRelease->url, $lang->install->seeLatestRelease, '_blank'); - echo html::a($this->createLink('install', 'step1'), $lang->install->keepInstalling); - ?> -

          - -
          - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + + + + + +
          install->welcome;?>
          install->desc, $config->version));?>
          + +

          createLink('install', 'step1'), $lang->install->start);?>

          + + install->newReleased, $latestRelease);?> +

          + install->choice; + echo html::a($latestRelease->url, $lang->install->seeLatestRelease, '_blank'); + echo html::a($this->createLink('install', 'step1'), $lang->install->keepInstalling); + ?> +

          + +
          + diff --git a/module/install/view/step1.html.php b/module/install/view/step1.html.php index ee0a07898b..ed479aa75f 100644 --- a/module/install/view/step1.html.php +++ b/module/install/view/step1.html.php @@ -1,96 +1,96 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          install->checking;?>
          install->checkItem;?>install->current?>install->result?>install->action?>
          install->phpVersion;?>install->$phpResult;?>install->phpFail;?>
          install->pdo;?>install->loaded) : printf($lang->install->unloaded);?>install->$pdoResult;?>install->pdoFail;?>
          install->pdoMySQL;?>install->loaded) : printf($lang->install->unloaded);?>install->$pdoMySQLResult;?>install->pdoMySQLFail;?>
          install->json;?>install->loaded) : printf($lang->install->unloaded);?>install->$jsonResult;?>install->jsonFail;?>
          install->tmpRoot;?> - install->exists) : print($lang->install->notExists); - $tmpRootInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); - ?> - install->$tmpRootResult;?> - install->mkdir, $tmpRootInfo['path'], $tmpRootInfo['path']); - if(!$tmpRootInfo['writable']) printf($lang->install->chmod, $tmpRootInfo['path'], $tmpRootInfo['path']); - ?> -
          install->dataRoot;?> - install->exists) : print($lang->install->notExists); - $dataRootInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); - ?> - install->$dataRootResult;?> - install->mkdir, $dataRootInfo['path'], $dataRootInfo['path']); - if(!$dataRootInfo['writable']) printf($lang->install->chmod, $dataRootInfo['path'], $dataRootInfo['path']); - ?> -
          - createLink('install', 'step2'), $lang->install->next); - } - else - { - echo html::a($this->createLink('install', 'step1'), $lang->install->reload); - if($pdoResult == 'fail' or $pdoMySQLResult == 'fail') - { - echo '

          ' . '' . $lang->install->phpINI . '
          ' . nl2br($this->install->getIniInfo()) . '

          '; - } - } - ?> -
          - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          install->checking;?>
          install->checkItem;?>install->current?>install->result?>install->action?>
          install->phpVersion;?>install->$phpResult;?>install->phpFail;?>
          install->pdo;?>install->loaded) : printf($lang->install->unloaded);?>install->$pdoResult;?>install->pdoFail;?>
          install->pdoMySQL;?>install->loaded) : printf($lang->install->unloaded);?>install->$pdoMySQLResult;?>install->pdoMySQLFail;?>
          install->json;?>install->loaded) : printf($lang->install->unloaded);?>install->$jsonResult;?>install->jsonFail;?>
          install->tmpRoot;?> + install->exists) : print($lang->install->notExists); + $tmpRootInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); + ?> + install->$tmpRootResult;?> + install->mkdir, $tmpRootInfo['path'], $tmpRootInfo['path']); + if(!$tmpRootInfo['writable']) printf($lang->install->chmod, $tmpRootInfo['path'], $tmpRootInfo['path']); + ?> +
          install->dataRoot;?> + install->exists) : print($lang->install->notExists); + $dataRootInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); + ?> + install->$dataRootResult;?> + install->mkdir, $dataRootInfo['path'], $dataRootInfo['path']); + if(!$dataRootInfo['writable']) printf($lang->install->chmod, $dataRootInfo['path'], $dataRootInfo['path']); + ?> +
          + createLink('install', 'step2'), $lang->install->next); + } + else + { + echo html::a($this->createLink('install', 'step1'), $lang->install->reload); + if($pdoResult == 'fail' or $pdoMySQLResult == 'fail') + { + echo '

          ' . '' . $lang->install->phpINI . '
          ' . nl2br($this->install->getIniInfo()) . '

          '; + } + } + ?> +
          + diff --git a/module/install/view/step2.html.php b/module/install/view/step2.html.php index ebfb6fc806..407fc62121 100644 --- a/module/install/view/step2.html.php +++ b/module/install/view/step2.html.php @@ -1,62 +1,62 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - -
          '> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          install->setConfig;?>
          install->key;?>install->value?>
          install->webRoot;?>
          install->requestType;?>install->requestTypes, 'GET', 'class=select-3');?>
          install->defaultLang;?>langs, $app->getClientLang(), 'class=select-3');?>
          install->dbHost;?>install->dbHostNote;?>
          install->dbPort;?>
          install->dbUser;?>
          install->dbPassword;?>
          install->dbName;?>
          install->dbPrefix;?>install->clearDB);?>
          -
          - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + +
          '> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          install->setConfig;?>
          install->key;?>install->value?>
          install->webRoot;?>
          install->requestType;?>install->requestTypes, 'GET', 'class=select-3');?>
          install->defaultLang;?>langs, $app->getClientLang(), 'class=select-3');?>
          install->dbHost;?>install->dbHostNote;?>
          install->dbPort;?>
          install->dbUser;?>
          install->dbPassword;?>
          install->dbName;?>
          install->dbPrefix;?>install->clearDB);?>
          +
          + diff --git a/module/install/view/step3.html.php b/module/install/view/step3.html.php index bb600a256a..eef82046a7 100644 --- a/module/install/view/step3.html.php +++ b/module/install/view/step3.html.php @@ -1,72 +1,72 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - -installed = true; -\$config->debug = false; -\$config->requestType = '$requestType'; -\$config->db->host = '$dbHost'; -\$config->db->port = '$dbPort'; -\$config->db->name = '$dbName'; -\$config->db->user = '$dbUser'; -\$config->db->password = '$dbPassword'; -\$config->db->prefix = '$dbPrefix'; -\$config->webRoot = '$webRoot'; -\$config->default->domain = '$domain'; -\$config->default->lang = '$defaultLang'; -EOT; -} -?> - - - - - -
          install->error;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          - - - - - - - - - -
          install->saveConfig;?>
          - app->getConfigRoot(); - $myConfigFile = $configRoot . 'my.php'; - if(is_writable($configRoot)) - { - if(@file_put_contents($myConfigFile, $configContent)) - { - printf($lang->install->saved2File, $myConfigFile); - } - else - { - printf($lang->install->save2File, $this->app->getConfigRoot() . 'my.php'); - } - } - else - { - printf($lang->install->save2File, $this->app->getConfigRoot() . 'my.php'); - } - echo "
          "; - echo "
          " . html::a($this->createLink('install', 'step4'), $lang->install->next) . '
          '; - ?> -
          - - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + +installed = true; +\$config->debug = false; +\$config->requestType = '$requestType'; +\$config->db->host = '$dbHost'; +\$config->db->port = '$dbPort'; +\$config->db->name = '$dbName'; +\$config->db->user = '$dbUser'; +\$config->db->password = '$dbPassword'; +\$config->db->prefix = '$dbPrefix'; +\$config->webRoot = '$webRoot'; +\$config->default->domain = '$domain'; +\$config->default->lang = '$defaultLang'; +EOT; +} +?> + + + + + +
          install->error;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          + + + + + + + + + +
          install->saveConfig;?>
          + app->getConfigRoot(); + $myConfigFile = $configRoot . 'my.php'; + if(is_writable($configRoot)) + { + if(@file_put_contents($myConfigFile, $configContent)) + { + printf($lang->install->saved2File, $myConfigFile); + } + else + { + printf($lang->install->save2File, $this->app->getConfigRoot() . 'my.php'); + } + } + else + { + printf($lang->install->save2File, $this->app->getConfigRoot() . 'my.php'); + } + echo "
          "; + echo "
          " . html::a($this->createLink('install', 'step4'), $lang->install->next) . '
          '; + ?> +
          + + diff --git a/module/install/view/step4.html.php b/module/install/view/step4.html.php index 4143461cf2..ed882db51a 100644 --- a/module/install/view/step4.html.php +++ b/module/install/view/step4.html.php @@ -1,52 +1,52 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - - - - - -
          install->error;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          - - - - - -
          install->success;?>
          install->afterSuccess;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          - -
          - - - - - - - - - - - - - - - - - - - - - -
          install->getPriv;?>
          install->company;?>
          install->pms;?>{$lang->install->pmsNote}";?>
          install->account;?>
          install->password;?>
          -
          - - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + + + + + +
          install->error;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          + + + + + +
          install->success;?>
          install->afterSuccess;?>
          install->pre, "onclick='javascript:history.back(-1)'");?>
          + +
          + + + + + + + + + + + + + + + + + + + + + +
          install->getPriv;?>
          install->company;?>
          install->pms;?>{$lang->install->pmsNote}";?>
          install->account;?>
          install->password;?>
          +
          + + diff --git a/module/mail/control.php b/module/mail/control.php index 85581f8775..679764b008 100755 --- a/module/mail/control.php +++ b/module/mail/control.php @@ -1,113 +1,113 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -class mail extends control -{ - /** - * Config email. - * - * @access public - * @return void - */ - public function set() - { - $this->view->mailConfig = $this->app->loadConfig('mail')->mail; - $this->display(); - } - - /** - * Save the email config. - * - * @access public - * @return void - */ - public function save() - { - if(!empty($_POST)) - { - if('gmail' == $this->post->mta) - { - $config = <<mail->turnon = {$this->post->turnon}; -\$config->mail->fromAddress = "{$this->post->fromAddress}"; -\$config->mail->mta = "gmail"; -\$config->mail->fromName = "{$this->post->fromName}"; -\$config->mail->gmail->debug = {$this->post->gmailDebug}; -\$config->mail->gmail->username = "{$this->post->gmailUsername}"; -\$config->mail->gmail->password = "{$this->post->gmailPassword}"; -EOT; - } - elseif('smtp' == $this->post->mta) - { - $position = strpos($this->post->fromAddress, '@'); - if($this->post->smtpHost == '') - { - $host = 'smtp.' . substr($this->post->fromAddress, $position + 1); - } - else - { - $host = $this->post->smtpHost; - } - - $config = <<mail->turnon = {$this->post->turnon}; -\$config->mail->fromAddress = "{$this->post->fromAddress}"; -\$config->mail->mta = "{$this->post->mta}"; -\$config->mail->fromName = "{$this->post->fromName}"; -\$config->mail->smtp->debug = {$this->post->smtpDebug}; -\$config->mail->smtp->username = "{$this->post->smtpUsername}"; -\$config->mail->smtp->password = "{$this->post->smtpPassword}"; -\$config->mail->smtp->auth = {$this->post->smtpAuth}; -\$config->mail->smtp->host = "$host"; -\$config->mail->smtp->secure = "{$this->post->smtpSecure}"; -\$config->mail->smtp->port = "{$this->post->smtpPort}"; -EOT; - } - elseif('phpmail' == $this->post->mta or 'sendmail' == $this->post->mta) - { - $config = <<mail->turnon = {$this->post->turnon}; -\$config->mail->fromAddress = "{$this->post->fromAddress}"; -\$config->mail->mta = "{$this->post->mta}"; -\$config->mail->fromName = "{$this->post->fromName}"; -EOT; - } - - /* Output config to the extconfig file of mail */ - $configPath = $this->app->getModuleExtPath('mail', 'config'); - if(is_writable($configPath)) - { - if(file_put_contents($configPath . 'zzzemail.php', $config)) - { - /* Send test mail */ - $this->mail->send($this->app->user->account, $this->lang->mail->subject, $this->lang->mail->content,"", true); - if($this->mail->isError()) echo js::error($this->mail->getError()); - echo js::confirm($this->lang->mail->confirmSave,$this->createLink('mail', 'set')); - } - else - { - $this->view->config = $config; - $this->view->configPath = $configPath; - $this->display(); - } - } - else - { - $this->view->config = $config; - $this->view->configPath = $configPath; - $this->display(); - } - } - } -} + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +class mail extends control +{ + /** + * Config email. + * + * @access public + * @return void + */ + public function set() + { + $this->view->mailConfig = $this->app->loadConfig('mail')->mail; + $this->display(); + } + + /** + * Save the email config. + * + * @access public + * @return void + */ + public function save() + { + if(!empty($_POST)) + { + if('gmail' == $this->post->mta) + { + $config = <<mail->turnon = {$this->post->turnon}; +\$config->mail->fromAddress = "{$this->post->fromAddress}"; +\$config->mail->mta = "gmail"; +\$config->mail->fromName = "{$this->post->fromName}"; +\$config->mail->gmail->debug = {$this->post->gmailDebug}; +\$config->mail->gmail->username = "{$this->post->gmailUsername}"; +\$config->mail->gmail->password = "{$this->post->gmailPassword}"; +EOT; + } + elseif('smtp' == $this->post->mta) + { + $position = strpos($this->post->fromAddress, '@'); + if($this->post->smtpHost == '') + { + $host = 'smtp.' . substr($this->post->fromAddress, $position + 1); + } + else + { + $host = $this->post->smtpHost; + } + + $config = <<mail->turnon = {$this->post->turnon}; +\$config->mail->fromAddress = "{$this->post->fromAddress}"; +\$config->mail->mta = "{$this->post->mta}"; +\$config->mail->fromName = "{$this->post->fromName}"; +\$config->mail->smtp->debug = {$this->post->smtpDebug}; +\$config->mail->smtp->username = "{$this->post->smtpUsername}"; +\$config->mail->smtp->password = "{$this->post->smtpPassword}"; +\$config->mail->smtp->auth = {$this->post->smtpAuth}; +\$config->mail->smtp->host = "$host"; +\$config->mail->smtp->secure = "{$this->post->smtpSecure}"; +\$config->mail->smtp->port = "{$this->post->smtpPort}"; +EOT; + } + elseif('phpmail' == $this->post->mta or 'sendmail' == $this->post->mta) + { + $config = <<mail->turnon = {$this->post->turnon}; +\$config->mail->fromAddress = "{$this->post->fromAddress}"; +\$config->mail->mta = "{$this->post->mta}"; +\$config->mail->fromName = "{$this->post->fromName}"; +EOT; + } + + /* Output config to the extconfig file of mail */ + $configPath = $this->app->getModuleExtPath('mail', 'config'); + if(is_writable($configPath)) + { + if(file_put_contents($configPath . 'zzzemail.php', $config)) + { + /* Send test mail */ + $this->mail->send($this->app->user->account, $this->lang->mail->subject, $this->lang->mail->content,"", true); + if($this->mail->isError()) echo js::error($this->mail->getError()); + echo js::confirm($this->lang->mail->confirmSave,$this->createLink('mail', 'set')); + } + else + { + $this->view->config = $config; + $this->view->configPath = $configPath; + $this->display(); + } + } + else + { + $this->view->config = $config; + $this->view->configPath = $configPath; + $this->display(); + } + } + } +} diff --git a/module/mail/model.php b/module/mail/model.php index 4e900c6c3b..28f0b197b7 100644 --- a/module/mail/model.php +++ b/module/mail/model.php @@ -1,268 +1,268 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->loadClass('phpmailer', $static = true); - $this->setMTA(); - } - - /** - * Set MTA. - * - * @access public - * @return void - */ - public function setMTA() - { - if(self::$instance == null) self::$instance = new phpmailer(true); - $this->mta = self::$instance; - $this->mta->CharSet = $this->config->encoding; - $funcName = "set{$this->config->mail->mta}"; - if(!method_exists($this, $funcName)) echo $this->app->error("The MTA {$this->config->mail->mta} not supported now.", __FILE__, __LINE__, $exit = false); - $this->$funcName(); - } - - /** - * Set smtp. - * - * @access public - * @return void - */ - public function setSMTP() - { - $this->mta->isSMTP(); - $this->mta->SMTPDebug = $this->config->mail->smtp->debug; - $this->mta->Host = $this->config->mail->smtp->host; - $this->mta->SMTPAuth = $this->config->mail->smtp->auth; - $this->mta->Username = $this->config->mail->smtp->username; - $this->mta->Password = $this->config->mail->smtp->password; - if(isset($this->config->mail->smtp->port)) $this->mta->Port = $this->config->mail->smtp->port; - if(isset($this->config->mail->smtp->secure) and !empty($this->config->mail->smtp->secure))$this->mta->SMTPSecure = strtolower($this->config->mail->smtp->secure); - } - - /** - * PHPmail. - * - * @access public - * @return void - */ - public function setPhpMail() - { - $this->mta->isMail(); - } - - /** - * Sendmail. - * - * @access public - * @return void - */ - public function setSendMail() - { - $this->mta->isSendmail(); - } - - /** - * Gmail. - * - * @access public - * @return void - */ - public function setGMail() - { - $this->mta->isSMTP(); - $this->mta->SMTPDebug = $this->config->mail->gmail->debug; - $this->mta->Host = 'smtp.gmail.com'; - $this->mta->Port = 465; - $this->mta->SMTPSecure = "ssl"; - $this->mta->SMTPAuth = true; - $this->mta->Username = $this->config->mail->gmail->username; - $this->mta->Password = $this->config->mail->gmail->password; - } - - /** - * Send email - * - * @param array $toList - * @param string $subject - * @param string $body - * @param array $ccList - * @param bool $includeMe - * @access public - * @return void - */ - public function send($toList, $subject, $body = '', $ccList = '', $includeMe = false) - { - if(!$this->config->mail->turnon) return; - - /* Process toList and ccList, remove current user from them. If toList is empty, use the first cc as to. */ - if($includeMe == false) - { - $account = isset($this->app->user->account) ? $this->app->user->account : ''; - $toList = $toList ? explode(',', str_replace(' ', '', $toList)) : array(); - $ccList = $ccList ? explode(',', str_replace(' ', '', $ccList)) : array(); - - foreach($toList as $key => $to) if(trim($to) == $account or !trim($to)) unset($toList[$key]); - foreach($ccList as $key => $cc) if(trim($cc) == $account or !trim($cc)) unset($ccList[$key]); - - if(!$toList and !$ccList) return; - if(!$toList and $ccList) $toList = array(array_shift($ccList)); - $toList = join(',', $toList); - $ccList = join(',', $ccList); - } - - /* Get realname and email of users. */ - $this->loadModel('user'); - $emails = $this->user->getRealNameAndEmails(str_replace(' ', '', $toList . ',' . $ccList)); - - $this->clear(); - - try - { - $this->mta->setFrom($this->config->mail->fromAddress, $this->config->mail->fromName); - $this->setSubject($subject); - $this->setTO($toList, $emails); - $this->setCC($ccList, $emails); - $this->setBody($body); - $this->setErrorLang(); - $this->mta->send(); - } - catch (phpmailerException $e) - { - $this->errors[] = trim(strip_tags($e->errorMessage())); - } - catch (Exception $e) - { - $this->errors[] = trim(strip_tags($e->getMessage())); - } - } - - /** - * Set to address - * - * @param array $toList - * @param array $emails - * @access public - * @return void - */ - public function setTO($toList, $emails) - { - $toList = explode(',', str_replace(' ', '', $toList)); - foreach($toList as $account) - { - if(!isset($emails[$account]) or isset($emails[$account]->sended) or strpos($emails[$account]->email, '@') == false) continue; - $this->mta->addAddress($emails[$account]->email, $emails[$account]->realname); - $emails[$account]->sended = true; - } - } - - /** - * Set cc. - * - * @param array $ccList - * @param array $emails - * @access public - * @return void - */ - public function setCC($ccList, $emails) - { - $ccList = explode(',', str_replace(' ', '', $ccList)); - if(!is_array($ccList)) return; - foreach($ccList as $account) - { - if(!isset($emails[$account]) or isset($emails[$account]->sended) or strpos($emails[$account]->email, '@') == false) continue; - $this->mta->addCC($emails[$account]->email, $emails[$account]->realname); - $emails[$account]->sended = true; - } - } - - /** - * Set subject - * - * @param string $subject - * @access public - * @return void - */ - public function setSubject($subject) - { - $this->mta->Subject = stripslashes($subject); - } - - /** - * Set body. - * - * @param string $body - * @access public - * @return void - */ - public function setBody($body) - { - $this->mta->msgHtml("$body"); - } - - /** - * Set error lang. - * - * @access public - * @return void - */ - public function setErrorLang() - { - $this->mta->SetLanguage($this->app->getClientLang()); - } - - /** - * Clear. - * - * @access public - * @return void - */ - public function clear() - { - $this->mta->clearAddresses(); - $this->mta->clearAttachments(); - } - - /** - * Is error? - * - * @access public - * @return bool - */ - public function isError() - { - return !empty($this->errors); - } - - /** - * Get errors. - * - * @access public - * @return void - */ - public function getError() - { - $errors = $this->errors; - $this->errors = array(); - return $errors; - } -} + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +?> +app->loadClass('phpmailer', $static = true); + $this->setMTA(); + } + + /** + * Set MTA. + * + * @access public + * @return void + */ + public function setMTA() + { + if(self::$instance == null) self::$instance = new phpmailer(true); + $this->mta = self::$instance; + $this->mta->CharSet = $this->config->encoding; + $funcName = "set{$this->config->mail->mta}"; + if(!method_exists($this, $funcName)) echo $this->app->error("The MTA {$this->config->mail->mta} not supported now.", __FILE__, __LINE__, $exit = false); + $this->$funcName(); + } + + /** + * Set smtp. + * + * @access public + * @return void + */ + public function setSMTP() + { + $this->mta->isSMTP(); + $this->mta->SMTPDebug = $this->config->mail->smtp->debug; + $this->mta->Host = $this->config->mail->smtp->host; + $this->mta->SMTPAuth = $this->config->mail->smtp->auth; + $this->mta->Username = $this->config->mail->smtp->username; + $this->mta->Password = $this->config->mail->smtp->password; + if(isset($this->config->mail->smtp->port)) $this->mta->Port = $this->config->mail->smtp->port; + if(isset($this->config->mail->smtp->secure) and !empty($this->config->mail->smtp->secure))$this->mta->SMTPSecure = strtolower($this->config->mail->smtp->secure); + } + + /** + * PHPmail. + * + * @access public + * @return void + */ + public function setPhpMail() + { + $this->mta->isMail(); + } + + /** + * Sendmail. + * + * @access public + * @return void + */ + public function setSendMail() + { + $this->mta->isSendmail(); + } + + /** + * Gmail. + * + * @access public + * @return void + */ + public function setGMail() + { + $this->mta->isSMTP(); + $this->mta->SMTPDebug = $this->config->mail->gmail->debug; + $this->mta->Host = 'smtp.gmail.com'; + $this->mta->Port = 465; + $this->mta->SMTPSecure = "ssl"; + $this->mta->SMTPAuth = true; + $this->mta->Username = $this->config->mail->gmail->username; + $this->mta->Password = $this->config->mail->gmail->password; + } + + /** + * Send email + * + * @param array $toList + * @param string $subject + * @param string $body + * @param array $ccList + * @param bool $includeMe + * @access public + * @return void + */ + public function send($toList, $subject, $body = '', $ccList = '', $includeMe = false) + { + if(!$this->config->mail->turnon) return; + + /* Process toList and ccList, remove current user from them. If toList is empty, use the first cc as to. */ + if($includeMe == false) + { + $account = isset($this->app->user->account) ? $this->app->user->account : ''; + $toList = $toList ? explode(',', str_replace(' ', '', $toList)) : array(); + $ccList = $ccList ? explode(',', str_replace(' ', '', $ccList)) : array(); + + foreach($toList as $key => $to) if(trim($to) == $account or !trim($to)) unset($toList[$key]); + foreach($ccList as $key => $cc) if(trim($cc) == $account or !trim($cc)) unset($ccList[$key]); + + if(!$toList and !$ccList) return; + if(!$toList and $ccList) $toList = array(array_shift($ccList)); + $toList = join(',', $toList); + $ccList = join(',', $ccList); + } + + /* Get realname and email of users. */ + $this->loadModel('user'); + $emails = $this->user->getRealNameAndEmails(str_replace(' ', '', $toList . ',' . $ccList)); + + $this->clear(); + + try + { + $this->mta->setFrom($this->config->mail->fromAddress, $this->config->mail->fromName); + $this->setSubject($subject); + $this->setTO($toList, $emails); + $this->setCC($ccList, $emails); + $this->setBody($body); + $this->setErrorLang(); + $this->mta->send(); + } + catch (phpmailerException $e) + { + $this->errors[] = trim(strip_tags($e->errorMessage())); + } + catch (Exception $e) + { + $this->errors[] = trim(strip_tags($e->getMessage())); + } + } + + /** + * Set to address + * + * @param array $toList + * @param array $emails + * @access public + * @return void + */ + public function setTO($toList, $emails) + { + $toList = explode(',', str_replace(' ', '', $toList)); + foreach($toList as $account) + { + if(!isset($emails[$account]) or isset($emails[$account]->sended) or strpos($emails[$account]->email, '@') == false) continue; + $this->mta->addAddress($emails[$account]->email, $emails[$account]->realname); + $emails[$account]->sended = true; + } + } + + /** + * Set cc. + * + * @param array $ccList + * @param array $emails + * @access public + * @return void + */ + public function setCC($ccList, $emails) + { + $ccList = explode(',', str_replace(' ', '', $ccList)); + if(!is_array($ccList)) return; + foreach($ccList as $account) + { + if(!isset($emails[$account]) or isset($emails[$account]->sended) or strpos($emails[$account]->email, '@') == false) continue; + $this->mta->addCC($emails[$account]->email, $emails[$account]->realname); + $emails[$account]->sended = true; + } + } + + /** + * Set subject + * + * @param string $subject + * @access public + * @return void + */ + public function setSubject($subject) + { + $this->mta->Subject = stripslashes($subject); + } + + /** + * Set body. + * + * @param string $body + * @access public + * @return void + */ + public function setBody($body) + { + $this->mta->msgHtml("$body"); + } + + /** + * Set error lang. + * + * @access public + * @return void + */ + public function setErrorLang() + { + $this->mta->SetLanguage($this->app->getClientLang()); + } + + /** + * Clear. + * + * @access public + * @return void + */ + public function clear() + { + $this->mta->clearAddresses(); + $this->mta->clearAttachments(); + } + + /** + * Is error? + * + * @access public + * @return bool + */ + public function isError() + { + return !empty($this->errors); + } + + /** + * Get errors. + * + * @access public + * @return void + */ + public function getError() + { + $errors = $this->errors; + $this->errors = array(); + return $errors; + } +} diff --git a/module/mail/view/save.html.php b/module/mail/view/save.html.php index e853ef0932..5098fe3fc8 100755 --- a/module/mail/view/save.html.php +++ b/module/mail/view/save.html.php @@ -1,25 +1,25 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -include '../../common/view/header.html.php'; -?> - - - - - - - - - - -
          mail->configInfo ?>
          -
          mail->saveConfig . $configPath . 'zzzemail.php' ?>
          mail->createFile ?>
          + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +?> + + + + + + + + + + +
          mail->configInfo ?>
          +
          mail->saveConfig . $configPath . 'zzzemail.php' ?>
          mail->createFile ?>
          diff --git a/module/mail/view/set.html.php b/module/mail/view/set.html.php index 9aff4a868a..3484fccc2b 100755 --- a/module/mail/view/set.html.php +++ b/module/mail/view/set.html.php @@ -1,110 +1,110 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -include '../../common/view/header.html.php'; -include '../../common/view/tablesorter.html.php';?> -turnon == 1) $turnon = 'ture'; -if(!empty($mailConfig->mta)) $mta = $mailConfig->mta; -if(!empty($mailConfig->gmail->username)) $gmailUsername = $mailConfig->gmail->username; -if(!empty($mailConfig->gmail->password)) $gmailPassword = $mailConfig->gmail->password; -if(!empty($mailConfig->smtp->username)) $smtpUsername = $mailConfig->smtp->username; -if(!empty($mailConfig->smtp->password)) $smtpPassword = $mailConfig->smtp->password; -if(!empty($mailConfig->smtp->host)) $smtpHost = $mailConfig->smtp->host; -if(!empty($mailConfig->smtp->secure)) $smtpSecure = $mailConfig->smtp->secure; -if(!empty($mailConfig->smtp->auth)) $smtpAuth = $mailConfig->smtp->auth; -if(!empty($mailConfig->smtp->port)) $smtpPort = $mailConfig->smtp->port; -?> -
          '> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          mail->setParam; ?>
          mail->turnon; ?>mail->turnonList, $turnon, 'class=select-3'); ?>
          mail->mta; ?>mail->mtaList, $mta, 'class=select-3 onchange=setMtaType(this.value)'); ?>
          mail->fromAddress; ?>fromAddress, 'class=text-3') ?>
          mail->fromName; ?>fromName, 'class=text-3') ?>
          -
          - + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +include '../../common/view/tablesorter.html.php';?> +turnon == 1) $turnon = 'ture'; +if(!empty($mailConfig->mta)) $mta = $mailConfig->mta; +if(!empty($mailConfig->gmail->username)) $gmailUsername = $mailConfig->gmail->username; +if(!empty($mailConfig->gmail->password)) $gmailPassword = $mailConfig->gmail->password; +if(!empty($mailConfig->smtp->username)) $smtpUsername = $mailConfig->smtp->username; +if(!empty($mailConfig->smtp->password)) $smtpPassword = $mailConfig->smtp->password; +if(!empty($mailConfig->smtp->host)) $smtpHost = $mailConfig->smtp->host; +if(!empty($mailConfig->smtp->secure)) $smtpSecure = $mailConfig->smtp->secure; +if(!empty($mailConfig->smtp->auth)) $smtpAuth = $mailConfig->smtp->auth; +if(!empty($mailConfig->smtp->port)) $smtpPort = $mailConfig->smtp->port; +?> +
          '> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          mail->setParam; ?>
          mail->turnon; ?>mail->turnonList, $turnon, 'class=select-3'); ?>
          mail->mta; ?>mail->mtaList, $mta, 'class=select-3 onchange=setMtaType(this.value)'); ?>
          mail->fromAddress; ?>fromAddress, 'class=text-3') ?>
          mail->fromName; ?>fromName, 'class=text-3') ?>
          +
          + diff --git a/module/misc/control.php b/module/misc/control.php index 1bfc05add8..aa7b549189 100644 --- a/module/misc/control.php +++ b/module/misc/control.php @@ -1,58 +1,58 @@ - - * @package misc - * @version $Id$ - * @link http://www.zentao.net - */ -class misc extends control -{ - /** - * Ping the server every 5 minutes to keep the session. - * - * @access public - * @return void - */ - public function ping() - { - if(mt_rand(0, 10) == 5) $this->loadModel('setting')->setSN(); - die(""); - } - - /** - * Show php info. - * - * @access public - * @return void - */ - public function phpinfo() - { - die(phpinfo()); - } - - /** - * Show about info of zentao. - * - * @access public - * @return void - */ - public function about() - { - die($this->display()); - } - - /** - * Update nl. - * - * @access public - * @return void - */ - public function updateNL() - { - $this->loadModel('upgrade')->updateNL(); - } -} + + * @package misc + * @version $Id$ + * @link http://www.zentao.net + */ +class misc extends control +{ + /** + * Ping the server every 5 minutes to keep the session. + * + * @access public + * @return void + */ + public function ping() + { + if(mt_rand(0, 10) == 5) $this->loadModel('setting')->setSN(); + die(""); + } + + /** + * Show php info. + * + * @access public + * @return void + */ + public function phpinfo() + { + die(phpinfo()); + } + + /** + * Show about info of zentao. + * + * @access public + * @return void + */ + public function about() + { + die($this->display()); + } + + /** + * Update nl. + * + * @access public + * @return void + */ + public function updateNL() + { + $this->loadModel('upgrade')->updateNL(); + } +} diff --git a/module/misc/lang/en.php b/module/misc/lang/en.php index 46c31a4f86..f820787987 100644 --- a/module/misc/lang/en.php +++ b/module/misc/lang/en.php @@ -1,58 +1,58 @@ - - * @package misc - * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -$lang->misc->common = 'Misc'; -$lang->misc->ping = 'Keep session'; - -$lang->misc->zentao->version = 'Version %s'; -$lang->misc->zentao->labels['about'] = 'About'; -$lang->misc->zentao->labels['support'] = 'Support'; -$lang->misc->zentao->labels['cowin'] = 'Help us'; -$lang->misc->zentao->labels['service'] = 'Services'; - -$lang->misc->zentao->about['official'] = "Official site"; -$lang->misc->zentao->about['project'] = "Project"; -$lang->misc->zentao->about['preview'] = "Demo"; -$lang->misc->zentao->about['changelog'] = "Change log"; -$lang->misc->zentao->about['license'] = "License"; -$lang->misc->zentao->about['contributors'] = "Contributors"; -$lang->misc->zentao->about['thirdparty'] = "Thirdparty"; -$lang->misc->zentao->about['sourcecode'] = "Source code"; -$lang->misc->zentao->about['extension'] = "Extensions"; - -$lang->misc->zentao->support['manual'] = "Manual"; -$lang->misc->zentao->support['faq'] = "FAQ"; -$lang->misc->zentao->support['forum'] = "Forum"; -$lang->misc->zentao->support['qqgroup'] = "QQ Grup"; -$lang->misc->zentao->support['howask'] = "How to ask"; -$lang->misc->zentao->support['vip'] = "Business"; - -$lang->misc->zentao->cowin['reportbug'] = "Report bug"; -$lang->misc->zentao->cowin['feedback'] = "Feedback feature"; -$lang->misc->zentao->cowin['devcode'] = "Commit code"; -$lang->misc->zentao->cowin['doc'] = "Write doc"; -$lang->misc->zentao->cowin['recommend'] = "Recommend"; -$lang->misc->zentao->cowin['addlink'] = "Add link"; -$lang->misc->zentao->cowin['shop'] = "Shop"; -$lang->misc->zentao->cowin['donate'] = "Donate"; -$lang->misc->zentao->cowin['cowinmore'] = "More..."; - -$lang->misc->zentao->service['install'] = 'Install service'; -$lang->misc->zentao->service['fixissue'] = 'Issue support'; -$lang->misc->zentao->service['zentaotrain']= 'ZenTao training'; -$lang->misc->zentao->service['idc'] = 'ZenTao online'; -$lang->misc->zentao->service['custom'] = 'custom develop'; -$lang->misc->zentao->service['review'] = 'ZenTao review'; -$lang->misc->zentao->service['scrumtrain'] = 'Scrum training'; -$lang->misc->zentao->service['fwtrain'] = 'ZenTaoPHP training'; -$lang->misc->zentao->service['servicemore']= 'More...'; - -$lang->misc->copyright = "Copyright ©2009-2011 Nature EasySoft Network Tecnology Co.ltd, QingDao, China"; + + * @package misc + * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $ + * @link http://www.zentao.net + */ +$lang->misc->common = 'Misc'; +$lang->misc->ping = 'Keep session'; + +$lang->misc->zentao->version = 'Version %s'; +$lang->misc->zentao->labels['about'] = 'About'; +$lang->misc->zentao->labels['support'] = 'Support'; +$lang->misc->zentao->labels['cowin'] = 'Help us'; +$lang->misc->zentao->labels['service'] = 'Services'; + +$lang->misc->zentao->about['official'] = "Official site"; +$lang->misc->zentao->about['project'] = "Project"; +$lang->misc->zentao->about['preview'] = "Demo"; +$lang->misc->zentao->about['changelog'] = "Change log"; +$lang->misc->zentao->about['license'] = "License"; +$lang->misc->zentao->about['contributors'] = "Contributors"; +$lang->misc->zentao->about['thirdparty'] = "Thirdparty"; +$lang->misc->zentao->about['sourcecode'] = "Source code"; +$lang->misc->zentao->about['extension'] = "Extensions"; + +$lang->misc->zentao->support['manual'] = "Manual"; +$lang->misc->zentao->support['faq'] = "FAQ"; +$lang->misc->zentao->support['forum'] = "Forum"; +$lang->misc->zentao->support['qqgroup'] = "QQ Grup"; +$lang->misc->zentao->support['howask'] = "How to ask"; +$lang->misc->zentao->support['vip'] = "Business"; + +$lang->misc->zentao->cowin['reportbug'] = "Report bug"; +$lang->misc->zentao->cowin['feedback'] = "Feedback feature"; +$lang->misc->zentao->cowin['devcode'] = "Commit code"; +$lang->misc->zentao->cowin['doc'] = "Write doc"; +$lang->misc->zentao->cowin['recommend'] = "Recommend"; +$lang->misc->zentao->cowin['addlink'] = "Add link"; +$lang->misc->zentao->cowin['shop'] = "Shop"; +$lang->misc->zentao->cowin['donate'] = "Donate"; +$lang->misc->zentao->cowin['cowinmore'] = "More..."; + +$lang->misc->zentao->service['install'] = 'Install service'; +$lang->misc->zentao->service['fixissue'] = 'Issue support'; +$lang->misc->zentao->service['zentaotrain']= 'ZenTao training'; +$lang->misc->zentao->service['idc'] = 'ZenTao online'; +$lang->misc->zentao->service['custom'] = 'custom develop'; +$lang->misc->zentao->service['review'] = 'ZenTao review'; +$lang->misc->zentao->service['scrumtrain'] = 'Scrum training'; +$lang->misc->zentao->service['fwtrain'] = 'ZenTaoPHP training'; +$lang->misc->zentao->service['servicemore']= 'More...'; + +$lang->misc->copyright = "Copyright ©2009-2012 Nature EasySoft Network Tecnology Co.ltd, QingDao, China"; diff --git a/module/misc/lang/zh-cn.php b/module/misc/lang/zh-cn.php index f9733f4e74..3f9f785e8a 100644 --- a/module/misc/lang/zh-cn.php +++ b/module/misc/lang/zh-cn.php @@ -1,58 +1,58 @@ - - * @package misc - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->misc->common = '杂项'; -$lang->misc->ping = '防超时'; - -$lang->misc->zentao->version = '版本%s'; -$lang->misc->zentao->labels['about'] = '关于禅道'; -$lang->misc->zentao->labels['support'] = '技术支持'; -$lang->misc->zentao->labels['cowin'] = '帮助我们'; -$lang->misc->zentao->labels['service'] = '服务列表'; - -$lang->misc->zentao->about['official'] = "官方网站"; -$lang->misc->zentao->about['project'] = "项目进展"; -$lang->misc->zentao->about['preview'] = "最新预览"; -$lang->misc->zentao->about['changelog'] = "版本历史"; -$lang->misc->zentao->about['license'] = "授权协议"; -$lang->misc->zentao->about['contributors'] = "贡献者"; -$lang->misc->zentao->about['thirdparty'] = "第三方代码"; -$lang->misc->zentao->about['sourcecode'] = "源代码"; -$lang->misc->zentao->about['extension'] = "插件平台"; - -$lang->misc->zentao->support['manual'] = "用户手册"; -$lang->misc->zentao->support['faq'] = "常见问题"; -$lang->misc->zentao->support['forum'] = "支持论坛"; -$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; -$lang->misc->zentao->support['howask'] = "如何提问"; -$lang->misc->zentao->support['vip'] = "商业支持"; - -$lang->misc->zentao->cowin['reportbug'] = "汇报Bug"; -$lang->misc->zentao->cowin['feedback'] = "反馈需求"; -$lang->misc->zentao->cowin['devcode'] = "提交代码"; -$lang->misc->zentao->cowin['doc'] = "完善文档"; -$lang->misc->zentao->cowin['recommend'] = "推荐给朋友"; -$lang->misc->zentao->cowin['addlink'] = "添加友情链接"; -$lang->misc->zentao->cowin['shop'] = "逛逛我们的商店"; -$lang->misc->zentao->cowin['donate'] = "捐助我们"; -$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; - -$lang->misc->zentao->service['install'] = '禅道安装服务'; -$lang->misc->zentao->service['fixissue'] = '禅道问题解决'; -$lang->misc->zentao->service['zentaotrain']= '禅道使用培训'; -$lang->misc->zentao->service['idc'] = '禅道在线托管'; -$lang->misc->zentao->service['custom'] = '禅道定制开发'; -$lang->misc->zentao->service['review'] = '禅道点评服务'; -$lang->misc->zentao->service['scrumtrain'] = 'scrum培训'; -$lang->misc->zentao->service['fwtrain'] = '禅道PHP框架培训'; -$lang->misc->zentao->service['servicemore']= '更多服务...'; - -$lang->misc->copyright = "版权所有 ©2009-2011 青岛易软天创网络科技有限公司"; + + * @package misc + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->misc->common = '杂项'; +$lang->misc->ping = '防超时'; + +$lang->misc->zentao->version = '版本%s'; +$lang->misc->zentao->labels['about'] = '关于禅道'; +$lang->misc->zentao->labels['support'] = '技术支持'; +$lang->misc->zentao->labels['cowin'] = '帮助我们'; +$lang->misc->zentao->labels['service'] = '服务列表'; + +$lang->misc->zentao->about['official'] = "官方网站"; +$lang->misc->zentao->about['project'] = "项目进展"; +$lang->misc->zentao->about['preview'] = "最新预览"; +$lang->misc->zentao->about['changelog'] = "版本历史"; +$lang->misc->zentao->about['license'] = "授权协议"; +$lang->misc->zentao->about['contributors'] = "贡献者"; +$lang->misc->zentao->about['thirdparty'] = "第三方代码"; +$lang->misc->zentao->about['sourcecode'] = "源代码"; +$lang->misc->zentao->about['extension'] = "插件平台"; + +$lang->misc->zentao->support['manual'] = "用户手册"; +$lang->misc->zentao->support['faq'] = "常见问题"; +$lang->misc->zentao->support['forum'] = "支持论坛"; +$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; +$lang->misc->zentao->support['howask'] = "如何提问"; +$lang->misc->zentao->support['vip'] = "商业支持"; + +$lang->misc->zentao->cowin['reportbug'] = "汇报Bug"; +$lang->misc->zentao->cowin['feedback'] = "反馈需求"; +$lang->misc->zentao->cowin['devcode'] = "提交代码"; +$lang->misc->zentao->cowin['doc'] = "完善文档"; +$lang->misc->zentao->cowin['recommend'] = "推荐给朋友"; +$lang->misc->zentao->cowin['addlink'] = "添加友情链接"; +$lang->misc->zentao->cowin['shop'] = "逛逛我们的商店"; +$lang->misc->zentao->cowin['donate'] = "捐助我们"; +$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; + +$lang->misc->zentao->service['install'] = '禅道安装服务'; +$lang->misc->zentao->service['fixissue'] = '禅道问题解决'; +$lang->misc->zentao->service['zentaotrain']= '禅道使用培训'; +$lang->misc->zentao->service['idc'] = '禅道在线托管'; +$lang->misc->zentao->service['custom'] = '禅道定制开发'; +$lang->misc->zentao->service['review'] = '禅道点评服务'; +$lang->misc->zentao->service['scrumtrain'] = 'scrum培训'; +$lang->misc->zentao->service['fwtrain'] = '禅道PHP框架培训'; +$lang->misc->zentao->service['servicemore']= '更多服务...'; + +$lang->misc->copyright = "版权所有 ©2009-2012 青岛易软天创网络科技有限公司"; diff --git a/module/misc/lang/zh-tw.php b/module/misc/lang/zh-tw.php index d78627e6e8..cb0e525192 100644 --- a/module/misc/lang/zh-tw.php +++ b/module/misc/lang/zh-tw.php @@ -1,58 +1,58 @@ - - * @package misc - * @version $Id: zh-tw.php 2500 2012-01-02 02:54:23Z wwccss $ - * @link http://www.zentao.net - */ -$lang->misc->common = '雜項'; -$lang->misc->ping = '防超時'; - -$lang->misc->zentao->version = '版本%s'; -$lang->misc->zentao->labels['about'] = '關於禪道'; -$lang->misc->zentao->labels['support'] = '技術支持'; -$lang->misc->zentao->labels['cowin'] = '幫助我們'; -$lang->misc->zentao->labels['service'] = '服務列表'; - -$lang->misc->zentao->about['official'] = "官方網站"; -$lang->misc->zentao->about['project'] = "項目進展"; -$lang->misc->zentao->about['preview'] = "最新預覽"; -$lang->misc->zentao->about['changelog'] = "版本歷史"; -$lang->misc->zentao->about['license'] = "授權協議"; -$lang->misc->zentao->about['contributors'] = "貢獻者"; -$lang->misc->zentao->about['thirdparty'] = "第三方代碼"; -$lang->misc->zentao->about['sourcecode'] = "原始碼"; -$lang->misc->zentao->about['extension'] = "插件平台"; - -$lang->misc->zentao->support['manual'] = "用戶手冊"; -$lang->misc->zentao->support['faq'] = "常見問題"; -$lang->misc->zentao->support['forum'] = "支持論壇"; -$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; -$lang->misc->zentao->support['howask'] = "如何提問"; -$lang->misc->zentao->support['vip'] = "商業支持"; - -$lang->misc->zentao->cowin['reportbug'] = "彙報Bug"; -$lang->misc->zentao->cowin['feedback'] = "反饋需求"; -$lang->misc->zentao->cowin['devcode'] = "提交代碼"; -$lang->misc->zentao->cowin['doc'] = "完善文檔"; -$lang->misc->zentao->cowin['recommend'] = "推薦給朋友"; -$lang->misc->zentao->cowin['addlink'] = "添加友情連結"; -$lang->misc->zentao->cowin['shop'] = "逛逛我們的商店"; -$lang->misc->zentao->cowin['donate'] = "捐助我們"; -$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; - -$lang->misc->zentao->service['install'] = '禪道安裝服務'; -$lang->misc->zentao->service['fixissue'] = '禪道問題解決'; -$lang->misc->zentao->service['zentaotrain']= '禪道使用培訓'; -$lang->misc->zentao->service['idc'] = '禪道在綫託管'; -$lang->misc->zentao->service['custom'] = '禪道定製開發'; -$lang->misc->zentao->service['review'] = '禪道點評服務'; -$lang->misc->zentao->service['scrumtrain'] = 'scrum培訓'; -$lang->misc->zentao->service['fwtrain'] = '禪道PHP框架培訓'; -$lang->misc->zentao->service['servicemore']= '更多服務...'; - -$lang->misc->copyright = "版權所有 ©2009-2011 青島易軟天創網絡科技有限公司"; + + * @package misc + * @version $Id: zh-tw.php 2500 2012-01-02 02:54:23Z wwccss $ + * @link http://www.zentao.net + */ +$lang->misc->common = '雜項'; +$lang->misc->ping = '防超時'; + +$lang->misc->zentao->version = '版本%s'; +$lang->misc->zentao->labels['about'] = '關於禪道'; +$lang->misc->zentao->labels['support'] = '技術支持'; +$lang->misc->zentao->labels['cowin'] = '幫助我們'; +$lang->misc->zentao->labels['service'] = '服務列表'; + +$lang->misc->zentao->about['official'] = "官方網站"; +$lang->misc->zentao->about['project'] = "項目進展"; +$lang->misc->zentao->about['preview'] = "最新預覽"; +$lang->misc->zentao->about['changelog'] = "版本歷史"; +$lang->misc->zentao->about['license'] = "授權協議"; +$lang->misc->zentao->about['contributors'] = "貢獻者"; +$lang->misc->zentao->about['thirdparty'] = "第三方代碼"; +$lang->misc->zentao->about['sourcecode'] = "原始碼"; +$lang->misc->zentao->about['extension'] = "插件平台"; + +$lang->misc->zentao->support['manual'] = "用戶手冊"; +$lang->misc->zentao->support['faq'] = "常見問題"; +$lang->misc->zentao->support['forum'] = "支持論壇"; +$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; +$lang->misc->zentao->support['howask'] = "如何提問"; +$lang->misc->zentao->support['vip'] = "商業支持"; + +$lang->misc->zentao->cowin['reportbug'] = "彙報Bug"; +$lang->misc->zentao->cowin['feedback'] = "反饋需求"; +$lang->misc->zentao->cowin['devcode'] = "提交代碼"; +$lang->misc->zentao->cowin['doc'] = "完善文檔"; +$lang->misc->zentao->cowin['recommend'] = "推薦給朋友"; +$lang->misc->zentao->cowin['addlink'] = "添加友情連結"; +$lang->misc->zentao->cowin['shop'] = "逛逛我們的商店"; +$lang->misc->zentao->cowin['donate'] = "捐助我們"; +$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; + +$lang->misc->zentao->service['install'] = '禪道安裝服務'; +$lang->misc->zentao->service['fixissue'] = '禪道問題解決'; +$lang->misc->zentao->service['zentaotrain']= '禪道使用培訓'; +$lang->misc->zentao->service['idc'] = '禪道在綫託管'; +$lang->misc->zentao->service['custom'] = '禪道定製開發'; +$lang->misc->zentao->service['review'] = '禪道點評服務'; +$lang->misc->zentao->service['scrumtrain'] = 'scrum培訓'; +$lang->misc->zentao->service['fwtrain'] = '禪道PHP框架培訓'; +$lang->misc->zentao->service['servicemore']= '更多服務...'; + +$lang->misc->copyright = "版權所有 ©2009-2012 青島易軟天創網絡科技有限公司"; diff --git a/module/misc/model.php b/module/misc/model.php index d171fe48bc..032fc8e819 100644 --- a/module/misc/model.php +++ b/module/misc/model.php @@ -1,16 +1,16 @@ - - * @package misc - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + * @package misc + * @version $Id$ + * @link http://www.zentao.net + */ +?> + - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -class my extends control -{ - /** - * Construct function. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('user'); - $this->loadModel('dept'); - $this->my->setMenu(); - } - - /** - * Index page, goto todo. - * - * @access public - * @return void - */ - public function index() - { - $account = $this->app->user->account; - - /* Get project and product stats. */ - $projectStats = $this->loadModel('project')->getProjectStats(); - $productStats = $this->loadModel('product')->getStats(); - - /* Set the dynamic pager. */ - $this->app->loadClass('pager', true); - $pager = new pager(0, $this->config->my->dynamicCounts); - - $this->view->projectStats = $projectStats; - $this->view->productStats = $productStats; - $this->view->actions = $this->loadModel('action')->getDynamic('all', 'all', 'date_desc', $pager); - $this->view->todos = $this->loadModel('todo')->getList('all', $account, 'wait, doing', $this->config->my->todoCounts); - $this->view->tasks = $this->loadModel('task')->getUserTasks($account, 'assignedTo', $this->config->my->taskCounts); - $this->view->bugs = $this->loadModel('bug')->getUserBugPairs($account, false, $this->config->my->bugCounts); - $this->view->users = $this->loadModel('user')->getPairs('noletter|withguest'); - $this->view->header->title = $this->lang->my->common; - - $this->display(); - } - - /** - * My todos. - * - * @param string $type - * @param string $account - * @param string $status - * @access public - * @return void - */ - public function todo($type = 'today', $account = '', $status = 'all') - { - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('todoList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('taskList', $uri); - - /* The header and position. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->todo; - $this->view->position[] = $this->lang->my->todo; - - /* Assign. */ - $this->view->dates = $this->loadModel('todo')->buildDateList(); - $this->view->todos = $this->todo->getList($type, $account, $status); - $this->view->date = (int)$type == 0 ? $this->todo->today() : $type; - $this->view->type = $type; - $this->view->account = $this->app->user->account; - $this->view->importFuture = ($type == 'before' or $type == TODOMODEL::DAY_IN_FUTURE); - - $this->display(); - } - - /** - * My stories. - * - * @access public - * @return void - */ - public function story($type = 'assignedto') - { - /* Save session. */ - $this->session->set('storyList', $this->app->getURI(true)); - - /* Assign. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->story; - $this->view->position[] = $this->lang->my->story; - $this->view->stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->type = $type; - - $this->display(); - } - - /** - * My tasks. - * - * @param string $type the browse type - * @access public - * @return void - */ - public function task($type = 'assignedto') - { - /* Save session. */ - $this->session->set('taskList', $this->app->getURI(true)); - $this->session->set('storyList', $this->app->getURI(true)); - - /* Assign. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->task; - $this->view->position[] = $this->lang->my->task; - $this->view->tabID = 'task'; - $this->view->tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $type); - $this->view->type = $type; - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * My bugs. - * - * @param string $type - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function bug($type = 'assigntome', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. load Lang. */ - $this->session->set('bugList', $this->app->getURI(true)); - $this->app->loadLang('bug'); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - $bugs = array(); - if($type == 'assigntome') - { - $bugs = $this->dao->select('t1.*') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t2.deleted')->eq(0) - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t1.assignedTo')->eq($this->app->user->account) - ->orderBy('t1.id_desc')->page($pager)->fetchAll(); - } - elseif($type == 'openedbyme') - { - $bugs = $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - elseif($type == 'resolvedbyme') - { - $bugs = $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - elseif($type == 'closedbyme') - { - $bugs = $this->dao->findByClosedBy($this->app->user->account)->from(TABLE_BUG) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /* assign. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->bug; - $this->view->position[] = $this->lang->my->bug; - $this->view->bugs = $bugs; - $this->view->users = $this->user->getPairs('noletter'); - $this->view->tabID = 'bug'; - $this->view->type = $type; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * My test task. - * - * @access public - * @return void - */ - public function testtask() - { - /* Save session. */ - $this->session->set('testtaskList', $this->app->getURI(true)); - - $this->app->loadLang('testcase'); - - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->testTask; - $this->view->position[] = $this->lang->my->testTask; - $this->view->tasks = $this->loadModel('testtask')->getByUser($this->app->user->account); - - $this->display(); - - } - - /** - * My test case. - * - * @param string $type - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function testcase($type = 'assigntome', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session, load lang. */ - $this->session->set('caseList', $this->app->getURI(true)); - $this->app->loadLang('testcase'); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - $cases = array(); - if($type == 'assigntome') - { - $cases = $this->dao->select('t1.assignedTo AS assignedTo, t2.*')->from(TABLE_TESTRUN)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') - ->leftJoin(TABLE_TESTTASK)->alias('t3')->on('t1.task = t3.id') - ->Where('t1.assignedTo')->eq($this->app->user->account) - ->andWhere('t1.status')->ne('done') - ->andWhere('t3.status')->ne('done') - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - elseif($type == 'donebyme') - { - $cases = $this->dao->select('t1.assignedTo AS assignedTo, t2.*')->from(TABLE_TESTRUN)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') - ->Where('t1.assignedTo')->eq($this->app->user->account) - ->andWhere('t1.status')->eq('done') - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - elseif($type == 'openedbyme') - { - $cases = $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_CASE) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /* Assign. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->testCase; - $this->view->position[] = $this->lang->my->testCase; - $this->view->cases = $cases; - $this->view->users = $this->user->getPairs('noletter'); - $this->view->tabID = 'test'; - $this->view->type = $type; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * My projects. - * - * @access public - * @return void - */ - public function project() - { - $this->app->loadLang('project'); - - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->myProject; - $this->view->position[] = $this->lang->my->myProject; - $this->view->tabID = 'project'; - $this->view->projects = @array_reverse($this->user->getProjects($this->app->user->account)); - - $this->display(); - } - - /** - * Edit profile - * - * @access public - * @return void - */ - public function editProfile() - { - if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); - if(!empty($_POST)) - { - $this->user->update($this->app->user->id); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('my', 'profile'), 'parent')); - } - - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->editProfile; - $this->view->position[] = $this->lang->my->editProfile; - $this->view->user = $this->user->getById($this->app->user->id); - - $this->display(); - } - - /** - * View my profile. - * - * @access public - * @return void - */ - public function profile() - { - if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); - $user = $this->user->getById($this->app->user->account); - $deptPath = $this->dept->getParents($user->dept); - $this->view->deptPath = $deptPath; - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->profile; - $this->view->position[] = $this->lang->my->profile; - $this->view->user = $this->user->getById($this->app->user->id); - $this->display(); - } - - /** - * My dynamic. - * - * @param string $type - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function dynamic($type = 'today', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('productList', $uri); - $this->session->set('productPlanList', $uri); - $this->session->set('releaseList', $uri); - $this->session->set('storyList', $uri); - $this->session->set('projectList', $uri); - $this->session->set('taskList', $uri); - $this->session->set('buildList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('caseList', $uri); - $this->session->set('testtaskList', $uri); - - /* Set the pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - /* The header and position. */ - $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->dynamic; - $this->view->position[] = $this->lang->my->dynamic; - - /* Assign. */ - $this->view->type = $type; - $this->view->actions = $this->loadModel('action')->getDynamic($this->app->user->account, $type, $orderBy, $pager); - $this->display(); - } - -} + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +class my extends control +{ + /** + * Construct function. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('user'); + $this->loadModel('dept'); + $this->my->setMenu(); + } + + /** + * Index page, goto todo. + * + * @access public + * @return void + */ + public function index() + { + $account = $this->app->user->account; + + /* Get project and product stats. */ + $projectStats = $this->loadModel('project')->getProjectStats(); + $productStats = $this->loadModel('product')->getStats(); + + /* Set the dynamic pager. */ + $this->app->loadClass('pager', true); + $pager = new pager(0, $this->config->my->dynamicCounts); + + $this->view->projectStats = $projectStats; + $this->view->productStats = $productStats; + $this->view->actions = $this->loadModel('action')->getDynamic('all', 'all', 'date_desc', $pager); + $this->view->todos = $this->loadModel('todo')->getList('all', $account, 'wait, doing', $this->config->my->todoCounts); + $this->view->tasks = $this->loadModel('task')->getUserTasks($account, 'assignedTo', $this->config->my->taskCounts); + $this->view->bugs = $this->loadModel('bug')->getUserBugPairs($account, false, $this->config->my->bugCounts); + $this->view->users = $this->loadModel('user')->getPairs('noletter|withguest'); + $this->view->header->title = $this->lang->my->common; + + $this->display(); + } + + /** + * My todos. + * + * @param string $type + * @param string $account + * @param string $status + * @access public + * @return void + */ + public function todo($type = 'today', $account = '', $status = 'all') + { + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('todoList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('taskList', $uri); + + /* The header and position. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->todo; + $this->view->position[] = $this->lang->my->todo; + + /* Assign. */ + $this->view->dates = $this->loadModel('todo')->buildDateList(); + $this->view->todos = $this->todo->getList($type, $account, $status); + $this->view->date = (int)$type == 0 ? $this->todo->today() : $type; + $this->view->type = $type; + $this->view->account = $this->app->user->account; + $this->view->importFuture = ($type == 'before' or $type == TODOMODEL::DAY_IN_FUTURE); + + $this->display(); + } + + /** + * My stories. + * + * @access public + * @return void + */ + public function story($type = 'assignedto') + { + /* Save session. */ + $this->session->set('storyList', $this->app->getURI(true)); + + /* Assign. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->story; + $this->view->position[] = $this->lang->my->story; + $this->view->stories = $this->loadModel('story')->getUserStories($this->app->user->account, $type); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->type = $type; + + $this->display(); + } + + /** + * My tasks. + * + * @param string $type the browse type + * @access public + * @return void + */ + public function task($type = 'assignedto') + { + /* Save session. */ + $this->session->set('taskList', $this->app->getURI(true)); + $this->session->set('storyList', $this->app->getURI(true)); + + /* Assign. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->task; + $this->view->position[] = $this->lang->my->task; + $this->view->tabID = 'task'; + $this->view->tasks = $this->loadModel('task')->getUserTasks($this->app->user->account, $type); + $this->view->type = $type; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * My bugs. + * + * @param string $type + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function bug($type = 'assigntome', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. load Lang. */ + $this->session->set('bugList', $this->app->getURI(true)); + $this->app->loadLang('bug'); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + $bugs = array(); + if($type == 'assigntome') + { + $bugs = $this->dao->select('t1.*') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t2.deleted')->eq(0) + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t1.assignedTo')->eq($this->app->user->account) + ->orderBy('t1.id_desc')->page($pager)->fetchAll(); + } + elseif($type == 'openedbyme') + { + $bugs = $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + elseif($type == 'resolvedbyme') + { + $bugs = $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + elseif($type == 'closedbyme') + { + $bugs = $this->dao->findByClosedBy($this->app->user->account)->from(TABLE_BUG) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /* assign. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->bug; + $this->view->position[] = $this->lang->my->bug; + $this->view->bugs = $bugs; + $this->view->users = $this->user->getPairs('noletter'); + $this->view->tabID = 'bug'; + $this->view->type = $type; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * My test task. + * + * @access public + * @return void + */ + public function testtask() + { + /* Save session. */ + $this->session->set('testtaskList', $this->app->getURI(true)); + + $this->app->loadLang('testcase'); + + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->testTask; + $this->view->position[] = $this->lang->my->testTask; + $this->view->tasks = $this->loadModel('testtask')->getByUser($this->app->user->account); + + $this->display(); + + } + + /** + * My test case. + * + * @param string $type + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function testcase($type = 'assigntome', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session, load lang. */ + $this->session->set('caseList', $this->app->getURI(true)); + $this->app->loadLang('testcase'); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + $cases = array(); + if($type == 'assigntome') + { + $cases = $this->dao->select('t1.assignedTo AS assignedTo, t2.*')->from(TABLE_TESTRUN)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->leftJoin(TABLE_TESTTASK)->alias('t3')->on('t1.task = t3.id') + ->Where('t1.assignedTo')->eq($this->app->user->account) + ->andWhere('t1.status')->ne('done') + ->andWhere('t3.status')->ne('done') + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + elseif($type == 'donebyme') + { + $cases = $this->dao->select('t1.assignedTo AS assignedTo, t2.*')->from(TABLE_TESTRUN)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->Where('t1.assignedTo')->eq($this->app->user->account) + ->andWhere('t1.status')->eq('done') + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + elseif($type == 'openedbyme') + { + $cases = $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_CASE) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /* Assign. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->testCase; + $this->view->position[] = $this->lang->my->testCase; + $this->view->cases = $cases; + $this->view->users = $this->user->getPairs('noletter'); + $this->view->tabID = 'test'; + $this->view->type = $type; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * My projects. + * + * @access public + * @return void + */ + public function project() + { + $this->app->loadLang('project'); + + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->myProject; + $this->view->position[] = $this->lang->my->myProject; + $this->view->tabID = 'project'; + $this->view->projects = @array_reverse($this->user->getProjects($this->app->user->account)); + + $this->display(); + } + + /** + * Edit profile + * + * @access public + * @return void + */ + public function editProfile() + { + if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); + if(!empty($_POST)) + { + $this->user->update($this->app->user->id); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('my', 'profile'), 'parent')); + } + + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->editProfile; + $this->view->position[] = $this->lang->my->editProfile; + $this->view->user = $this->user->getById($this->app->user->id); + + $this->display(); + } + + /** + * View my profile. + * + * @access public + * @return void + */ + public function profile() + { + if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); + $user = $this->user->getById($this->app->user->account); + $deptPath = $this->dept->getParents($user->dept); + $this->view->deptPath = $deptPath; + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->profile; + $this->view->position[] = $this->lang->my->profile; + $this->view->user = $this->user->getById($this->app->user->id); + $this->display(); + } + + /** + * My dynamic. + * + * @param string $type + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function dynamic($type = 'today', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('productList', $uri); + $this->session->set('productPlanList', $uri); + $this->session->set('releaseList', $uri); + $this->session->set('storyList', $uri); + $this->session->set('projectList', $uri); + $this->session->set('taskList', $uri); + $this->session->set('buildList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('caseList', $uri); + $this->session->set('testtaskList', $uri); + + /* Set the pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + /* The header and position. */ + $this->view->header->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->dynamic; + $this->view->position[] = $this->lang->my->dynamic; + + /* Assign. */ + $this->view->type = $type; + $this->view->actions = $this->loadModel('action')->getDynamic($this->app->user->account, $type, $orderBy, $pager); + $this->display(); + } + +} diff --git a/module/my/model.php b/module/my/model.php index f65aace634..6ec4ed6c3d 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -1,26 +1,26 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> -lang->my->menu->account = sprintf($this->lang->my->menu->account, $this->app->user->realname); - } -} + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> +lang->my->menu->account = sprintf($this->lang->my->menu->account, $this->app->user->realname); + } +} diff --git a/module/my/view/bug.html.php b/module/my/view/bug.html.php index f2e8e0dd44..6d5d2be71d 100644 --- a/module/my/view/bug.html.php +++ b/module/my/view/bug.html.php @@ -1,65 +1,65 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          - " . html::a(inlink('bug', "type=assigntome"), $lang->bug->assignToMe) . ""; - echo "" . html::a(inlink('bug', "type=openedbyme"), $lang->bug->openedByMe) . ""; - echo "" . html::a(inlink('bug', "type=resolvedbyme"), $lang->bug->resolvedByMe) . ""; - echo "" . html::a(inlink('bug', "type=closedbyme"), $lang->bug->closedByMe) . ""; - ?> -
          -
          -recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>bug->severityAB;?>priAB;?>typeAB;?>bug->title;?>openedByAB;?>bug->resolvedByAB;?>bug->resolutionAB;?>actions;?>
          createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> - id"; - if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; - if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; - common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); - ?> -
          show();?>
          - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          + " . html::a(inlink('bug', "type=assigntome"), $lang->bug->assignToMe) . ""; + echo "" . html::a(inlink('bug', "type=openedbyme"), $lang->bug->openedByMe) . ""; + echo "" . html::a(inlink('bug', "type=resolvedbyme"), $lang->bug->resolvedByMe) . ""; + echo "" . html::a(inlink('bug', "type=closedbyme"), $lang->bug->closedByMe) . ""; + ?> +
          +
          +recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>bug->severityAB;?>priAB;?>typeAB;?>bug->title;?>openedByAB;?>bug->resolvedByAB;?>bug->resolutionAB;?>actions;?>
          createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> + id"; + if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; + if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; + common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); + ?> +
          show();?>
          + + diff --git a/module/my/view/dynamic.html.php b/module/my/view/dynamic.html.php index 6b65d78baa..a3423594fe 100644 --- a/module/my/view/dynamic.html.php +++ b/module/my/view/dynamic.html.php @@ -1,55 +1,55 @@ -dynamic view file of dashboard module of ZenTaoPMS. - * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) - * @license LGPL (http://www.gnu.org/licenses/lgpl.html) - * @author Chunsheng Wang - * @package dashboard - * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ - * @link http://www.zentao.net - */ -?> - - -
          - ' . html::a(inlink('dynamic', "type=today"), $lang->action->dynamic->today) . ''; - echo '' . html::a(inlink('dynamic', "type=yesterday"), $lang->action->dynamic->yesterday) . ''; - echo '' . html::a(inlink('dynamic', "type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; - echo '' . html::a(inlink('dynamic', "type=thisweek"), $lang->action->dynamic->thisWeek) . ''; - echo '' . html::a(inlink('dynamic', "type=lastweek"), $lang->action->dynamic->lastWeek) . ''; - echo '' . html::a(inlink('dynamic', "type=thismonth"), $lang->action->dynamic->thisMonth) . ''; - echo '' . html::a(inlink('dynamic', "type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; - echo '' . html::a(inlink('dynamic', "type=all"), $lang->action->dynamic->all) . ''; - ?> -
          - - - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - -
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>user->realname;?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @license LGPL (http://www.gnu.org/licenses/lgpl.html) + * @author Chunsheng Wang + * @package dashboard + * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ + * @link http://www.zentao.net + */ +?> + + +
          + ' . html::a(inlink('dynamic', "type=today"), $lang->action->dynamic->today) . ''; + echo '' . html::a(inlink('dynamic', "type=yesterday"), $lang->action->dynamic->yesterday) . ''; + echo '' . html::a(inlink('dynamic', "type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; + echo '' . html::a(inlink('dynamic', "type=thisweek"), $lang->action->dynamic->thisWeek) . ''; + echo '' . html::a(inlink('dynamic', "type=lastweek"), $lang->action->dynamic->lastWeek) . ''; + echo '' . html::a(inlink('dynamic', "type=thismonth"), $lang->action->dynamic->thisMonth) . ''; + echo '' . html::a(inlink('dynamic', "type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; + echo '' . html::a(inlink('dynamic', "type=all"), $lang->action->dynamic->all) . ''; + ?> +
          + + + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + +
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>user->realname;?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          + + diff --git a/module/my/view/editprofile.html.php b/module/my/view/editprofile.html.php index 5340d6104e..e8aecb398d 100644 --- a/module/my/view/editprofile.html.php +++ b/module/my/view/editprofile.html.php @@ -1,100 +1,100 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          my->editProfile;?>
          user->account;?>account . html::hidden('account',$user->account);?>
          user->realname;?>realname);?>
          user->commiter;?>commiter);?>
          user->email;?>email);?>
          user->gender;?>user->genderList, $user->gender);?>
          user->password;?>
          user->password2;?>
          user->birthyear;?>birthday,"class='date'");?>
          user->join;?>account, "readonly"); - echo $user->join; - echo html::hidden('join',$user->join); - ?> -
          user->msn;?>msn);?>
          user->qq;?>qq);?>
          user->yahoo;?>yahoo);?>
          user->gtalk;?>gtalk);?>
          user->wangwang;?>wangwang);?>
          user->mobile;?>mobile);?>
          user->phone;?>phone);?>
          user->address;?>address);?>
          user->zipcode;?>zipcode);?>
          -
          - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          my->editProfile;?>
          user->account;?>account . html::hidden('account',$user->account);?>
          user->realname;?>realname);?>
          user->commiter;?>commiter);?>
          user->email;?>email);?>
          user->gender;?>user->genderList, $user->gender);?>
          user->password;?>
          user->password2;?>
          user->birthyear;?>birthday,"class='date'");?>
          user->join;?>account, "readonly"); + echo $user->join; + echo html::hidden('join',$user->join); + ?> +
          user->msn;?>msn);?>
          user->qq;?>qq);?>
          user->yahoo;?>yahoo);?>
          user->gtalk;?>gtalk);?>
          user->wangwang;?>wangwang);?>
          user->mobile;?>mobile);?>
          user->phone;?>phone);?>
          user->address;?>address);?>
          user->zipcode;?>zipcode);?>
          +
          + diff --git a/module/my/view/index.html.php b/module/my/view/index.html.php index 435b810986..69641ea887 100644 --- a/module/my/view/index.html.php +++ b/module/my/view/index.html.php @@ -1,31 +1,31 @@ - - * @package ZenTaoPMS - * @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $ - */ -?> - - - - - - - - -
          -
          - -
          - - - - - - -
          - + + * @package ZenTaoPMS + * @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $ + */ +?> + + + + + + + + +
          +
          + +
          + + + + + + +
          + diff --git a/module/my/view/profile.html.php b/module/my/view/profile.html.php index 83f33adbdb..d14f731242 100644 --- a/module/my/view/profile.html.php +++ b/module/my/view/profile.html.php @@ -1,120 +1,120 @@ - - * @package my - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          my->profile;?>
          user->dept;?> - $dept) - { - if($dept->name) echo $dept->name; - if(isset($deptPath[$key + 1])) echo $lang->arrow; - } - } - ?> -
          user->account;?>account;?>
          user->realname;?>realname;?>
          user->commiter;?>commiter;?>
          user->email;?>email;?>
          user->join;?>join;?>
          user->visits;?>visits;?>
          user->ip;?>ip;?>
          user->last;?>last;?>
          user->msn;?>msn;?>
          user->qq;?>qq;?>
          user->yahoo;?>yahoo;?>
          user->gtalk;?>gtalk;?>
          user->wangwang;?>wangwang;?>
          user->mobile;?>mobile;?>
          user->phone;?>phone;?>
          user->address;?>address;?>
          user->zipcode;?>zipcode;?>
          - createLink('my', 'editprofile'), $lang->user->editProfile); - echo html::a($this->createLink('user', 'logout'), $lang->logout); - ?> -
          - + + * @package my + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          my->profile;?>
          user->dept;?> + $dept) + { + if($dept->name) echo $dept->name; + if(isset($deptPath[$key + 1])) echo $lang->arrow; + } + } + ?> +
          user->account;?>account;?>
          user->realname;?>realname;?>
          user->commiter;?>commiter;?>
          user->email;?>email;?>
          user->join;?>join;?>
          user->visits;?>visits;?>
          user->ip;?>ip;?>
          user->last;?>last;?>
          user->msn;?>msn;?>
          user->qq;?>qq;?>
          user->yahoo;?>yahoo;?>
          user->gtalk;?>gtalk;?>
          user->wangwang;?>wangwang;?>
          user->mobile;?>mobile;?>
          user->phone;?>phone;?>
          user->address;?>address;?>
          user->zipcode;?>zipcode;?>
          + createLink('my', 'editprofile'), $lang->user->editProfile); + echo html::a($this->createLink('user', 'logout'), $lang->logout); + ?> +
          + diff --git a/module/my/view/project.html.php b/module/my/view/project.html.php index 1ee3ffc1ad..289a8a0154 100644 --- a/module/my/view/project.html.php +++ b/module/my/view/project.html.php @@ -1,46 +1,46 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - createLink('project', 'browse', "projectID=$project->id");?> - - - - - - - - - - - - - -
          idAB;?>project->code;?>project->name;?>project->begin;?>project->end;?>statusAB;?>team->role;?>team->join;?>team->hours;?>
          id);?>code;?>name);?>begin;?>end;?>project->statusList[$project->status];?>role;?>join;?>hours;?>
          - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + createLink('project', 'browse', "projectID=$project->id");?> + + + + + + + + + + + + + +
          idAB;?>project->code;?>project->name;?>project->begin;?>project->end;?>statusAB;?>team->role;?>team->join;?>team->hours;?>
          id);?>code;?>name);?>begin;?>end;?>project->statusList[$project->status];?>role;?>join;?>hours;?>
          + diff --git a/module/my/view/story.html.php b/module/my/view/story.html.php index d0fbad4118..2c396554b6 100644 --- a/module/my/view/story.html.php +++ b/module/my/view/story.html.php @@ -1,65 +1,65 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          - " . html::a(inlink('story', "type=assignedto"), $lang->my->storyMenu->assignedToMe) . ""; - echo "" . html::a(inlink('story', "type=openedby"), $lang->my->storyMenu->openedByMe) . ""; - echo "" . html::a(inlink('story', "type=reviewedby"), $lang->my->storyMenu->reviewedByMe) . ""; - echo "" . html::a(inlink('story', "type=closedby"), $lang->my->storyMenu->closedByMe) . ""; - ?> -
          -
          - - - - - - - - - - - - - - - - - $story):?> - createLink('story', 'view', "id=$story->id");?> - - - - - - - - - - - - - - -
          idAB;?>priAB;?>story->product;?>story->title;?>story->plan;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions;?>
          id));?>pri;?>productTitle;?>title);?>planTitle;?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; - if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; - if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; - ?> -
          - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          + " . html::a(inlink('story', "type=assignedto"), $lang->my->storyMenu->assignedToMe) . ""; + echo "" . html::a(inlink('story', "type=openedby"), $lang->my->storyMenu->openedByMe) . ""; + echo "" . html::a(inlink('story', "type=reviewedby"), $lang->my->storyMenu->reviewedByMe) . ""; + echo "" . html::a(inlink('story', "type=closedby"), $lang->my->storyMenu->closedByMe) . ""; + ?> +
          +
          + + + + + + + + + + + + + + + + + $story):?> + createLink('story', 'view', "id=$story->id");?> + + + + + + + + + + + + + + +
          idAB;?>priAB;?>story->product;?>story->title;?>story->plan;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions;?>
          id));?>pri;?>productTitle;?>title);?>planTitle;?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; + if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; + if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; + ?> +
          + + diff --git a/module/my/view/task.html.php b/module/my/view/task.html.php index 53a53360b8..06be12ea41 100644 --- a/module/my/view/task.html.php +++ b/module/my/view/task.html.php @@ -1,82 +1,82 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          -
          - " . html::a(inlink('task', "type=assignedto"), $lang->my->taskMenu->assignedToMe) . ""; - echo "" . html::a(inlink('task', "type=openedby"), $lang->my->taskMenu->openedByMe) . ""; - echo "" . html::a(inlink('task', "type=finishedby"), $lang->my->taskMenu->finishedByMe) . ""; - echo "" . html::a(inlink('task', "type=closedby"), $lang->my->taskMenu->closedByMe) . ""; - echo "" . html::a(inlink('task', "type=canceledby"), $lang->my->taskMenu->canceledByMe) . ""; - ?> -
          -
          -
          '> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>priAB;?>task->project;?>task->name;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>openedByAB;?>actions;?>
          - - createLink('task', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?> - task->priList[$task->pri];?>createLink('project', 'browse', "projectid=$task->projectID"), $task->projectName);?> - createLink('task', 'view', "taskID=$task->id"), $task->name);?>estimate;?>consumed;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>task->statusList[$task->status];?>openedBy];?> - status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; - if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; - if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; - if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; - ?> -
          - selectAll;?> - close)?> -
          -
          - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          +
          + " . html::a(inlink('task', "type=assignedto"), $lang->my->taskMenu->assignedToMe) . ""; + echo "" . html::a(inlink('task', "type=openedby"), $lang->my->taskMenu->openedByMe) . ""; + echo "" . html::a(inlink('task', "type=finishedby"), $lang->my->taskMenu->finishedByMe) . ""; + echo "" . html::a(inlink('task', "type=closedby"), $lang->my->taskMenu->closedByMe) . ""; + echo "" . html::a(inlink('task', "type=canceledby"), $lang->my->taskMenu->canceledByMe) . ""; + ?> +
          +
          +
          '> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>priAB;?>task->project;?>task->name;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>openedByAB;?>actions;?>
          + + createLink('task', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?> + task->priList[$task->pri];?>createLink('project', 'browse', "projectid=$task->projectID"), $task->projectName);?> + createLink('task', 'view', "taskID=$task->id"), $task->name);?>estimate;?>consumed;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>task->statusList[$task->status];?>openedBy];?> + status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; + if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; + if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; + if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; + ?> +
          + selectAll;?> + close)?> +
          +
          + diff --git a/module/my/view/team.html.php b/module/my/view/team.html.php index ed3f21d400..7030b367d6 100644 --- a/module/my/view/team.html.php +++ b/module/my/view/team.html.php @@ -1,14 +1,14 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + diff --git a/module/my/view/testcase.html.php b/module/my/view/testcase.html.php index 09a18dae14..78d7afc3ad 100644 --- a/module/my/view/testcase.html.php +++ b/module/my/view/testcase.html.php @@ -1,59 +1,59 @@ - - * @package dashboard - * @version $Id: test.html.php 1191 2010-11-13 07:30:35Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - -
          -
          - " . html::a($this->createLink('my', 'testtask'), $lang->my->testTask) . ""; - echo "" . html::a($this->createLink('my', 'testcase', "type=assigntome"), $lang->testcase->assignToMe) . ""; - //echo "" . html::a($this->createLink('my', 'testcase', "type=donebyme"), $lang->testcase->doneByMe) . ""; - echo "" . html::a($this->createLink('my', 'testcase', "type=openedbyme"), $lang->testcase->openedByMe) . ""; - ?> -
          -
          - -recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>priAB;?>testcase->title;?> typeAB;?> openedByAB;?>statusAB;?>actions;?>
          createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?>createLink('testcase', 'view', "testcaseID=$case->id"), $case->title);?>testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> - id", $lang->testcase->buttonEdit); - ?> -
          show();?>
          - - + + * @package dashboard + * @version $Id: test.html.php 1191 2010-11-13 07:30:35Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + +
          +
          + " . html::a($this->createLink('my', 'testtask'), $lang->my->testTask) . ""; + echo "" . html::a($this->createLink('my', 'testcase', "type=assigntome"), $lang->testcase->assignToMe) . ""; + //echo "" . html::a($this->createLink('my', 'testcase', "type=donebyme"), $lang->testcase->doneByMe) . ""; + echo "" . html::a($this->createLink('my', 'testcase', "type=openedbyme"), $lang->testcase->openedByMe) . ""; + ?> +
          +
          + +recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>priAB;?>testcase->title;?> typeAB;?> openedByAB;?>statusAB;?>actions;?>
          createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?>createLink('testcase', 'view', "testcaseID=$case->id"), $case->title);?>testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> + id", $lang->testcase->buttonEdit); + ?> +
          show();?>
          + + diff --git a/module/my/view/testtask.html.php b/module/my/view/testtask.html.php index 49018b9d0d..2a861cccf1 100644 --- a/module/my/view/testtask.html.php +++ b/module/my/view/testtask.html.php @@ -1,60 +1,60 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          - " . html::a($this->createLink('my', 'testtask'), $lang->my->testTask) . ""; - echo "" . html::a($this->createLink('my', 'testcase', "type=assigntome"), $lang->testcase->assignToMe) . ""; - //echo "" . html::a($this->createLink('my', 'testcase', "type=donebyme"), $lang->testcase->doneByMe) . ""; - echo "" . html::a($this->createLink('my', 'testcase', "type=openedbyme"), $lang->testcase->openedByMe) . ""; - ?> -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>testtask->name;?>testtask->project;?>testtask->build;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>projectName?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>begin?>end?>testtask->statusList[$task->status];?> - id", $lang->testtask->cases); - common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); - common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); - ?> -
          - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          + " . html::a($this->createLink('my', 'testtask'), $lang->my->testTask) . ""; + echo "" . html::a($this->createLink('my', 'testcase', "type=assigntome"), $lang->testcase->assignToMe) . ""; + //echo "" . html::a($this->createLink('my', 'testcase', "type=donebyme"), $lang->testcase->doneByMe) . ""; + echo "" . html::a($this->createLink('my', 'testcase', "type=openedbyme"), $lang->testcase->openedByMe) . ""; + ?> +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>testtask->name;?>testtask->project;?>testtask->build;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>projectName?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>begin?>end?>testtask->statusList[$task->status];?> + id", $lang->testtask->cases); + common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); + common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); + ?> +
          + + diff --git a/module/my/view/todo.html.php b/module/my/view/todo.html.php index eddc0683af..3b0254d098 100644 --- a/module/my/view/todo.html.php +++ b/module/my/view/todo.html.php @@ -1,89 +1,89 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          ' id='todoform'> -
          -
          - ' . html::a(inlink('todo', "date=today"), $lang->todo->todayTodos) . ''; - echo '' . html::a(inlink('todo', "date=thisweek"), $lang->todo->thisWeekTodos) . ''; - echo '' . html::a(inlink('todo', "date=lastweek"), $lang->todo->lastWeekTodos) . ''; - echo '' . html::a(inlink('todo', "date=future"), $lang->todo->futureTodos) . ''; - echo '' . html::a(inlink('todo', "date=all"), $lang->todo->allDaysTodos) . ''; - echo '' . html::a(inlink('todo', "date=before&account={$app->user->account}&status=undone"), $lang->todo->allUndone) . ''; - echo "" . html::select('date', $dates, $date, 'onchange=changeDate(this.value)') . ''; - ?> - -
          -
          - export, '', 'class="export"'); - echo html::a($this->createLink('todo', 'create', "date=$date"), $lang->todo->create); - ?> -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>todo->date;?>todo->type;?>priAB;?>todo->name;?>todo->beginAB;?>todo->endAB;?>todo->status;?>actions;?>
          - id' /> "; - echo $todo->id; - ?> - date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList->{$todo->type};?>pri;?>createLink('todo', 'view', "id=$todo->id&from=my"), $todo->name);?>begin;?>end;?>todo->statusList[$todo->status];?> - createLink('todo', 'mark', "id=$todo->id&status=$todo->status"), $lang->todo->{'mark'.ucfirst($todo->status)}, 'hiddenwin'); - echo html::a($this->createLink('todo', 'view', "id=$todo->id&from=my"), $lang->todo->viewAB); - echo html::a($this->createLink('todo', 'edit', "id=$todo->id"), $lang->edit); - echo html::a($this->createLink('todo', 'delete', "id=$todo->id"), $lang->delete, 'hiddenwin'); - ?> -
          - -
          -
          - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          ' id='todoform'> +
          +
          + ' . html::a(inlink('todo', "date=today"), $lang->todo->todayTodos) . ''; + echo '' . html::a(inlink('todo', "date=thisweek"), $lang->todo->thisWeekTodos) . ''; + echo '' . html::a(inlink('todo', "date=lastweek"), $lang->todo->lastWeekTodos) . ''; + echo '' . html::a(inlink('todo', "date=future"), $lang->todo->futureTodos) . ''; + echo '' . html::a(inlink('todo', "date=all"), $lang->todo->allDaysTodos) . ''; + echo '' . html::a(inlink('todo', "date=before&account={$app->user->account}&status=undone"), $lang->todo->allUndone) . ''; + echo "" . html::select('date', $dates, $date, 'onchange=changeDate(this.value)') . ''; + ?> + +
          +
          + export, '', 'class="export"'); + echo html::a($this->createLink('todo', 'create', "date=$date"), $lang->todo->create); + ?> +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>todo->date;?>todo->type;?>priAB;?>todo->name;?>todo->beginAB;?>todo->endAB;?>todo->status;?>actions;?>
          + id' /> "; + echo $todo->id; + ?> + date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList->{$todo->type};?>pri;?>createLink('todo', 'view', "id=$todo->id&from=my"), $todo->name);?>begin;?>end;?>todo->statusList[$todo->status];?> + createLink('todo', 'mark', "id=$todo->id&status=$todo->status"), $lang->todo->{'mark'.ucfirst($todo->status)}, 'hiddenwin'); + echo html::a($this->createLink('todo', 'view', "id=$todo->id&from=my"), $lang->todo->viewAB); + echo html::a($this->createLink('todo', 'edit', "id=$todo->id"), $lang->edit); + echo html::a($this->createLink('todo', 'delete', "id=$todo->id"), $lang->delete, 'hiddenwin'); + ?> +
          + +
          +
          + diff --git a/module/product/control.php b/module/product/control.php index 99bbda583e..bc97623d77 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -1,380 +1,380 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -class product extends control -{ - private $products = array(); - - /** - * Construct function. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - - /* Load need modules. */ - $this->loadModel('story'); - $this->loadModel('release'); - $this->loadModel('tree'); - $this->loadModel('user'); - - /* Get all products, if no, goto the create page. */ - $this->products = $this->product->getPairs(); - if(empty($this->products) and strpos('create|view', $this->methodName) === false) $this->locate($this->createLink('product', 'create')); - $this->view->products = $this->products; - } - - /** - * Index page, to browse. - * - * @access public - * @return void - */ - public function index($locate = 'yes') - { - if($locate == 'yes') $this->locate($this->createLink($this->moduleName, 'browse')); - - $this->app->loadLang('my'); - $this->view->productStats = $this->product->getStats(); - $this->display(); - } - - /** - * project - * - * @param string $status - * @param int $productID - * @access public - * @return void - */ - public function project($status = 'all', $productID = 0) - { - $this->app->loadLang('my'); - $this->view->projectStats = $this->loadModel('project')->getProjectStats($status, $productID); - - $this->view->productID = $productID; - $this->display(); - } - - /** - * Browse a product. - * - * @param int $productID - * @param string $browseType - * @param int $param - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Lower browse type. */ - $browseType = strtolower($browseType); - - /* Save session. */ - $this->session->set('storyList', $this->app->getURI(true)); - $this->session->set('productList', $this->app->getURI(true)); - - /* Set product, module and query. */ - $productID = $this->product->saveState($productID, $this->products); - $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Set menu. */ - $this->product->setMenu($this->products, $productID); - - /* Process the order by field. */ - if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc'; - setcookie('productStoryOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); - - /* Set header and position. */ - $this->view->header->title = $this->lang->product->index . $this->lang->colon . $this->products[$productID]; - $this->view->position[] = $this->products[$productID]; - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - /* Get stories. */ - $stories = array(); - if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, 0, 'all', $orderBy, $pager); - if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $this->tree->getAllChildID($moduleID), 'all', $orderBy, $pager); - if($browseType == 'bysearch') $stories = $this->story->getBySearch($productID, $queryID, $orderBy, $pager); - if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $this->app->user->account, $orderBy, $pager); - if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $this->app->user->account, $orderBy, $pager); - if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $this->app->user->account, $orderBy, $pager); - if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $this->app->user->account, $orderBy, $pager); - if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, 'draft', $orderBy, $pager); - if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, 'active', $orderBy, $pager); - if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, 'changed', $orderBy, $pager); - if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, 'closed', $orderBy, $pager); - - /* Build search form. */ - $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); - $this->config->product->search['queryID'] = $queryID; - $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID); - $this->config->product->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->product->allProduct); - $this->config->product->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'story', $startModuleID = 0); - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->product->search); - - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleID = $moduleID; - $this->view->stories = $stories; - $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'story', $startModuleID = 0, array('treeModel', 'createStoryLink')); - $this->view->parentModules = $this->tree->getParents($moduleID); - $this->view->pager = $pager; - $this->view->users = $this->user->getPairs('noletter'); - $this->view->orderBy = $orderBy; - $this->view->browseType = $browseType; - $this->view->moduleID = $moduleID; - $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; - $this->display(); - } - - /** - * Create a product. - * - * @access public - * @return void - */ - public function create() - { - if(!empty($_POST)) - { - $productID = $this->product->create(); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('product', $productID, 'opened'); - die(js::locate($this->createLink($this->moduleName, 'browse', "productID=$productID"), 'parent')); - } - - $this->product->setMenu($this->products, key($this->products)); - - $this->view->header->title = $this->lang->product->create; - $this->view->position[] = $this->view->header->title; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs(); - $this->display(); - } - - /** - * Edit a product. - * - * @param int $productID - * @access public - * @return void - */ - public function edit($productID) - { - if(!empty($_POST)) - { - $changes = $this->product->update($productID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('product', $productID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "product=$productID"), 'parent')); - } - - $this->product->setMenu($this->products, $productID); - - $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - $this->view->header->title = $this->lang->product->edit . $this->lang->colon . $product->name; - $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); - $this->view->position[] = $this->lang->product->edit; - $this->view->product = $product; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->users = $this->loadModel('user')->getPairs(); - - $this->display(); - } - - /** - * View a product. - * - * @param int $productID - * @access public - * @return void - */ - public function view($productID) - { - $this->product->setMenu($this->products, $productID); - - $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - $product->desc = $this->loadModel('file')->setImgSize($product->desc); - if(!$product) die(js::error($this->lang->notFound) . js::locate('back')); - - $this->view->header->title = $this->lang->product->view . $this->lang->colon . $product->name; - $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); - $this->view->position[] = $this->lang->product->view; - $this->view->product = $product; - $this->view->actions = $this->loadModel('action')->getList('product', $productID); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->groups = $this->loadModel('group')->getPairs(); - - $this->display(); - } - - /** - * Delete a product. - * - * @param int $productID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($productID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->product->confirmDelete, $this->createLink('product', 'delete', "productID=$productID&confirm=yes"))); - } - else - { - $this->product->delete(TABLE_PRODUCT, $productID); - $this->session->set('product', ''); // 清除session。 - die(js::locate($this->createLink('product', 'browse'), 'parent')); - } - } - - /** - * Docs of a product. - * - * @param int $productID - * @access public - * @return void - */ - public function doc($productID) - { - $this->product->setMenu($this->products, $productID); - $this->session->set('docList', $this->app->getURI(true)); - - $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - $this->view->header->title = $this->lang->product->doc; - $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); - $this->view->position[] = $this->lang->product->doc; - $this->view->product = $product; - $this->view->docs = $this->loadModel('doc')->getProductDocs($productID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Road map of a product. - * - * @param int $productID - * @access public - * @return void - */ - public function roadmap($productID) - { - $this->product->setMenu($this->products, $productID); - - $this->session->set('releaseList', $this->app->getURI(true)); - $this->session->set('productPlanList', $this->app->getURI(true)); - - $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - $this->view->header->title = $this->lang->product->roadmap; - $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); - $this->view->position[] = $this->lang->product->roadmap; - $this->view->product = $product; - $this->view->roadmaps = $this->product->getRoadmap($productID); - - $this->display(); - } - - /** - * Product dynamic. - * - * @param string $type - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function dynamic($productID = 0, $type = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('productList', $uri); - $this->session->set('productPlanList', $uri); - $this->session->set('releaseList', $uri); - $this->session->set('storyList', $uri); - $this->session->set('projectList', $uri); - $this->session->set('taskList', $uri); - $this->session->set('buildList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('caseList', $uri); - $this->session->set('testtaskList', $uri); - - $this->product->setMenu($this->products, $productID); - - /* Set the pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - /* Set the user and type. */ - $account = $type == 'account' ? $param : 'all'; - $period = $type == 'account' ? 'all' : $type; - - /* The header and position. */ - $this->view->header->title = $this->lang->product->dynamic; - $this->view->position[] = $this->lang->product->dynamic; - - /* Assign. */ - $this->view->productID = $productID; - $this->view->type = $type; - $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter'); - $this->view->account = $account; - $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager, $productID); - $this->display(); - } - - /** - * AJAX: get projects of a product in html select. - * - * @param int $productID - * @param int $projectID - * @access public - * @return void - */ - public function ajaxGetProjects($productID, $projectID = 0) - { - $projects = $this->product->getProjectPairs($productID); - die(html::select('project', $projects, $projectID, 'onchange=loadProjectRelated(this.value)')); - } - - /** - * AJAX: get plans of a product in html select. - * - * @param int $productID - * @param int $planID - * @access public - * @return void - */ - public function ajaxGetPlans($productID, $planID = 0) - { - $plans = $this->loadModel('productplan')->getPairs($productID); - die(html::select('plan', $plans, $planID)); - } -} + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +class product extends control +{ + private $products = array(); + + /** + * Construct function. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + + /* Load need modules. */ + $this->loadModel('story'); + $this->loadModel('release'); + $this->loadModel('tree'); + $this->loadModel('user'); + + /* Get all products, if no, goto the create page. */ + $this->products = $this->product->getPairs(); + if(empty($this->products) and strpos('create|view', $this->methodName) === false) $this->locate($this->createLink('product', 'create')); + $this->view->products = $this->products; + } + + /** + * Index page, to browse. + * + * @access public + * @return void + */ + public function index($locate = 'yes') + { + if($locate == 'yes') $this->locate($this->createLink($this->moduleName, 'browse')); + + $this->app->loadLang('my'); + $this->view->productStats = $this->product->getStats(); + $this->display(); + } + + /** + * project + * + * @param string $status + * @param int $productID + * @access public + * @return void + */ + public function project($status = 'all', $productID = 0) + { + $this->app->loadLang('my'); + $this->view->projectStats = $this->loadModel('project')->getProjectStats($status, $productID); + + $this->view->productID = $productID; + $this->display(); + } + + /** + * Browse a product. + * + * @param int $productID + * @param string $browseType + * @param int $param + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Lower browse type. */ + $browseType = strtolower($browseType); + + /* Save session. */ + $this->session->set('storyList', $this->app->getURI(true)); + $this->session->set('productList', $this->app->getURI(true)); + + /* Set product, module and query. */ + $productID = $this->product->saveState($productID, $this->products); + $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Set menu. */ + $this->product->setMenu($this->products, $productID); + + /* Process the order by field. */ + if(!$orderBy) $orderBy = $this->cookie->productStoryOrder ? $this->cookie->productStoryOrder : 'id_desc'; + setcookie('productStoryOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); + + /* Set header and position. */ + $this->view->header->title = $this->lang->product->index . $this->lang->colon . $this->products[$productID]; + $this->view->position[] = $this->products[$productID]; + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + /* Get stories. */ + $stories = array(); + if($browseType == 'allstory') $stories = $this->story->getProductStories($productID, 0, 'all', $orderBy, $pager); + if($browseType == 'bymodule') $stories = $this->story->getProductStories($productID, $this->tree->getAllChildID($moduleID), 'all', $orderBy, $pager); + if($browseType == 'bysearch') $stories = $this->story->getBySearch($productID, $queryID, $orderBy, $pager); + if($browseType == 'assignedtome')$stories = $this->story->getByAssignedTo($productID, $this->app->user->account, $orderBy, $pager); + if($browseType == 'openedbyme') $stories = $this->story->getByOpenedBy($productID, $this->app->user->account, $orderBy, $pager); + if($browseType == 'reviewedbyme')$stories = $this->story->getByReviewedBy($productID, $this->app->user->account, $orderBy, $pager); + if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $this->app->user->account, $orderBy, $pager); + if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, 'draft', $orderBy, $pager); + if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, 'active', $orderBy, $pager); + if($browseType == 'changedstory')$stories = $this->story->getByStatus($productID, 'changed', $orderBy, $pager); + if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, 'closed', $orderBy, $pager); + + /* Build search form. */ + $this->config->product->search['actionURL'] = $this->createLink('product', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); + $this->config->product->search['queryID'] = $queryID; + $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getPairs($productID); + $this->config->product->search['params']['product']['values'] = array($productID => $this->products[$productID], 'all' => $this->lang->product->allProduct); + $this->config->product->search['params']['module']['values'] = $this->tree->getOptionMenu($productID, $viewType = 'story', $startModuleID = 0); + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->product->search); + + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleID = $moduleID; + $this->view->stories = $stories; + $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'story', $startModuleID = 0, array('treeModel', 'createStoryLink')); + $this->view->parentModules = $this->tree->getParents($moduleID); + $this->view->pager = $pager; + $this->view->users = $this->user->getPairs('noletter'); + $this->view->orderBy = $orderBy; + $this->view->browseType = $browseType; + $this->view->moduleID = $moduleID; + $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; + $this->display(); + } + + /** + * Create a product. + * + * @access public + * @return void + */ + public function create() + { + if(!empty($_POST)) + { + $productID = $this->product->create(); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('product', $productID, 'opened'); + die(js::locate($this->createLink($this->moduleName, 'browse', "productID=$productID"), 'parent')); + } + + $this->product->setMenu($this->products, key($this->products)); + + $this->view->header->title = $this->lang->product->create; + $this->view->position[] = $this->view->header->title; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs(); + $this->display(); + } + + /** + * Edit a product. + * + * @param int $productID + * @access public + * @return void + */ + public function edit($productID) + { + if(!empty($_POST)) + { + $changes = $this->product->update($productID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('product', $productID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "product=$productID"), 'parent')); + } + + $this->product->setMenu($this->products, $productID); + + $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); + $this->view->header->title = $this->lang->product->edit . $this->lang->colon . $product->name; + $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); + $this->view->position[] = $this->lang->product->edit; + $this->view->product = $product; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->users = $this->loadModel('user')->getPairs(); + + $this->display(); + } + + /** + * View a product. + * + * @param int $productID + * @access public + * @return void + */ + public function view($productID) + { + $this->product->setMenu($this->products, $productID); + + $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); + $product->desc = $this->loadModel('file')->setImgSize($product->desc); + if(!$product) die(js::error($this->lang->notFound) . js::locate('back')); + + $this->view->header->title = $this->lang->product->view . $this->lang->colon . $product->name; + $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); + $this->view->position[] = $this->lang->product->view; + $this->view->product = $product; + $this->view->actions = $this->loadModel('action')->getList('product', $productID); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->groups = $this->loadModel('group')->getPairs(); + + $this->display(); + } + + /** + * Delete a product. + * + * @param int $productID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($productID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->product->confirmDelete, $this->createLink('product', 'delete', "productID=$productID&confirm=yes"))); + } + else + { + $this->product->delete(TABLE_PRODUCT, $productID); + $this->session->set('product', ''); // 清除session。 + die(js::locate($this->createLink('product', 'browse'), 'parent')); + } + } + + /** + * Docs of a product. + * + * @param int $productID + * @access public + * @return void + */ + public function doc($productID) + { + $this->product->setMenu($this->products, $productID); + $this->session->set('docList', $this->app->getURI(true)); + + $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); + $this->view->header->title = $this->lang->product->doc; + $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); + $this->view->position[] = $this->lang->product->doc; + $this->view->product = $product; + $this->view->docs = $this->loadModel('doc')->getProductDocs($productID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Road map of a product. + * + * @param int $productID + * @access public + * @return void + */ + public function roadmap($productID) + { + $this->product->setMenu($this->products, $productID); + + $this->session->set('releaseList', $this->app->getURI(true)); + $this->session->set('productPlanList', $this->app->getURI(true)); + + $product = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); + $this->view->header->title = $this->lang->product->roadmap; + $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $product->name); + $this->view->position[] = $this->lang->product->roadmap; + $this->view->product = $product; + $this->view->roadmaps = $this->product->getRoadmap($productID); + + $this->display(); + } + + /** + * Product dynamic. + * + * @param string $type + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function dynamic($productID = 0, $type = 'today', $param = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('productList', $uri); + $this->session->set('productPlanList', $uri); + $this->session->set('releaseList', $uri); + $this->session->set('storyList', $uri); + $this->session->set('projectList', $uri); + $this->session->set('taskList', $uri); + $this->session->set('buildList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('caseList', $uri); + $this->session->set('testtaskList', $uri); + + $this->product->setMenu($this->products, $productID); + + /* Set the pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + /* Set the user and type. */ + $account = $type == 'account' ? $param : 'all'; + $period = $type == 'account' ? 'all' : $type; + + /* The header and position. */ + $this->view->header->title = $this->lang->product->dynamic; + $this->view->position[] = $this->lang->product->dynamic; + + /* Assign. */ + $this->view->productID = $productID; + $this->view->type = $type; + $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter'); + $this->view->account = $account; + $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager, $productID); + $this->display(); + } + + /** + * AJAX: get projects of a product in html select. + * + * @param int $productID + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetProjects($productID, $projectID = 0) + { + $projects = $this->product->getProjectPairs($productID); + die(html::select('project', $projects, $projectID, 'onchange=loadProjectRelated(this.value)')); + } + + /** + * AJAX: get plans of a product in html select. + * + * @param int $productID + * @param int $planID + * @access public + * @return void + */ + public function ajaxGetPlans($productID, $planID = 0) + { + $plans = $this->loadModel('productplan')->getPairs($productID); + die(html::select('plan', $plans, $planID)); + } +} diff --git a/module/product/lang/en.php b/module/product/lang/en.php index 67f9cf88f7..d3d3786d04 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -1,76 +1,76 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->product->common = 'Product'; -$lang->product->index = "Index"; -$lang->product->browse = "Browse"; -$lang->product->dynamic= "Dynamic"; -$lang->product->view = "Info"; -$lang->product->edit = "Edit"; -$lang->product->create = "Create"; -$lang->product->read = "Info"; -$lang->product->delete = "Delete"; -$lang->product->select = '--select product--'; - -$lang->product->plans = 'Plans'; -$lang->product->releases = 'Releases'; -$lang->product->roadmap = 'Roadmap'; -$lang->product->doc = 'Doc'; -$lang->product->project = 'Projects'; - -$lang->product->selectProduct = "Select product"; -$lang->product->saveButton = " Save (S) "; -$lang->product->confirmDelete = " Are you sure to delete this product?"; -$lang->product->ajaxGetProjects = "API: projects of product"; -$lang->product->ajaxGetPlans = "API: plans of product"; - -$lang->product->errorFormat = 'Error format.'; -$lang->product->errorEmptyName = 'Name can not be empty.'; -$lang->product->errorEmptyCode = 'Code can not be empty'; -$lang->product->errorNoProduct = 'No product in system yet.'; -$lang->product->accessDenied = 'Access to this product denined.'; - -$lang->product->id = 'ID'; -$lang->product->company = 'Company'; -$lang->product->name = 'Name'; -$lang->product->code = 'Code'; -$lang->product->order = 'Order'; -$lang->product->status = 'Status'; -$lang->product->desc = 'Desc'; -$lang->product->PO = 'Product owner'; -$lang->product->QM = 'Test manager'; -$lang->product->RM = 'Release manager'; -$lang->product->acl = 'Access limitation'; -$lang->product->whitelist = 'Whitelist'; - -$lang->product->moduleStory = 'By module'; -$lang->product->searchStory = 'By search'; -$lang->product->assignedToMe = 'To me'; -$lang->product->openedByMe = 'Opened by me'; -$lang->product->reviewedByMe = 'Reviewed by me'; -$lang->product->closedByMe = 'Closed by me'; -$lang->product->draftStory = 'Draft story'; -$lang->product->activeStory = 'Active story'; -$lang->product->changedStory = 'Changed story'; -$lang->product->closedStory = 'Closed story'; - -$lang->product->allStory = 'All story'; -$lang->product->allProduct = 'All products'; - -$lang->product->statusList[''] = ''; -$lang->product->statusList['normal'] = 'Normal'; -$lang->product->statusList['closed'] = 'Closed'; - -$lang->product->aclList['open'] = 'Default(Having product module prividge, can visit this product)'; -$lang->product->aclList['private'] = 'Private(Only project team members can visit)'; -$lang->product->aclList['custom'] = 'Whitelist(Project team members and who belongs to the whilelist groups can visit)'; - -$lang->product->storySummary = "Total %s stories in this page, estimate %s hours."; + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->product->common = 'Product'; +$lang->product->index = "Index"; +$lang->product->browse = "Browse"; +$lang->product->dynamic= "Dynamic"; +$lang->product->view = "Info"; +$lang->product->edit = "Edit"; +$lang->product->create = "Create"; +$lang->product->read = "Info"; +$lang->product->delete = "Delete"; +$lang->product->select = '--select product--'; + +$lang->product->plans = 'Plans'; +$lang->product->releases = 'Releases'; +$lang->product->roadmap = 'Roadmap'; +$lang->product->doc = 'Doc'; +$lang->product->project = 'Projects'; + +$lang->product->selectProduct = "Select product"; +$lang->product->saveButton = " Save (S) "; +$lang->product->confirmDelete = " Are you sure to delete this product?"; +$lang->product->ajaxGetProjects = "API: projects of product"; +$lang->product->ajaxGetPlans = "API: plans of product"; + +$lang->product->errorFormat = 'Error format.'; +$lang->product->errorEmptyName = 'Name can not be empty.'; +$lang->product->errorEmptyCode = 'Code can not be empty'; +$lang->product->errorNoProduct = 'No product in system yet.'; +$lang->product->accessDenied = 'Access to this product denined.'; + +$lang->product->id = 'ID'; +$lang->product->company = 'Company'; +$lang->product->name = 'Name'; +$lang->product->code = 'Code'; +$lang->product->order = 'Order'; +$lang->product->status = 'Status'; +$lang->product->desc = 'Desc'; +$lang->product->PO = 'Product owner'; +$lang->product->QM = 'Test manager'; +$lang->product->RM = 'Release manager'; +$lang->product->acl = 'Access limitation'; +$lang->product->whitelist = 'Whitelist'; + +$lang->product->moduleStory = 'By module'; +$lang->product->searchStory = 'By search'; +$lang->product->assignedToMe = 'To me'; +$lang->product->openedByMe = 'Opened by me'; +$lang->product->reviewedByMe = 'Reviewed by me'; +$lang->product->closedByMe = 'Closed by me'; +$lang->product->draftStory = 'Draft story'; +$lang->product->activeStory = 'Active story'; +$lang->product->changedStory = 'Changed story'; +$lang->product->closedStory = 'Closed story'; + +$lang->product->allStory = 'All story'; +$lang->product->allProduct = 'All products'; + +$lang->product->statusList[''] = ''; +$lang->product->statusList['normal'] = 'Normal'; +$lang->product->statusList['closed'] = 'Closed'; + +$lang->product->aclList['open'] = 'Default(Having product module prividge, can visit this product)'; +$lang->product->aclList['private'] = 'Private(Only project team members can visit)'; +$lang->product->aclList['custom'] = 'Whitelist(Project team members and who belongs to the whilelist groups can visit)'; + +$lang->product->storySummary = "Total %s stories in this page, estimate %s hours."; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 46766a65aa..13f0bfcac7 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -1,76 +1,76 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->product->common = '产品视图'; -$lang->product->index = "产品首页"; -$lang->product->browse = "浏览产品"; -$lang->product->dynamic= "动态"; -$lang->product->view = "产品信息"; -$lang->product->edit = "编辑产品"; -$lang->product->create = "新增产品"; -$lang->product->read = "产品详情"; -$lang->product->delete = "删除产品"; -$lang->product->select = '--请选择产品--'; - -$lang->product->plans = '计划数'; -$lang->product->releases = '发布数'; -$lang->product->roadmap = '路线图'; -$lang->product->doc = '文档列表'; -$lang->product->project = '项目列表'; - -$lang->product->selectProduct = "请选择产品"; -$lang->product->saveButton = " 保存 (S) "; -$lang->product->confirmDelete = " 您确定删除该产品吗?"; -$lang->product->ajaxGetProjects = "接口:项目列表"; -$lang->product->ajaxGetPlans = "接口:计划列表"; - -$lang->product->errorFormat = '产品数据格式不正确'; -$lang->product->errorEmptyName = '产品名称不能为空'; -$lang->product->errorEmptyCode = '产品代号不能为空'; -$lang->product->errorNoProduct = '还没有创建产品!'; -$lang->product->accessDenied = '您无权访问该产品'; - -$lang->product->id = '编号'; -$lang->product->company = '所属公司'; -$lang->product->name = '产品名称'; -$lang->product->code = '产品代号'; -$lang->product->order = '排序'; -$lang->product->status = '状态'; -$lang->product->desc = '产品描述'; -$lang->product->PO = '产品负责人'; -$lang->product->QM = '测试负责人'; -$lang->product->RM = '发布负责人'; -$lang->product->acl = '访问控制'; -$lang->product->whitelist = '分组白名单'; - -$lang->product->moduleStory = '按模块浏览'; -$lang->product->searchStory = '搜索'; -$lang->product->assignedToMe = '指派给我'; -$lang->product->openedByMe = '由我创建'; -$lang->product->reviewedByMe = '由我评审'; -$lang->product->closedByMe = '由我关闭'; -$lang->product->draftStory = '草稿'; -$lang->product->activeStory = '激活'; -$lang->product->changedStory = '已变更'; -$lang->product->closedStory = '已关闭'; - -$lang->product->allStory = '全部需求'; -$lang->product->allProduct = '全部产品'; - -$lang->product->statusList[''] = ''; -$lang->product->statusList['normal'] = '正常'; -$lang->product->statusList['closed'] = '结束'; - -$lang->product->aclList['open'] = '默认设置(有产品视图权限,即可访问)'; -$lang->product->aclList['private'] = '私有项目(只有项目团队成员才能访问)'; -$lang->product->aclList['custom'] = '自定义白名单(团队成员和白名单的成员可以访问)'; - -$lang->product->storySummary = "本页共 %s 个需求,预计 %s 个工时。"; + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->product->common = '产品视图'; +$lang->product->index = "产品首页"; +$lang->product->browse = "浏览产品"; +$lang->product->dynamic= "动态"; +$lang->product->view = "产品信息"; +$lang->product->edit = "编辑产品"; +$lang->product->create = "新增产品"; +$lang->product->read = "产品详情"; +$lang->product->delete = "删除产品"; +$lang->product->select = '--请选择产品--'; + +$lang->product->plans = '计划数'; +$lang->product->releases = '发布数'; +$lang->product->roadmap = '路线图'; +$lang->product->doc = '文档列表'; +$lang->product->project = '项目列表'; + +$lang->product->selectProduct = "请选择产品"; +$lang->product->saveButton = " 保存 (S) "; +$lang->product->confirmDelete = " 您确定删除该产品吗?"; +$lang->product->ajaxGetProjects = "接口:项目列表"; +$lang->product->ajaxGetPlans = "接口:计划列表"; + +$lang->product->errorFormat = '产品数据格式不正确'; +$lang->product->errorEmptyName = '产品名称不能为空'; +$lang->product->errorEmptyCode = '产品代号不能为空'; +$lang->product->errorNoProduct = '还没有创建产品!'; +$lang->product->accessDenied = '您无权访问该产品'; + +$lang->product->id = '编号'; +$lang->product->company = '所属公司'; +$lang->product->name = '产品名称'; +$lang->product->code = '产品代号'; +$lang->product->order = '排序'; +$lang->product->status = '状态'; +$lang->product->desc = '产品描述'; +$lang->product->PO = '产品负责人'; +$lang->product->QM = '测试负责人'; +$lang->product->RM = '发布负责人'; +$lang->product->acl = '访问控制'; +$lang->product->whitelist = '分组白名单'; + +$lang->product->moduleStory = '按模块浏览'; +$lang->product->searchStory = '搜索'; +$lang->product->assignedToMe = '指派给我'; +$lang->product->openedByMe = '由我创建'; +$lang->product->reviewedByMe = '由我评审'; +$lang->product->closedByMe = '由我关闭'; +$lang->product->draftStory = '草稿'; +$lang->product->activeStory = '激活'; +$lang->product->changedStory = '已变更'; +$lang->product->closedStory = '已关闭'; + +$lang->product->allStory = '全部需求'; +$lang->product->allProduct = '全部产品'; + +$lang->product->statusList[''] = ''; +$lang->product->statusList['normal'] = '正常'; +$lang->product->statusList['closed'] = '结束'; + +$lang->product->aclList['open'] = '默认设置(有产品视图权限,即可访问)'; +$lang->product->aclList['private'] = '私有项目(只有项目团队成员才能访问)'; +$lang->product->aclList['custom'] = '自定义白名单(团队成员和白名单的成员可以访问)'; + +$lang->product->storySummary = "本页共 %s 个需求,预计 %s 个工时。"; diff --git a/module/product/lang/zh-tw.php b/module/product/lang/zh-tw.php index d86c714b15..b4570031a3 100644 --- a/module/product/lang/zh-tw.php +++ b/module/product/lang/zh-tw.php @@ -1,76 +1,76 @@ - - * @package product - * @version $Id: zh-tw.php 2411 2011-12-07 05:14:21Z wwccss $ - * @link http://www.zentao.net - */ -$lang->product->common = '產品視圖'; -$lang->product->index = "產品首頁"; -$lang->product->browse = "瀏覽產品"; -$lang->product->dynamic= "動態"; -$lang->product->view = "產品信息"; -$lang->product->edit = "編輯產品"; -$lang->product->create = "新增產品"; -$lang->product->read = "產品詳情"; -$lang->product->delete = "刪除產品"; -$lang->product->select = '--請選擇產品--'; - -$lang->product->plans = '計劃數'; -$lang->product->releases = '發佈數'; -$lang->product->roadmap = '路線圖'; -$lang->product->doc = '文檔列表'; -$lang->product->project = '項目列表'; - -$lang->product->selectProduct = "請選擇產品"; -$lang->product->saveButton = " 保存 (S) "; -$lang->product->confirmDelete = " 您確定刪除該產品嗎?"; -$lang->product->ajaxGetProjects = "介面:項目列表"; -$lang->product->ajaxGetPlans = "介面:計劃列表"; - -$lang->product->errorFormat = '產品數據格式不正確'; -$lang->product->errorEmptyName = '產品名稱不能為空'; -$lang->product->errorEmptyCode = '產品代號不能為空'; -$lang->product->errorNoProduct = '還沒有創建產品!'; -$lang->product->accessDenied = '您無權訪問該產品'; - -$lang->product->id = '編號'; -$lang->product->company = '所屬公司'; -$lang->product->name = '產品名稱'; -$lang->product->code = '產品代號'; -$lang->product->order = '排序'; -$lang->product->status = '狀態'; -$lang->product->desc = '產品描述'; -$lang->product->PO = '產品負責人'; -$lang->product->QM = '測試負責人'; -$lang->product->RM = '發佈負責人'; -$lang->product->acl = '訪問控制'; -$lang->product->whitelist = '分組白名單'; - -$lang->product->moduleStory = '按模組瀏覽'; -$lang->product->searchStory = '搜索'; -$lang->product->assignedToMe = '指派給我'; -$lang->product->openedByMe = '由我創建'; -$lang->product->reviewedByMe = '由我評審'; -$lang->product->closedByMe = '由我關閉'; -$lang->product->draftStory = '草稿'; -$lang->product->activeStory = '激活'; -$lang->product->changedStory = '已變更'; -$lang->product->closedStory = '已關閉'; - -$lang->product->allStory = '全部需求'; -$lang->product->allProduct = '全部產品'; - -$lang->product->statusList[''] = ''; -$lang->product->statusList['normal'] = '正常'; -$lang->product->statusList['closed'] = '結束'; - -$lang->product->aclList['open'] = '預設設置(有產品視圖權限,即可訪問)'; -$lang->product->aclList['private'] = '私有項目(只有項目團隊成員才能訪問)'; -$lang->product->aclList['custom'] = '自定義白名單(團隊成員和白名單的成員可以訪問)'; - -$lang->product->storySummary = "本頁共 %s 個需求,預計 %s 個工時。"; + + * @package product + * @version $Id: zh-tw.php 2411 2011-12-07 05:14:21Z wwccss $ + * @link http://www.zentao.net + */ +$lang->product->common = '產品視圖'; +$lang->product->index = "產品首頁"; +$lang->product->browse = "瀏覽產品"; +$lang->product->dynamic= "動態"; +$lang->product->view = "產品信息"; +$lang->product->edit = "編輯產品"; +$lang->product->create = "新增產品"; +$lang->product->read = "產品詳情"; +$lang->product->delete = "刪除產品"; +$lang->product->select = '--請選擇產品--'; + +$lang->product->plans = '計劃數'; +$lang->product->releases = '發佈數'; +$lang->product->roadmap = '路線圖'; +$lang->product->doc = '文檔列表'; +$lang->product->project = '項目列表'; + +$lang->product->selectProduct = "請選擇產品"; +$lang->product->saveButton = " 保存 (S) "; +$lang->product->confirmDelete = " 您確定刪除該產品嗎?"; +$lang->product->ajaxGetProjects = "介面:項目列表"; +$lang->product->ajaxGetPlans = "介面:計劃列表"; + +$lang->product->errorFormat = '產品數據格式不正確'; +$lang->product->errorEmptyName = '產品名稱不能為空'; +$lang->product->errorEmptyCode = '產品代號不能為空'; +$lang->product->errorNoProduct = '還沒有創建產品!'; +$lang->product->accessDenied = '您無權訪問該產品'; + +$lang->product->id = '編號'; +$lang->product->company = '所屬公司'; +$lang->product->name = '產品名稱'; +$lang->product->code = '產品代號'; +$lang->product->order = '排序'; +$lang->product->status = '狀態'; +$lang->product->desc = '產品描述'; +$lang->product->PO = '產品負責人'; +$lang->product->QM = '測試負責人'; +$lang->product->RM = '發佈負責人'; +$lang->product->acl = '訪問控制'; +$lang->product->whitelist = '分組白名單'; + +$lang->product->moduleStory = '按模組瀏覽'; +$lang->product->searchStory = '搜索'; +$lang->product->assignedToMe = '指派給我'; +$lang->product->openedByMe = '由我創建'; +$lang->product->reviewedByMe = '由我評審'; +$lang->product->closedByMe = '由我關閉'; +$lang->product->draftStory = '草稿'; +$lang->product->activeStory = '激活'; +$lang->product->changedStory = '已變更'; +$lang->product->closedStory = '已關閉'; + +$lang->product->allStory = '全部需求'; +$lang->product->allProduct = '全部產品'; + +$lang->product->statusList[''] = ''; +$lang->product->statusList['normal'] = '正常'; +$lang->product->statusList['closed'] = '結束'; + +$lang->product->aclList['open'] = '預設設置(有產品視圖權限,即可訪問)'; +$lang->product->aclList['private'] = '私有項目(只有項目團隊成員才能訪問)'; +$lang->product->aclList['custom'] = '自定義白名單(團隊成員和白名單的成員可以訪問)'; + +$lang->product->storySummary = "本頁共 %s 個需求,預計 %s 個工時。"; diff --git a/module/product/model.php b/module/product/model.php index c8685ed2c2..c17d9d26c3 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -1,427 +1,427 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> -checkPriv($this->getById($productID))) - { - echo(js::alert($this->lang->product->accessDenied)); - die(js::locate('back')); - } - - $currentModule = $this->app->getModuleName(); - $currentMethod = $this->app->getMethodName(); - - /* init currentModule and currentMethod for report*/ - if($currentModule == 'story') $currentModule = 'product'; - if($currentMethod == 'report') $currentMethod = 'browse'; - - $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra); - foreach($this->lang->product->menu as $key => $menu) - { - $replace = $key == 'list' ? $selectHtml . $this->lang->arrow : $productID; - common::setMenuVars($this->lang->product->menu, $key, $replace); - } - } - - /** - * Create the select code of products. - * - * @param array $products - * @param int $productID - * @param string $currentModule - * @param string $currentMethod - * @param string $extra - * @access public - * @return string - */ - public function select($products, $productID, $currentModule, $currentMethod, $extra = '') - { - /** - * 1. if user selected by mouse, reload it. - * 2. if the user select by keyboard, save the event.keyCode, thus the switchProduct() can judge whether reload or not. - * 3. if user press enter key in the select, reload it. - * 4. if user click the go button, reload it. - * */ - $switchCode = "switchProduct($('#productID').val(), '$currentModule', '$currentMethod', '$extra');"; - $onchange = "onchange=\"$switchCode\""; - $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; - $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; - $selectHtml = html::select('productID', $products, $productID, "tabindex=2 $onchange $onkeypress"); - $selectHtml .= html::commonButton($this->lang->go, "id='productSwitcher' tabindex=3 $onclick"); - return $selectHtml; - } - - /** - * Save the product id user last visited to session. - * - * @param int $productID - * @param array $products - * @access public - * @return int - */ - public function saveState($productID, $products) - { - if($productID > 0) $this->session->set('product', (int)$productID); - if($productID == 0 and $this->cookie->lastProduct) $this->session->set('product', (int)$this->cookie->lastProduct); - if($productID == 0 and $this->session->product == '') $this->session->set('product', key($products)); - if(!isset($products[$this->session->product])) $this->session->set('product', key($products)); - return $this->session->product; - } - - /** - * Check privilege. - * - * @param int $product - * @access public - * @return bool - */ - public function checkPriv($product) - { - /* Is admin? */ - $account = ',' . $this->app->user->account . ','; - if(strpos($this->app->company->admins, $account) !== false) return true; - - /* Product is open, return true. */ - if($product->acl == 'open') return true; - - /* Get team members. */ - $teamMembers = $this->getTeamMemberPairs($product); - - /* Private. */ - if($product->acl == 'private') - { - return isset($teamMembers[$this->app->user->account]); - } - - /* Custom, check groups. */ - if($product->acl == 'custom') - { - if(isset($teamMembers[$this->app->user->account])) return true; - $userGroups = $this->loadModel('user')->getGroups($this->app->user->account); - $productGroups = explode(',', $product->whitelist); - foreach($userGroups as $groupID) - { - if(in_array($groupID, $productGroups)) return true; - } - return false; - } - } - - /** - * Get product by id. - * - * @param int $productID - * @access public - * @return object - */ - public function getById($productID) - { - return $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - } - - /** - * Get products. - * - * @param string $status - * @param int $limit - * @access public - * @return array - */ - public function getList($status = 'all', $limit = 0) - { - return $this->dao->select('*')->from(TABLE_PRODUCT) - ->where('deleted')->eq(0) - ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() - ->beginIF($limit > 0)->limit($limit)->fi() - ->fetchAll('id'); - } - - /** - * Get product pairs. - * - * @param string $mode - * @return array - */ - public function getPairs($mode = '') - { - $orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'code'; - $mode .= $this->cookie->productMode; - $products = $this->dao->select('*') - ->from(TABLE_PRODUCT) - ->where('deleted')->eq(0) - ->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi() - ->orderBy($orderBy) - ->fetchAll(); - $pairs = array(); - foreach($products as $product) - { - if($this->checkPriv($product)) - { - - if(strpos($mode, 'nocode') === false and $product->code) - { - $firstChar = strtoupper(substr($product->code, 0, 1)); - if(ord($firstChar) < 127) $product->name = $firstChar . ':' . $product->name; - } - - $pairs[$product->id] = $product->name; - } - } - return $pairs; - } - - /** - * Get products by project. - * - * @param int $projectID - * @access public - * @return array - */ - public function getProductsByProject($projectID) - { - return $this->dao->select('t1.product, t2.name') - ->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t1.project')->eq($projectID) - ->fetchPairs(); - } - - /** - * Get grouped products. - * - * @access public - * @return void - */ - public function getStatusGroups() - { - $products = $this->dao->select('id, name, status')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchGroup('status'); - } - - /** - * Create a product. - * - * @access public - * @return int - */ - public function create() - { - $product = fixer::input('post') - ->stripTags('name,code') - ->setIF($this->post->acl != 'custom', 'whitelist', '') - ->setDefault('status', 'normal') - ->setDefault('createdBy', $this->app->user->account) - ->setDefault('createdDate', helper::now()) - ->join('whitelist', ',') - ->get(); - $this->dao->insert(TABLE_PRODUCT) - ->data($product) - ->autoCheck() - ->batchCheck('name,code', 'notempty') - ->check('name', 'unique') - ->check('code', 'unique') - ->exec(); - return $this->dao->lastInsertID(); - } - - /** - * Update a product. - * - * @param int $productID - * @access public - * @return array - */ - public function update($productID) - { - $productID = (int)$productID; - $oldProduct = $this->getById($productID); - $product = fixer::input('post') - ->stripTags('name,code') - ->setIF($this->post->acl != 'custom', 'whitelist', '') - ->join('whitelist', ',') - ->get(); - $this->dao->update(TABLE_PRODUCT) - ->data($product) - ->autoCheck() - ->batchCheck('name,code', 'notempty') - ->check('name', 'unique', "id != $productID") - ->check('code', 'unique', "id != $productID") - ->where('id')->eq($productID) - ->exec(); - if(!dao::isError()) return common::createChanges($oldProduct, $product); - } - - /** - * Get projects of a product in pairs. - * - * @param int $productID - * @param string $param all|nodeleted - * @access public - * @return array - */ - public function getProjectPairs($productID, $param = 'all') - { - $projects = array(); - $datas = $this->dao->select('t2.id, t2.name, t2.deleted') - ->from(TABLE_PROJECTPRODUCT)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.product')->eq((int)$productID) - ->orderBy('t1.project desc') - ->fetchAll(); - - foreach($datas as $data) - { - if($param == 'nodeleted' and $data->deleted) continue; - $projects[$data->id] = $data->name; - } - $projects = array('' => '') + $projects; - return $projects; - } - - /** - * Get roadmap of a proejct - * - * @param int $productID - * @access public - * @return array - */ - public function getRoadmap($productID) - { - $plans = $this->loadModel('productplan')->getList($productID); - $releases = $this->loadModel('release')->getList($productID); - $roadmap = array(); - if(is_array($releases)) $releases = array_reverse($releases); - foreach($releases as $release) - { - $year = substr($release->date, 0, 4); - $roadmap[$year][] = $release; - } - foreach($plans as $plan) - { - if($plan->end != '0000-00-00' and strtotime($plan->end) - time() <= 0) continue; - $year = substr($plan->end, 0, 4); - $roadmap[$year][] = $plan; - } - - ksort($roadmap); - return $roadmap; - } - - /** - * Get team members of a product from projects. - * - * @param object $product - * @access public - * @return array - */ - public function getTeamMemberPairs($product) - { - $members[$product->PO] = $product->PO; - $members[$product->QM] = $product->QM; - $members[$product->RM] = $product->RM; - $members[$product->createdBy] = $product->createdBy; - - $projects = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($product->id)->fetchPairs(); - if(!$projects) return $members; - $projectTeams = $this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs(); - return array_merge($members, $projectTeams); - } - - /** - * Get product stats. - * - * @access public - * @return array - */ - public function getStats() - { - $this->loadModel('report'); - $this->loadModel('story'); - - $products = $this->getList(',normal'); - $stats = array(); - - $stories = $this->dao->select('product, status, count(status) AS count') - ->from(TABLE_STORY) - ->where('deleted')->eq(0) - ->andWhere('product')->in(array_keys($products)) - ->groupBy('product, status') - ->fetchGroup('product', 'status'); - - /* Padding the stories to sure all products have records. */ - $emptyStory = array_keys($this->lang->story->statusList); - foreach(array_keys($products) as $productID) - { - if(!isset($stories[$productID])) $stories[$productID] = $emptyStory; - } - - /* Padding the stories to sure all status have records. */ - foreach($stories as $key => $story) - { - foreach(array_keys($this->lang->story->statusList) as $status) - { - $story[$status] = isset($story[$status]) ? $story[$status]->count : 0; - } - $stories[$key] = $story; - } - - $plans = $this->dao->select('product, count(*) AS count') - ->from(TABLE_PRODUCTPLAN) - ->where('deleted')->eq(0) - ->andWhere('product')->in(array_keys($products)) - ->andWhere('end')->gt(helper::now()) - ->groupBy('product') - ->fetchPairs(); - - $releases = $this->dao->select('product, count(*) AS count') - ->from(TABLE_RELEASE) - ->where('deleted')->eq(0) - ->andWhere('product')->in(array_keys($products)) - ->groupBy('product') - ->fetchPairs(); - - foreach($products as $key => $product) - { - if($this->checkPriv($product)) - { - if($product->status != 'closed') - { - $product->stories = $stories[$product->id]; - $product->plans = isset($plans[$product->id]) ? $plans[$product->id] : 0; - $product->releases= isset($releases[$product->id]) ? $releases[$product->id] : 0; - - $stats[] = $product; - } - } - else - { - unset($products[$key]); - } - } - - return $stats; - } -} + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> +checkPriv($this->getById($productID))) + { + echo(js::alert($this->lang->product->accessDenied)); + die(js::locate('back')); + } + + $currentModule = $this->app->getModuleName(); + $currentMethod = $this->app->getMethodName(); + + /* init currentModule and currentMethod for report*/ + if($currentModule == 'story') $currentModule = 'product'; + if($currentMethod == 'report') $currentMethod = 'browse'; + + $selectHtml = $this->select($products, $productID, $currentModule, $currentMethod, $extra); + foreach($this->lang->product->menu as $key => $menu) + { + $replace = $key == 'list' ? $selectHtml . $this->lang->arrow : $productID; + common::setMenuVars($this->lang->product->menu, $key, $replace); + } + } + + /** + * Create the select code of products. + * + * @param array $products + * @param int $productID + * @param string $currentModule + * @param string $currentMethod + * @param string $extra + * @access public + * @return string + */ + public function select($products, $productID, $currentModule, $currentMethod, $extra = '') + { + /** + * 1. if user selected by mouse, reload it. + * 2. if the user select by keyboard, save the event.keyCode, thus the switchProduct() can judge whether reload or not. + * 3. if user press enter key in the select, reload it. + * 4. if user click the go button, reload it. + * */ + $switchCode = "switchProduct($('#productID').val(), '$currentModule', '$currentMethod', '$extra');"; + $onchange = "onchange=\"$switchCode\""; + $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; + $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; + $selectHtml = html::select('productID', $products, $productID, "tabindex=2 $onchange $onkeypress"); + $selectHtml .= html::commonButton($this->lang->go, "id='productSwitcher' tabindex=3 $onclick"); + return $selectHtml; + } + + /** + * Save the product id user last visited to session. + * + * @param int $productID + * @param array $products + * @access public + * @return int + */ + public function saveState($productID, $products) + { + if($productID > 0) $this->session->set('product', (int)$productID); + if($productID == 0 and $this->cookie->lastProduct) $this->session->set('product', (int)$this->cookie->lastProduct); + if($productID == 0 and $this->session->product == '') $this->session->set('product', key($products)); + if(!isset($products[$this->session->product])) $this->session->set('product', key($products)); + return $this->session->product; + } + + /** + * Check privilege. + * + * @param int $product + * @access public + * @return bool + */ + public function checkPriv($product) + { + /* Is admin? */ + $account = ',' . $this->app->user->account . ','; + if(strpos($this->app->company->admins, $account) !== false) return true; + + /* Product is open, return true. */ + if($product->acl == 'open') return true; + + /* Get team members. */ + $teamMembers = $this->getTeamMemberPairs($product); + + /* Private. */ + if($product->acl == 'private') + { + return isset($teamMembers[$this->app->user->account]); + } + + /* Custom, check groups. */ + if($product->acl == 'custom') + { + if(isset($teamMembers[$this->app->user->account])) return true; + $userGroups = $this->loadModel('user')->getGroups($this->app->user->account); + $productGroups = explode(',', $product->whitelist); + foreach($userGroups as $groupID) + { + if(in_array($groupID, $productGroups)) return true; + } + return false; + } + } + + /** + * Get product by id. + * + * @param int $productID + * @access public + * @return object + */ + public function getById($productID) + { + return $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); + } + + /** + * Get products. + * + * @param string $status + * @param int $limit + * @access public + * @return array + */ + public function getList($status = 'all', $limit = 0) + { + return $this->dao->select('*')->from(TABLE_PRODUCT) + ->where('deleted')->eq(0) + ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() + ->beginIF($limit > 0)->limit($limit)->fi() + ->fetchAll('id'); + } + + /** + * Get product pairs. + * + * @param string $mode + * @return array + */ + public function getPairs($mode = '') + { + $orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'code'; + $mode .= $this->cookie->productMode; + $products = $this->dao->select('*') + ->from(TABLE_PRODUCT) + ->where('deleted')->eq(0) + ->beginIF(strpos($mode, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi() + ->orderBy($orderBy) + ->fetchAll(); + $pairs = array(); + foreach($products as $product) + { + if($this->checkPriv($product)) + { + + if(strpos($mode, 'nocode') === false and $product->code) + { + $firstChar = strtoupper(substr($product->code, 0, 1)); + if(ord($firstChar) < 127) $product->name = $firstChar . ':' . $product->name; + } + + $pairs[$product->id] = $product->name; + } + } + return $pairs; + } + + /** + * Get products by project. + * + * @param int $projectID + * @access public + * @return array + */ + public function getProductsByProject($projectID) + { + return $this->dao->select('t1.product, t2.name') + ->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t1.project')->eq($projectID) + ->fetchPairs(); + } + + /** + * Get grouped products. + * + * @access public + * @return void + */ + public function getStatusGroups() + { + $products = $this->dao->select('id, name, status')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchGroup('status'); + } + + /** + * Create a product. + * + * @access public + * @return int + */ + public function create() + { + $product = fixer::input('post') + ->stripTags('name,code') + ->setIF($this->post->acl != 'custom', 'whitelist', '') + ->setDefault('status', 'normal') + ->setDefault('createdBy', $this->app->user->account) + ->setDefault('createdDate', helper::now()) + ->join('whitelist', ',') + ->get(); + $this->dao->insert(TABLE_PRODUCT) + ->data($product) + ->autoCheck() + ->batchCheck('name,code', 'notempty') + ->check('name', 'unique') + ->check('code', 'unique') + ->exec(); + return $this->dao->lastInsertID(); + } + + /** + * Update a product. + * + * @param int $productID + * @access public + * @return array + */ + public function update($productID) + { + $productID = (int)$productID; + $oldProduct = $this->getById($productID); + $product = fixer::input('post') + ->stripTags('name,code') + ->setIF($this->post->acl != 'custom', 'whitelist', '') + ->join('whitelist', ',') + ->get(); + $this->dao->update(TABLE_PRODUCT) + ->data($product) + ->autoCheck() + ->batchCheck('name,code', 'notempty') + ->check('name', 'unique', "id != $productID") + ->check('code', 'unique', "id != $productID") + ->where('id')->eq($productID) + ->exec(); + if(!dao::isError()) return common::createChanges($oldProduct, $product); + } + + /** + * Get projects of a product in pairs. + * + * @param int $productID + * @param string $param all|nodeleted + * @access public + * @return array + */ + public function getProjectPairs($productID, $param = 'all') + { + $projects = array(); + $datas = $this->dao->select('t2.id, t2.name, t2.deleted') + ->from(TABLE_PROJECTPRODUCT)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.product')->eq((int)$productID) + ->orderBy('t1.project desc') + ->fetchAll(); + + foreach($datas as $data) + { + if($param == 'nodeleted' and $data->deleted) continue; + $projects[$data->id] = $data->name; + } + $projects = array('' => '') + $projects; + return $projects; + } + + /** + * Get roadmap of a proejct + * + * @param int $productID + * @access public + * @return array + */ + public function getRoadmap($productID) + { + $plans = $this->loadModel('productplan')->getList($productID); + $releases = $this->loadModel('release')->getList($productID); + $roadmap = array(); + if(is_array($releases)) $releases = array_reverse($releases); + foreach($releases as $release) + { + $year = substr($release->date, 0, 4); + $roadmap[$year][] = $release; + } + foreach($plans as $plan) + { + if($plan->end != '0000-00-00' and strtotime($plan->end) - time() <= 0) continue; + $year = substr($plan->end, 0, 4); + $roadmap[$year][] = $plan; + } + + ksort($roadmap); + return $roadmap; + } + + /** + * Get team members of a product from projects. + * + * @param object $product + * @access public + * @return array + */ + public function getTeamMemberPairs($product) + { + $members[$product->PO] = $product->PO; + $members[$product->QM] = $product->QM; + $members[$product->RM] = $product->RM; + $members[$product->createdBy] = $product->createdBy; + + $projects = $this->dao->select('project')->from(TABLE_PROJECTPRODUCT)->where('product')->eq($product->id)->fetchPairs(); + if(!$projects) return $members; + $projectTeams = $this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs(); + return array_merge($members, $projectTeams); + } + + /** + * Get product stats. + * + * @access public + * @return array + */ + public function getStats() + { + $this->loadModel('report'); + $this->loadModel('story'); + + $products = $this->getList(',normal'); + $stats = array(); + + $stories = $this->dao->select('product, status, count(status) AS count') + ->from(TABLE_STORY) + ->where('deleted')->eq(0) + ->andWhere('product')->in(array_keys($products)) + ->groupBy('product, status') + ->fetchGroup('product', 'status'); + + /* Padding the stories to sure all products have records. */ + $emptyStory = array_keys($this->lang->story->statusList); + foreach(array_keys($products) as $productID) + { + if(!isset($stories[$productID])) $stories[$productID] = $emptyStory; + } + + /* Padding the stories to sure all status have records. */ + foreach($stories as $key => $story) + { + foreach(array_keys($this->lang->story->statusList) as $status) + { + $story[$status] = isset($story[$status]) ? $story[$status]->count : 0; + } + $stories[$key] = $story; + } + + $plans = $this->dao->select('product, count(*) AS count') + ->from(TABLE_PRODUCTPLAN) + ->where('deleted')->eq(0) + ->andWhere('product')->in(array_keys($products)) + ->andWhere('end')->gt(helper::now()) + ->groupBy('product') + ->fetchPairs(); + + $releases = $this->dao->select('product, count(*) AS count') + ->from(TABLE_RELEASE) + ->where('deleted')->eq(0) + ->andWhere('product')->in(array_keys($products)) + ->groupBy('product') + ->fetchPairs(); + + foreach($products as $key => $product) + { + if($this->checkPriv($product)) + { + if($product->status != 'closed') + { + $product->stories = $stories[$product->id]; + $product->plans = isset($plans[$product->id]) ? $plans[$product->id] : 0; + $product->releases= isset($releases[$product->id]) ? $releases[$product->id] : 0; + + $stats[] = $product; + } + } + else + { + unset($products[$key]); + } + } + + return $stats; + } +} diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index bb8fb3b7c2..558d492b01 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -1,120 +1,120 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          -
          - product->moduleStory;?> - inlink('browse', "productID=$productID&browseType=assignedtome"), $lang->product->assignedToMe);?> - inlink('browse', "productID=$productID&browseType=openedByMe"), $lang->product->openedByMe);?> - inlink('browse', "productID=$productID&browseType=reviewedByMe"), $lang->product->reviewedByMe);?> - inlink('browse', "productID=$productID&browseType=closedByMe"), $lang->product->closedByMe);?> - inlink('browse', "productID=$productID&browseType=draftStory"), $lang->product->draftStory);?> - inlink('browse', "productID=$productID&browseType=activeStory"), $lang->product->activeStory);?> - inlink('browse', "productID=$productID&browseType=changedStory"), $lang->product->changedStory);?> - inlink('browse', "productID=$productID&browseType=closedStory"), $lang->product->closedStory);?> - inlink('browse', "productID=$productID&browseType=allStory"), $lang->product->allStory);?> - product->searchStory;?> -
          -
          - export, '', 'class="export"'); ?> - story->report->common); ?> - createLink('story', 'batchCreate', "productID=$productID&moduleID=$moduleID"), $lang->story->batchCreate); ?> - createLink('story', 'create', "productID=$productID&moduleID=$moduleID"), $lang->story->create); ?> -
          -
          -
          '>
          - - - - - - -
          -
          -
          - -
          - createLink('product', 'edit', "productID=$productID"), $lang->edit);?> - createLink('product', 'delete', "productID=$productID&confirm=no"), $lang->delete, 'hiddenwin');?> - createLink('tree', 'browse', "rootID=$productID&view=story"), $lang->tree->manage);?> -
          -
          -
          - - - - recTotal}&recPerPage={$pager->recPerPage}";?> - - - - - - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - $totalEstimate += $story->estimate; - $canView = common::hasPriv('story', 'view'); - ?> - - - - - - - - - - - - - - - - - - - - -
          idAB);?>priAB);?>story->title);?>story->planAB);?>story->source);?>openedByAB);?>assignedToAB);?>story->estimateAB);?>statusAB);?>story->stageAB);?>actions;?>
          id)); else printf('%03d', $story->id);?>pri;?>title);?>planTitle;?>story->sourceList[$story->source];?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - id}"; - if(!common::printLink('testcase', 'create', "productID=$story->product&module=0&from=¶m=0&$vars", $lang->story->createCase)) echo $lang->story->createCase . ' '; - if(!($story->status != 'closed' and common::printLink('story', 'change', $vars, $lang->story->change))) echo $lang->story->change . ' '; - if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', $vars, $lang->story->review))) echo $lang->story->review . ' '; - if(!common::printLink('story', 'edit', $vars, $lang->edit)) echo $lang->edit; - ?> -
          -
          product->storySummary, count($stories), $totalEstimate);?>
          - show();?> -
          -
          - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          +
          + product->moduleStory;?> + inlink('browse', "productID=$productID&browseType=assignedtome"), $lang->product->assignedToMe);?> + inlink('browse', "productID=$productID&browseType=openedByMe"), $lang->product->openedByMe);?> + inlink('browse', "productID=$productID&browseType=reviewedByMe"), $lang->product->reviewedByMe);?> + inlink('browse', "productID=$productID&browseType=closedByMe"), $lang->product->closedByMe);?> + inlink('browse', "productID=$productID&browseType=draftStory"), $lang->product->draftStory);?> + inlink('browse', "productID=$productID&browseType=activeStory"), $lang->product->activeStory);?> + inlink('browse', "productID=$productID&browseType=changedStory"), $lang->product->changedStory);?> + inlink('browse', "productID=$productID&browseType=closedStory"), $lang->product->closedStory);?> + inlink('browse', "productID=$productID&browseType=allStory"), $lang->product->allStory);?> + product->searchStory;?> +
          +
          + export, '', 'class="export"'); ?> + story->report->common); ?> + createLink('story', 'batchCreate', "productID=$productID&moduleID=$moduleID"), $lang->story->batchCreate); ?> + createLink('story', 'create', "productID=$productID&moduleID=$moduleID"), $lang->story->create); ?> +
          +
          +
          '>
          + + + + + + +
          +
          +
          + +
          + createLink('product', 'edit', "productID=$productID"), $lang->edit);?> + createLink('product', 'delete', "productID=$productID&confirm=no"), $lang->delete, 'hiddenwin');?> + createLink('tree', 'browse', "rootID=$productID&view=story"), $lang->tree->manage);?> +
          +
          +
          + + + + recTotal}&recPerPage={$pager->recPerPage}";?> + + + + + + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id"); + $totalEstimate += $story->estimate; + $canView = common::hasPriv('story', 'view'); + ?> + + + + + + + + + + + + + + + + + + + + +
          idAB);?>priAB);?>story->title);?>story->planAB);?>story->source);?>openedByAB);?>assignedToAB);?>story->estimateAB);?>statusAB);?>story->stageAB);?>actions;?>
          id)); else printf('%03d', $story->id);?>pri;?>title);?>planTitle;?>story->sourceList[$story->source];?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + id}"; + if(!common::printLink('testcase', 'create', "productID=$story->product&module=0&from=¶m=0&$vars", $lang->story->createCase)) echo $lang->story->createCase . ' '; + if(!($story->status != 'closed' and common::printLink('story', 'change', $vars, $lang->story->change))) echo $lang->story->change . ' '; + if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', $vars, $lang->story->review))) echo $lang->story->review . ' '; + if(!common::printLink('story', 'edit', $vars, $lang->edit)) echo $lang->edit; + ?> +
          +
          product->storySummary, count($stories), $totalEstimate);?>
          + show();?> +
          +
          + + diff --git a/module/product/view/create.html.php b/module/product/view/create.html.php index d3a4b318e8..a3657994b3 100644 --- a/module/product/view/create.html.php +++ b/module/product/view/create.html.php @@ -1,53 +1,53 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          product->create;?>
          product->name;?>
          product->code;?>
          product->PO;?>app->user->account, "class='select-3'");?>
          product->QM;?>app->user->account, "class='select-3'");?>
          product->RM;?>app->user->account, "class='select-3'");?>
          product->desc;?>
          product->acl;?>product->aclList, 'open', "onclick='setWhite(this.value);'"));?>
          -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          product->create;?>
          product->name;?>
          product->code;?>
          product->PO;?>app->user->account, "class='select-3'");?>
          product->QM;?>app->user->account, "class='select-3'");?>
          product->RM;?>app->user->account, "class='select-3'");?>
          product->desc;?>
          product->acl;?>product->aclList, 'open', "onclick='setWhite(this.value);'"));?>
          +
          + diff --git a/module/product/view/doc.html.php b/module/product/view/doc.html.php index bf53e55f4d..0c9f54e622 100644 --- a/module/product/view/doc.html.php +++ b/module/product/view/doc.html.php @@ -1,54 +1,54 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - $doc):?> - createLink('doc', 'view', "docID=$doc->id"); - $canView = common::hasPriv('doc', 'view'); - ?> - - - - - - - - - - -
          id}&projectID=0&from=product", $lang->doc->create);?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module;?>title);?>addedBy];?>addedDate;?> - id}"; - if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; - if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; - ?> -
          -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + $doc):?> + createLink('doc', 'view', "docID=$doc->id"); + $canView = common::hasPriv('doc', 'view'); + ?> + + + + + + + + + + +
          id}&projectID=0&from=product", $lang->doc->create);?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module;?>title);?>addedBy];?>addedDate;?> + id}"; + if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; + if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; + ?> +
          +
          + diff --git a/module/product/view/dynamic.html.php b/module/product/view/dynamic.html.php index 89ece16cf4..ad15b8f041 100755 --- a/module/product/view/dynamic.html.php +++ b/module/product/view/dynamic.html.php @@ -1,56 +1,56 @@ -dynamic view file of dashboard module of ZenTaoPMS. - * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) - * @license LGPL (http://www.gnu.org/licenses/lgpl.html) - * @author Chunsheng Wang - * @package dashboard - * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ - * @link http://www.zentao.net - */ -?> - - -
          - ' . html::a(inlink('dynamic', "productID=$productID&type=today"), $lang->action->dynamic->today) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=yesterday"), $lang->action->dynamic->yesterday) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=thisweek"), $lang->action->dynamic->thisWeek) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=lastweek"), $lang->action->dynamic->lastWeek) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=thismonth"), $lang->action->dynamic->thisMonth) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; - echo '' . html::a(inlink('dynamic', "productID=$productID&type=all"), $lang->action->dynamic->all) . ''; - echo "" . html::select('account', $users, $account, "onchange=changeUser(this.value,$productID)") . ''; - ?> -
          - - - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - -
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @license LGPL (http://www.gnu.org/licenses/lgpl.html) + * @author Chunsheng Wang + * @package dashboard + * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ + * @link http://www.zentao.net + */ +?> + + +
          + ' . html::a(inlink('dynamic', "productID=$productID&type=today"), $lang->action->dynamic->today) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=yesterday"), $lang->action->dynamic->yesterday) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=thisweek"), $lang->action->dynamic->thisWeek) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=lastweek"), $lang->action->dynamic->lastWeek) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=thismonth"), $lang->action->dynamic->thisMonth) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; + echo '' . html::a(inlink('dynamic', "productID=$productID&type=all"), $lang->action->dynamic->all) . ''; + echo "" . html::select('account', $users, $account, "onchange=changeUser(this.value,$productID)") . ''; + ?> +
          + + + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + +
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          + + diff --git a/module/product/view/edit.html.php b/module/product/view/edit.html.php index 3b7a085326..73b107f2d8 100644 --- a/module/product/view/edit.html.php +++ b/module/product/view/edit.html.php @@ -1,57 +1,57 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - acl != 'custom') echo "class='hidden'";?>> - - - - -
          product->edit;?>
          product->name;?>name, "class='text-3'");?>
          product->code;?>code, "class='text-3'");?>
          product->PO;?>PO, "class='select-3'");?>
          product->QM;?>QM, "class='select-3'");?>
          product->RM;?>RM, "class='select-3'");?>
          product->status;?>product->statusList, $product->status, "class='select-3'");?>
          product->desc;?>desc), "rows='8' class='area-1'");?>
          product->acl;?>product->aclList, $product->acl, "onclick='setWhite(this.value);'"));?>
          product->whitelist;?>whitelist);?>
          -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + acl != 'custom') echo "class='hidden'";?>> + + + + +
          product->edit;?>
          product->name;?>name, "class='text-3'");?>
          product->code;?>code, "class='text-3'");?>
          product->PO;?>PO, "class='select-3'");?>
          product->QM;?>QM, "class='select-3'");?>
          product->RM;?>RM, "class='select-3'");?>
          product->status;?>product->statusList, $product->status, "class='select-3'");?>
          product->desc;?>desc), "rows='8' class='area-1'");?>
          product->acl;?>product->aclList, $product->acl, "onclick='setWhite(this.value);'"));?>
          product->whitelist;?>whitelist);?>
          +
          + diff --git a/module/product/view/index.html.php b/module/product/view/index.html.php index 4204890713..8550e86617 100644 --- a/module/product/view/index.html.php +++ b/module/product/view/index.html.php @@ -1,54 +1,54 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - -
          - - - - - - -
          my->home->products;?>
          - createLink('product', 'create'); - printf($lang->my->home->noProductsTip, $productLink); - ?> -
          - - - - - - - - - - - - - - - - - - - - - - -
          product->name;?>story->statusList['active'] . $lang->story->common;?>story->statusList['changed'] . $lang->story->common;?>story->statusList['draft'] . $lang->story->common;?>story->statusList['closed'] . $lang->story->common;?>product->plans;?>product->releases;?>
          createLink('product', 'view', 'product=' . $product->id), $product->name);?>stories['active']?>stories['changed']?>stories['draft']?>stories['closed']?>plans?>releases?>
          -
          - - - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + +
          + + + + + + +
          my->home->products;?>
          + createLink('product', 'create'); + printf($lang->my->home->noProductsTip, $productLink); + ?> +
          + + + + + + + + + + + + + + + + + + + + + + +
          product->name;?>story->statusList['active'] . $lang->story->common;?>story->statusList['changed'] . $lang->story->common;?>story->statusList['draft'] . $lang->story->common;?>story->statusList['closed'] . $lang->story->common;?>product->plans;?>product->releases;?>
          createLink('product', 'view', 'product=' . $product->id), $product->name);?>stories['active']?>stories['changed']?>stories['draft']?>stories['closed']?>plans?>releases?>
          +
          + + + diff --git a/module/product/view/project.html.php b/module/product/view/project.html.php index d6a57066fa..006d5088f1 100644 --- a/module/product/view/project.html.php +++ b/module/product/view/project.html.php @@ -1,44 +1,44 @@ - - * @package ZenTaoPMS - * @version $Id: index.html.php 2343 2011-11-21 05:24:56Z wwccss $ - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'task', 'project=' . $project->id), $project->name, '_parent');?>code;?>end;?>project->statusList[$project->status];?>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> - hours->progress;?> height='13' text-align: /> - hours->progress;?>% - burns);?>'>
          - + + * @package ZenTaoPMS + * @version $Id: index.html.php 2343 2011-11-21 05:24:56Z wwccss $ + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'task', 'project=' . $project->id), $project->name, '_parent');?>code;?>end;?>project->statusList[$project->status];?>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> + hours->progress;?> height='13' text-align: /> + hours->progress;?>% + burns);?>'>
          + diff --git a/module/product/view/roadmap.html.php b/module/product/view/roadmap.html.php index 9c14ab8ca5..cffecf69fc 100644 --- a/module/product/view/roadmap.html.php +++ b/module/product/view/roadmap.html.php @@ -1,49 +1,49 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - '; - foreach($years as $year) - { - $year = $year == '0000' ? $lang->future : $year . $lang->year; - echo ""; - } - echo ''; - echo ''; - foreach($years as $year) - { - echo ''; - } - echo ''; - ?> -
          product->roadmap;?>
          $year
          '; - foreach($roadmaps[$year] as $key => $roadmap) - { - if(isset($roadmap->build)) - { - echo "
          "; - echo "

          " . html::a($this->createLink('release', 'view', "releaseID=$roadmap->id"), $roadmap->name, '_blank') . '

          ' . $roadmap->date; - } - else - { - echo "
          "; - echo "

          " . html::a($this->createLink('productplan', 'view', "planID=$roadmap->id"), $roadmap->title, '_blank') . '

          ' . $roadmap->begin . ' ~ ' . $roadmap->end; - } - echo "
          "; - if(isset($roadmaps[$year][$key + 1])) echo "{$lang->downArrow}"; - } - echo '
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + '; + foreach($years as $year) + { + $year = $year == '0000' ? $lang->future : $year . $lang->year; + echo ""; + } + echo ''; + echo ''; + foreach($years as $year) + { + echo ''; + } + echo ''; + ?> +
          product->roadmap;?>
          $year
          '; + foreach($roadmaps[$year] as $key => $roadmap) + { + if(isset($roadmap->build)) + { + echo "
          "; + echo "

          " . html::a($this->createLink('release', 'view', "releaseID=$roadmap->id"), $roadmap->name, '_blank') . '

          ' . $roadmap->date; + } + else + { + echo "
          "; + echo "

          " . html::a($this->createLink('productplan', 'view', "planID=$roadmap->id"), $roadmap->title, '_blank') . '

          ' . $roadmap->begin . ' ~ ' . $roadmap->end; + } + echo "
          "; + if(isset($roadmaps[$year][$key + 1])) echo "{$lang->downArrow}"; + } + echo '
          + diff --git a/module/product/view/view.html.php b/module/product/view/view.html.php index 6aa8bda5aa..314e4f49d4 100644 --- a/module/product/view/view.html.php +++ b/module/product/view/view.html.php @@ -1,70 +1,70 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          product->view;?>
          product->name;?>deleted) echo "class='deleted'";?>>name;?>
          product->code;?>code;?>
          product->PO;?>PO];?>
          product->QM;?>QM];?>
          product->RM;?>RM];?>
          product->status;?>product->statusList[$product->status];?>
          product->desc;?>desc;?>
          product->acl;?>product->aclList[$product->acl];?>
          product->whitelist;?> - whitelist); - foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; - ?> -
          -
          - session->productList ? $this->session->productList : inlink('browse', "productID=$product->id"); - if(!$product->deleted) - { - common::printLink('product', 'edit', "productID=$product->id", $lang->edit); - common::printLink('product', 'delete', "productID=$product->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          product->view;?>
          product->name;?>deleted) echo "class='deleted'";?>>name;?>
          product->code;?>code;?>
          product->PO;?>PO];?>
          product->QM;?>QM];?>
          product->RM;?>RM];?>
          product->status;?>product->statusList[$product->status];?>
          product->desc;?>desc;?>
          product->acl;?>product->aclList[$product->acl];?>
          product->whitelist;?> + whitelist); + foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; + ?> +
          +
          + session->productList ? $this->session->productList : inlink('browse', "productID=$product->id"); + if(!$product->deleted) + { + common::printLink('product', 'edit', "productID=$product->id", $lang->edit); + common::printLink('product', 'delete', "productID=$product->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + + diff --git a/module/productplan/control.php b/module/productplan/control.php index d78e3cbcc6..9fd67397db 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -1,192 +1,192 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -class productplan extends control -{ - /** - * Common actions - * - * @param int $productID - * @access public - * @return void - */ - public function commonAction($productID) - { - $this->loadModel('product'); - $this->view->product = $this->product->getById($productID); - $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}"), $this->view->product->name); - $this->product->setMenu($this->product->getPairs(), $productID); - } - - /** - * Create a plan. - * - * @param int $product - * @access public - * @return void - */ - public function create($product = '') - { - if(!empty($_POST)) - { - $planID = $this->productplan->create(); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('productplan', $planID, 'opened'); - die(js::locate($this->createLink('productplan', 'browse', "product=$product"), 'parent')); - } - - $this->commonAction($product); - - $this->view->header->title = $this->lang->productplan->create; - $this->display(); - } - - /** - * Edit a plan. - * - * @param int $planID - * @access public - * @return void - */ - public function edit($planID) - { - if(!empty($_POST)) - { - $changes = $this->productplan->update($planID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('productplan', $planID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "planID=$planID"), 'parent')); - } - - $plan = $this->productplan->getByID($planID); - $this->commonAction($plan->product); - $this->view->header->title = $this->lang->productplan->edit; - $this->view->position[] = $this->lang->productplan->edit; - $this->view->plan = $plan; - $this->display(); - } - - /** - * Delete a plan. - * - * @param int $planID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($planID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->productplan->confirmDelete, $this->createLink('productPlan', 'delete', "planID=$planID&confirm=yes"))); - } - else - { - $plan = $this->productplan->getById($planID); - $this->productplan->delete(TABLE_PRODUCTPLAN, $planID); - die(js::locate(inlink('browse', "productID=$plan->product"), 'parent')); - } - } - - /** - * Browse plans. - * - * @param int $product - * @access public - * @return void - */ - public function browse($product = 0) - { - $this->session->set('productPlanList', $this->app->getURI(true)); - $this->commonAction($product); - $this->view->header->title = $this->lang->productplan->browse; - $this->view->position[] = $this->lang->productplan->browse; - $this->view->plans = $this->productplan->getList($product); - $this->display(); - } - - /** - * View plan. - * - * @param int $planID - * @access public - * @return void - */ - public function view($planID = 0) - { - $this->session->set('storyList', $this->app->getURI(true)); - - $plan = $this->productplan->getByID($planID); - if(!$plan) die(js::error($this->lang->notFound) . js::locate('back')); - - $this->commonAction($plan->product); - - $this->view->header->title = $this->lang->productplan->view; - $this->view->position[] = $this->lang->productplan->view; - $this->view->planStories= $this->loadModel('story')->getPlanStories($planID); - $this->view->products = $this->product->getPairs(); - $this->view->plan = $plan; - $this->view->actions = $this->loadModel('action')->getList('productplan', $planID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Link stories. - * - * @param int $planID - * @access public - * @return void - */ - public function linkStory($planID = 0) - { - $this->session->set('storyList', $this->app->getURI(true)); - - if(!empty($_POST)) $this->productplan->linkStory($planID); - - $plan = $this->productplan->getByID($planID); - $this->commonAction($plan->product); - $this->view->header->title = $this->lang->productplan->linkStory; - $this->view->position[] = $this->lang->productplan->linkStory; - $this->view->allStories = $this->loadModel('story')->getProductStories($this->view->product->id, $moduleID = '0', $status = 'draft,active,changed'); - $this->view->planStories= $this->story->getPlanStories($planID); - $this->view->products = $this->product->getPairs(); - $this->view->plan = $plan; - $this->view->plans = $this->dao->select('id, end')->from(TABLE_PRODUCTPLAN)->fetchPairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Unlink story - * - * @param int $storyID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function unlinkStory($storyID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->productplan->confirmUnlinkStory, $this->createLink('productplan', 'unlinkstory', "storyID=$storyID&confirm=yes"))); - } - else - { - $this->productplan->unlinkStory($storyID); - die(js::reload('parent')); - } - } -} + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +class productplan extends control +{ + /** + * Common actions + * + * @param int $productID + * @access public + * @return void + */ + public function commonAction($productID) + { + $this->loadModel('product'); + $this->view->product = $this->product->getById($productID); + $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}"), $this->view->product->name); + $this->product->setMenu($this->product->getPairs(), $productID); + } + + /** + * Create a plan. + * + * @param int $product + * @access public + * @return void + */ + public function create($product = '') + { + if(!empty($_POST)) + { + $planID = $this->productplan->create(); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('productplan', $planID, 'opened'); + die(js::locate($this->createLink('productplan', 'browse', "product=$product"), 'parent')); + } + + $this->commonAction($product); + + $this->view->header->title = $this->lang->productplan->create; + $this->display(); + } + + /** + * Edit a plan. + * + * @param int $planID + * @access public + * @return void + */ + public function edit($planID) + { + if(!empty($_POST)) + { + $changes = $this->productplan->update($planID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('productplan', $planID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "planID=$planID"), 'parent')); + } + + $plan = $this->productplan->getByID($planID); + $this->commonAction($plan->product); + $this->view->header->title = $this->lang->productplan->edit; + $this->view->position[] = $this->lang->productplan->edit; + $this->view->plan = $plan; + $this->display(); + } + + /** + * Delete a plan. + * + * @param int $planID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($planID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->productplan->confirmDelete, $this->createLink('productPlan', 'delete', "planID=$planID&confirm=yes"))); + } + else + { + $plan = $this->productplan->getById($planID); + $this->productplan->delete(TABLE_PRODUCTPLAN, $planID); + die(js::locate(inlink('browse', "productID=$plan->product"), 'parent')); + } + } + + /** + * Browse plans. + * + * @param int $product + * @access public + * @return void + */ + public function browse($product = 0) + { + $this->session->set('productPlanList', $this->app->getURI(true)); + $this->commonAction($product); + $this->view->header->title = $this->lang->productplan->browse; + $this->view->position[] = $this->lang->productplan->browse; + $this->view->plans = $this->productplan->getList($product); + $this->display(); + } + + /** + * View plan. + * + * @param int $planID + * @access public + * @return void + */ + public function view($planID = 0) + { + $this->session->set('storyList', $this->app->getURI(true)); + + $plan = $this->productplan->getByID($planID); + if(!$plan) die(js::error($this->lang->notFound) . js::locate('back')); + + $this->commonAction($plan->product); + + $this->view->header->title = $this->lang->productplan->view; + $this->view->position[] = $this->lang->productplan->view; + $this->view->planStories= $this->loadModel('story')->getPlanStories($planID); + $this->view->products = $this->product->getPairs(); + $this->view->plan = $plan; + $this->view->actions = $this->loadModel('action')->getList('productplan', $planID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Link stories. + * + * @param int $planID + * @access public + * @return void + */ + public function linkStory($planID = 0) + { + $this->session->set('storyList', $this->app->getURI(true)); + + if(!empty($_POST)) $this->productplan->linkStory($planID); + + $plan = $this->productplan->getByID($planID); + $this->commonAction($plan->product); + $this->view->header->title = $this->lang->productplan->linkStory; + $this->view->position[] = $this->lang->productplan->linkStory; + $this->view->allStories = $this->loadModel('story')->getProductStories($this->view->product->id, $moduleID = '0', $status = 'draft,active,changed'); + $this->view->planStories= $this->story->getPlanStories($planID); + $this->view->products = $this->product->getPairs(); + $this->view->plan = $plan; + $this->view->plans = $this->dao->select('id, end')->from(TABLE_PRODUCTPLAN)->fetchPairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Unlink story + * + * @param int $storyID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function unlinkStory($storyID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->productplan->confirmUnlinkStory, $this->createLink('productplan', 'unlinkstory', "storyID=$storyID&confirm=yes"))); + } + else + { + $this->productplan->unlinkStory($storyID); + die(js::reload('parent')); + } + } +} diff --git a/module/productplan/lang/en.php b/module/productplan/lang/en.php index 8b0e21e32e..31bdb4f88b 100644 --- a/module/productplan/lang/en.php +++ b/module/productplan/lang/en.php @@ -1,34 +1,34 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->productplan->common = 'Plan'; -$lang->productplan->browse = "Browse"; -$lang->productplan->index = "Index"; -$lang->productplan->create = "Create"; -$lang->productplan->edit = "Edit"; -$lang->productplan->delete = "Delete"; -$lang->productplan->view = "Info"; -$lang->productplan->linkStory = "Link story"; -$lang->productplan->unlinkStory = "Remove story"; -$lang->productplan->linkedStories = 'Stories linked'; -$lang->productplan->unlinkedStories = 'Stories unlinked'; - -$lang->productplan->confirmDelete = "Are you sure to delete this plan?"; -$lang->productplan->confirmUnlinkStory = "Are you sure to remove this story?"; - -$lang->productplan->id = 'ID'; -$lang->productplan->product = 'Product'; -$lang->productplan->title = 'Title'; -$lang->productplan->desc = 'Desc'; -$lang->productplan->begin = 'Begin'; -$lang->productplan->end = 'End'; - -$lang->productplan->storySummary = "Total 『%s』stories, estimate『%s』hours."; + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->productplan->common = 'Plan'; +$lang->productplan->browse = "Browse"; +$lang->productplan->index = "Index"; +$lang->productplan->create = "Create"; +$lang->productplan->edit = "Edit"; +$lang->productplan->delete = "Delete"; +$lang->productplan->view = "Info"; +$lang->productplan->linkStory = "Link story"; +$lang->productplan->unlinkStory = "Remove story"; +$lang->productplan->linkedStories = 'Stories linked'; +$lang->productplan->unlinkedStories = 'Stories unlinked'; + +$lang->productplan->confirmDelete = "Are you sure to delete this plan?"; +$lang->productplan->confirmUnlinkStory = "Are you sure to remove this story?"; + +$lang->productplan->id = 'ID'; +$lang->productplan->product = 'Product'; +$lang->productplan->title = 'Title'; +$lang->productplan->desc = 'Desc'; +$lang->productplan->begin = 'Begin'; +$lang->productplan->end = 'End'; + +$lang->productplan->storySummary = "Total 『%s』stories, estimate『%s』hours."; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index 2fdf333a89..d85a9a44f4 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -1,32 +1,32 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->productplan->common = '产品计划'; -$lang->productplan->browse = "浏览计划"; -$lang->productplan->index = "计划列表"; -$lang->productplan->create = "创建计划"; -$lang->productplan->edit = "编辑计划"; -$lang->productplan->delete = "删除计划"; -$lang->productplan->view = "计划详情"; -$lang->productplan->linkStory = "关联需求"; -$lang->productplan->unlinkStory = "移除需求"; -$lang->productplan->linkedStories = '已关联需求列表'; -$lang->productplan->unlinkedStories = '未关联需求列表'; - -$lang->productplan->confirmDelete = "您确认删除该计划吗?"; -$lang->productplan->confirmUnlinkStory = "您确认移除该需求吗?"; - -$lang->productplan->id = '编号'; -$lang->productplan->product = '产品'; -$lang->productplan->title = '名称'; -$lang->productplan->desc = '描述'; -$lang->productplan->begin = '开始日期'; -$lang->productplan->end = '结束日期'; + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->productplan->common = '产品计划'; +$lang->productplan->browse = "浏览计划"; +$lang->productplan->index = "计划列表"; +$lang->productplan->create = "创建计划"; +$lang->productplan->edit = "编辑计划"; +$lang->productplan->delete = "删除计划"; +$lang->productplan->view = "计划详情"; +$lang->productplan->linkStory = "关联需求"; +$lang->productplan->unlinkStory = "移除需求"; +$lang->productplan->linkedStories = '已关联需求列表'; +$lang->productplan->unlinkedStories = '未关联需求列表'; + +$lang->productplan->confirmDelete = "您确认删除该计划吗?"; +$lang->productplan->confirmUnlinkStory = "您确认移除该需求吗?"; + +$lang->productplan->id = '编号'; +$lang->productplan->product = '产品'; +$lang->productplan->title = '名称'; +$lang->productplan->desc = '描述'; +$lang->productplan->begin = '开始日期'; +$lang->productplan->end = '结束日期'; diff --git a/module/productplan/lang/zh-tw.php b/module/productplan/lang/zh-tw.php index 0f7806ff1e..f0ad599b5a 100644 --- a/module/productplan/lang/zh-tw.php +++ b/module/productplan/lang/zh-tw.php @@ -1,32 +1,32 @@ - - * @package productplan - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->productplan->common = '產品計劃'; -$lang->productplan->browse = "瀏覽計劃"; -$lang->productplan->index = "計劃列表"; -$lang->productplan->create = "創建計劃"; -$lang->productplan->edit = "編輯計劃"; -$lang->productplan->delete = "刪除計劃"; -$lang->productplan->view = "計劃詳情"; -$lang->productplan->linkStory = "關聯需求"; -$lang->productplan->unlinkStory = "移除需求"; -$lang->productplan->linkedStories = '已關聯需求列表'; -$lang->productplan->unlinkedStories = '未關聯需求列表'; - -$lang->productplan->confirmDelete = "您確認刪除該計劃嗎?"; -$lang->productplan->confirmUnlinkStory = "您確認移除該需求嗎?"; - -$lang->productplan->id = '編號'; -$lang->productplan->product = '產品'; -$lang->productplan->title = '名稱'; -$lang->productplan->desc = '描述'; -$lang->productplan->begin = '開始日期'; -$lang->productplan->end = '結束日期'; + + * @package productplan + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->productplan->common = '產品計劃'; +$lang->productplan->browse = "瀏覽計劃"; +$lang->productplan->index = "計劃列表"; +$lang->productplan->create = "創建計劃"; +$lang->productplan->edit = "編輯計劃"; +$lang->productplan->delete = "刪除計劃"; +$lang->productplan->view = "計劃詳情"; +$lang->productplan->linkStory = "關聯需求"; +$lang->productplan->unlinkStory = "移除需求"; +$lang->productplan->linkedStories = '已關聯需求列表'; +$lang->productplan->unlinkedStories = '未關聯需求列表'; + +$lang->productplan->confirmDelete = "您確認刪除該計劃嗎?"; +$lang->productplan->confirmUnlinkStory = "您確認移除該需求嗎?"; + +$lang->productplan->id = '編號'; +$lang->productplan->product = '產品'; +$lang->productplan->title = '名稱'; +$lang->productplan->desc = '描述'; +$lang->productplan->begin = '開始日期'; +$lang->productplan->end = '結束日期'; diff --git a/module/productplan/model.php b/module/productplan/model.php index c2895d9b69..02b933ede8 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -1,125 +1,125 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch(); - $plan->desc = $this->loadModel('file')->setImgSize($plan->desc); - return $plan; - } - - /** - * Get list - * - * @param int $product - * @access public - * @return object - */ - public function getList($product = 0) - { - return $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) - ->andWhere('deleted')->eq(0) - ->orderBy('begin')->fetchAll(); - } - - /** - * Get plan pairs. - * - * @param int $product - * @param string $expired - * @access public - * @return array - */ - public function getPairs($product = 0, $expired = '') - { - $date = date('Y-m-d'); - return array('' => '') + $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) - ->where('product')->eq((int)$product) - ->andWhere('deleted')->eq(0) - ->beginIF($expired = 'unexpired') - ->andWhere('end')->gt($date) - ->fi() - ->orderBy('begin')->fetchPairs(); - } - - /** - * Create a plan. - * - * @access public - * @return int - */ - public function create() - { - $plan = fixer::input('post')->stripTags('title')->get(); - $this->dao->insert(TABLE_PRODUCTPLAN)->data($plan)->autoCheck()->batchCheck($this->config->productplan->create->requiredFields, 'notempty')->exec(); - if(!dao::isError()) return $this->dao->lastInsertID(); - } - - /** - * Update a plan - * - * @param int $planID - * @access public - * @return array - */ - public function update($planID) - { - $oldPlan = $this->getById($planID); - $plan = fixer::input('post')->stripTags('title')->get(); - $this->dao->update(TABLE_PRODUCTPLAN)->data($plan)->autoCheck()->batchCheck($this->config->productplan->edit->requiredFields, 'notempty')->where('id')->eq((int)$planID)->exec(); - if(!dao::isError()) return common::createChanges($oldPlan, $plan); - } - - /** - * Link stories. - * - * @param int $planID - * @access public - * @return void - */ - public function linkStory($planID) - { - $this->loadModel('story'); - $this->loadModel('action'); - foreach($this->post->stories as $storyID) - { - $this->dao->update(TABLE_STORY)->set('plan')->eq((int)$planID)->where('id')->eq((int)$storyID)->exec(); - $this->action->create('story', $storyID, 'linked2plan', '', $planID); - $this->story->setStage($storyID); - } - } - - /** - * Unlink story - * - * @param int $storyID - * @access public - * @return void - */ - public function unlinkStory($storyID) - { - $planID = $this->dao->findByID($storyID)->from(TABLE_STORY)->fields('plan')->fetch('plan'); - $this->dao->update(TABLE_STORY)->set('plan')->eq(0)->where('id')->eq((int)$storyID)->exec(); - $this->loadModel('story')->setStage($storyID); - $this->loadModel('action')->create('story', $storyID, 'unlinkedfromplan', '', $planID); - } -} + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch(); + $plan->desc = $this->loadModel('file')->setImgSize($plan->desc); + return $plan; + } + + /** + * Get list + * + * @param int $product + * @access public + * @return object + */ + public function getList($product = 0) + { + return $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('product')->eq($product) + ->andWhere('deleted')->eq(0) + ->orderBy('begin')->fetchAll(); + } + + /** + * Get plan pairs. + * + * @param int $product + * @param string $expired + * @access public + * @return array + */ + public function getPairs($product = 0, $expired = '') + { + $date = date('Y-m-d'); + return array('' => '') + $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) + ->where('product')->eq((int)$product) + ->andWhere('deleted')->eq(0) + ->beginIF($expired = 'unexpired') + ->andWhere('end')->gt($date) + ->fi() + ->orderBy('begin')->fetchPairs(); + } + + /** + * Create a plan. + * + * @access public + * @return int + */ + public function create() + { + $plan = fixer::input('post')->stripTags('title')->get(); + $this->dao->insert(TABLE_PRODUCTPLAN)->data($plan)->autoCheck()->batchCheck($this->config->productplan->create->requiredFields, 'notempty')->exec(); + if(!dao::isError()) return $this->dao->lastInsertID(); + } + + /** + * Update a plan + * + * @param int $planID + * @access public + * @return array + */ + public function update($planID) + { + $oldPlan = $this->getById($planID); + $plan = fixer::input('post')->stripTags('title')->get(); + $this->dao->update(TABLE_PRODUCTPLAN)->data($plan)->autoCheck()->batchCheck($this->config->productplan->edit->requiredFields, 'notempty')->where('id')->eq((int)$planID)->exec(); + if(!dao::isError()) return common::createChanges($oldPlan, $plan); + } + + /** + * Link stories. + * + * @param int $planID + * @access public + * @return void + */ + public function linkStory($planID) + { + $this->loadModel('story'); + $this->loadModel('action'); + foreach($this->post->stories as $storyID) + { + $this->dao->update(TABLE_STORY)->set('plan')->eq((int)$planID)->where('id')->eq((int)$storyID)->exec(); + $this->action->create('story', $storyID, 'linked2plan', '', $planID); + $this->story->setStage($storyID); + } + } + + /** + * Unlink story + * + * @param int $storyID + * @access public + * @return void + */ + public function unlinkStory($storyID) + { + $planID = $this->dao->findByID($storyID)->from(TABLE_STORY)->fields('plan')->fetch('plan'); + $this->dao->update(TABLE_STORY)->set('plan')->eq(0)->where('id')->eq((int)$storyID)->exec(); + $this->loadModel('story')->setStage($storyID); + $this->loadModel('action')->create('story', $storyID, 'unlinkedfromplan', '', $planID); + } +} diff --git a/module/productplan/view/browse.html.php b/module/productplan/view/browse.html.php index 513750fa46..f2f31251e3 100644 --- a/module/productplan/view/browse.html.php +++ b/module/productplan/view/browse.html.php @@ -1,49 +1,49 @@ - - * @package plan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          productplan->browse;?>
          -
          id", $lang->productplan->create);?>
          -
          idAB;?>productplan->begin;?>productplan->end;?>productplan->title;?>productplan->desc;?>actions;?>
          id"), $plan->id);?>begin;?>end;?>id"), $plan->title);?>desc;?> - id", $lang->edit); - common::printLink('productplan', 'linkstory', "planID=$plan->id", $lang->productplan->linkStory); - common::printLink('productplan', 'delete', "planID=$plan->id", $lang->delete, 'hiddenwin'); - ?> -
          - + + * @package plan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          productplan->browse;?>
          +
          id", $lang->productplan->create);?>
          +
          idAB;?>productplan->begin;?>productplan->end;?>productplan->title;?>productplan->desc;?>actions;?>
          id"), $plan->id);?>begin;?>end;?>id"), $plan->title);?>desc;?> + id", $lang->edit); + common::printLink('productplan', 'linkstory', "planID=$plan->id", $lang->productplan->linkStory); + common::printLink('productplan', 'delete', "planID=$plan->id", $lang->delete, 'hiddenwin'); + ?> +
          + diff --git a/module/productplan/view/create.html.php b/module/productplan/view/create.html.php index 6cb7e2484c..d245c593c6 100644 --- a/module/productplan/view/create.html.php +++ b/module/productplan/view/create.html.php @@ -1,50 +1,50 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - -
          productplan->create;?>
          productplan->product;?>name;?>
          productplan->title;?>
          productplan->begin;?>
          productplan->end;?>
          productplan->desc;?>
          - id); - ?> -
          -
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + +
          productplan->create;?>
          productplan->product;?>name;?>
          productplan->title;?>
          productplan->begin;?>
          productplan->end;?>
          productplan->desc;?>
          + id); + ?> +
          +
          + diff --git a/module/productplan/view/edit.html.php b/module/productplan/view/edit.html.php index 77577f4e37..1da443f010 100644 --- a/module/productplan/view/edit.html.php +++ b/module/productplan/view/edit.html.php @@ -1,50 +1,50 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - -
          productplan->edit;?>
          productplan->product;?>name;?>
          productplan->title;?>title, 'class="text-3"');?>
          productplan->begin;?>begin, 'class="text-3 date"');?>
          productplan->end;?>end, 'class="text-3 date"');?>
          productplan->desc;?>desc), "rows='10' class='area-1'");?>
          - id); - ?> -
          -
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + +
          productplan->edit;?>
          productplan->product;?>name;?>
          productplan->title;?>title, 'class="text-3"');?>
          productplan->begin;?>begin, 'class="text-3 date"');?>
          productplan->end;?>end, 'class="text-3 date"');?>
          productplan->desc;?>desc), "rows='10' class='area-1'");?>
          + id); + ?> +
          +
          + diff --git a/module/productplan/view/linkstory.html.php b/module/productplan/view/linkstory.html.php index 2569809e92..e523dc7ba8 100644 --- a/module/productplan/view/linkstory.html.php +++ b/module/productplan/view/linkstory.html.php @@ -1,89 +1,89 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - id])) continue; - if($story->plan and helper::diffDate($plans[$story->plan], helper::today()) > 0) continue; - ?> - - - - - - - - - - - - - - - - - - -
          title .$lang->colon . $lang->productplan->unlinkedStories;?>
          idAB;?>priAB;?>story->plan;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>link;?>
          createLink('story', 'view', "storyID=$story->id"), $story->id);?>pri;?>planTitle;?>createLink('story', 'view', "storyID=$story->id"), $story->title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>
          story->linkStory);?>
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          title .$lang->colon . $lang->productplan->linkedStories;?>
          idAB;?>priAB;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions?>
          createLink('story', 'view', "storyID=$story->id"), $story->id);?>pri;?>createLink('story', 'view', "storyID=$story->id"), $story->title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + id])) continue; + if($story->plan and helper::diffDate($plans[$story->plan], helper::today()) > 0) continue; + ?> + + + + + + + + + + + + + + + + + + +
          title .$lang->colon . $lang->productplan->unlinkedStories;?>
          idAB;?>priAB;?>story->plan;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>link;?>
          createLink('story', 'view', "storyID=$story->id"), $story->id);?>pri;?>planTitle;?>createLink('story', 'view', "storyID=$story->id"), $story->title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>
          story->linkStory);?>
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          title .$lang->colon . $lang->productplan->linkedStories;?>
          idAB;?>priAB;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions?>
          createLink('story', 'view', "storyID=$story->id"), $story->id);?>pri;?>createLink('story', 'view', "storyID=$story->id"), $story->title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          + diff --git a/module/productplan/view/view.html.php b/module/productplan/view/view.html.php index cac4d62c7d..a8985279a7 100644 --- a/module/productplan/view/view.html.php +++ b/module/productplan/view/view.html.php @@ -1,84 +1,84 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - -
          title . $lang->colon . $lang->productplan->view;?>
          productplan->title;?>deleted) echo "class='deleted'";?>>title;?> -
          productplan->begin;?>begin;?> -
          productplan->end;?>end;?> -
          productplan->desc;?>desc;?> -
          -
          - session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id"); - if(!$plan->deleted) - { - common::printLink('productplan', 'edit', "planID=$plan->id", $lang->edit); - common::printLink('productplan', 'linkstory',"planID=$plan->id", $lang->productplan->linkStory); - common::printLink('productplan', 'delete', "planID=$plan->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - - - - - - - - - - - - - - - - - - - - createLink('story', 'view', "storyID=$story->id"); - $totalEstimate += $story->estimate; - ?> - - - - - - - - - - - - - - -
          title .$lang->colon . $lang->productplan->linkedStories;?>
          idAB;?>priAB;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions?>
          id);?>pri;?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          product->storySummary, count($planStories), $totalEstimate);?>
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + +
          title . $lang->colon . $lang->productplan->view;?>
          productplan->title;?>deleted) echo "class='deleted'";?>>title;?> +
          productplan->begin;?>begin;?> +
          productplan->end;?>end;?> +
          productplan->desc;?>desc;?> +
          +
          + session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id"); + if(!$plan->deleted) + { + common::printLink('productplan', 'edit', "planID=$plan->id", $lang->edit); + common::printLink('productplan', 'linkstory',"planID=$plan->id", $lang->productplan->linkStory); + common::printLink('productplan', 'delete', "planID=$plan->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + + + + + + + + + + + + + + + + + + + + createLink('story', 'view', "storyID=$story->id"); + $totalEstimate += $story->estimate; + ?> + + + + + + + + + + + + + + +
          title .$lang->colon . $lang->productplan->linkedStories;?>
          idAB;?>priAB;?>story->title;?>openedByAB;?>assignedToAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>actions?>
          id);?>pri;?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          product->storySummary, count($planStories), $totalEstimate);?>
          + diff --git a/module/project/control.php b/module/project/control.php index 99e95fad9d..3b5e9cf3dc 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -2,7 +2,7 @@ /** * The control file of project module of ZenTaoPMS. * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) * @author Chunsheng Wang * @package project * @version $Id$ diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 81e8fda42c..5fe8b6bab5 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -1,164 +1,164 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -/* Fields. */ -$lang->project->common = 'Project'; -$lang->project->id = 'ID'; -$lang->project->company = 'Company'; -$lang->project->iscat = 'Is category'; -$lang->project->type = 'Type'; -$lang->project->parent = 'Parent'; -$lang->project->name = 'Name'; -$lang->project->code = 'Code'; -$lang->project->begin = 'Begin'; -$lang->project->end = 'End'; -$lang->project->days = 'Workdays'; -$lang->project->status = 'Status'; -$lang->project->statge = 'Stage'; -$lang->project->pri = 'Priority'; -$lang->project->desc = 'Desc'; -$lang->project->goal = 'Goal'; -$lang->project->openedBy = 'Opened by'; -$lang->project->openedDate = 'Opened date'; -$lang->project->closedBy = 'Closed by'; -$lang->project->closedDate = 'Closed date'; -$lang->project->canceledBy = 'Canceled by'; -$lang->project->canceledDate = 'Canceled date'; -$lang->project->PO = 'Product owner'; -$lang->project->PM = 'Project manager'; -$lang->project->QM = 'Test manager'; -$lang->project->RM = 'Release manager'; -$lang->project->acl = 'Access limitation'; -$lang->project->teamname = 'Team name'; -$lang->project->products = 'Products'; -$lang->project->childProjects = 'Child projects'; -$lang->project->whitelist = 'Whitelist'; -$lang->project->totalEstimate = 'Est'; -$lang->project->totalConsumed = 'Done'; -$lang->project->totalLeft = 'Left'; -$lang->project->progess = 'Progess'; -$lang->project->viewBug = 'View bug'; -$lang->project->noProduct = 'No product'; -$lang->project->select = '--select project--'; - -$lang->team->account = 'Account'; -$lang->team->role = 'Role'; -$lang->team->join = 'Join date'; -$lang->team->hours = 'Hour/Day'; -$lang->team->days = 'Workdays'; -$lang->team->totalHours = 'Total'; - -/* Lists. */ -$lang->project->statusList[''] = ''; -$lang->project->statusList['wait'] = 'Waitting'; -$lang->project->statusList['doing'] = 'Doing'; -$lang->project->statusList['done'] = 'Done'; - -$lang->project->aclList['open'] = 'Default(Having the priviledge of project module can visit this project)'; -$lang->project->aclList['private'] = 'Private(Only team members can visit)'; -$lang->project->aclList['custom'] = 'Whitelist(Team members and who belongs to the whitelist grups can visit)'; - -/* Methods.*/ -$lang->project->index = "Index"; -$lang->project->task = 'Task'; -$lang->project->groupTask = 'View task by group'; -$lang->project->story = 'Story'; -$lang->project->bug = 'Bug'; -$lang->project->dynamic = 'Dynamic'; -$lang->project->build = 'Build'; -$lang->project->testtask = 'Testtask'; -$lang->project->burn = 'Burndown chart'; -$lang->project->computeBurn = 'Update burndown'; -$lang->project->burnData = 'Burndown data'; -$lang->project->team = 'Team'; -$lang->project->doc = 'Doc'; -$lang->project->manageProducts = 'Link product'; -$lang->project->linkStory = 'Link story'; -$lang->project->view = "Info"; -$lang->project->create = "Add"; -$lang->project->delete = "Delete"; -$lang->project->browse = "Browse"; -$lang->project->edit = "Edit"; -$lang->project->manageMembers = 'Manage team members'; -$lang->project->unlinkMember = 'Remove member'; -$lang->project->unlinkStory = 'Remove story'; -$lang->project->importTask = 'Import task'; -$lang->project->importBug = 'Import bug'; -$lang->project->ajaxGetProducts = "API: get project's products"; - -/* Browse. */ -$lang->project->allTasks = 'All'; -$lang->project->assignedToMe = 'To me'; -$lang->project->finishedByMe = 'My done'; -$lang->project->statusWait = 'Wait'; -$lang->project->statusDoing = 'Doing'; -$lang->project->statusDone = 'Done'; -$lang->project->statusClosed = 'Closed'; -$lang->project->delayed = 'Delayed'; -$lang->project->groups[''] = 'Group View'; -$lang->project->groups['story'] = 'Group by story'; -$lang->project->groups['status'] = 'Group by status'; -$lang->project->groups['pri'] = 'Group by priority'; -$lang->project->groups['openedby'] = 'Group by openedBy'; -$lang->project->groups['assignedTo'] = 'Group by assignedTo'; -$lang->project->groups['finishedby'] = 'Group by finishedBy'; -$lang->project->groups['closedby'] = 'Group by closedBy'; -$lang->project->groups['estimate'] = 'Group by estimate'; -$lang->project->groups['consumed'] = 'Group by consumed'; -$lang->project->groups['left'] = 'Group by left'; -$lang->project->groups['type'] = 'Group by type'; -$lang->project->groups['deadline'] = 'Group by deadline'; -$lang->project->listTaskNeedConfrim = 'Story changed'; -$lang->project->byQuery = 'Search'; - -/* Browse tabs. */ -$lang->project->allProject = 'All projects'; -$lang->project->aboveAllProduct = 'Above all products'; -$lang->project->aboveAllProject = 'Above all projects'; - -/* Notcie. */ -$lang->project->selectProject = "Select project"; -$lang->project->beginAndEnd = 'Begin and end'; -$lang->project->lblStats = 'Stats'; -$lang->project->stats = 'Total work hours is 『%s』hours,
          Total estimate is『%s』hours,
          Total confused is『%s』hours
          Total left is『%s』hours'; -$lang->project->oneLineStats = "Project『%s』, code is『%s』, products is『%s』,begin from『%s』to 『%s』,total estimate『%s』hours,consumed『%s』hours,left『%s』hours."; -$lang->project->taskSummary = "%s tasks this page, wait:%s, doing:%s, estimate %s, consumed %s, left %s hours."; -$lang->project->memberHours = "%s has %s workhours, "; -$lang->project->groupSummary = "%s tasks in this group, wait:%s, doing:%s, estimate %s, consumed %s, left %s hours."; -$lang->project->wbs = "WBS"; -$lang->project->largeBurnChart = 'View large'; -$lang->project->howToUpdateBurn = "How?"; -$lang->project->whyNoStories = "There no active stories to added to this project. Please check the linked product."; -$lang->project->doneProjects = 'Done'; -$lang->project->unDoneProjects = 'Undone'; - -/* Confirm. */ -$lang->project->confirmDelete = 'Are you sure to delete project [%s]?'; -$lang->project->confirmUnlinkMember = 'Are you sure to remove this user from this project?'; -$lang->project->confirmUnlinkStory = 'Are you sure to remove the story from this project?'; -$lang->project->errorNoLinkedProducts = 'There is no linked products, go to the link page.'; -$lang->project->accessDenied = 'Access to this project denied.'; -$lang->project->tips = 'Tips'; -$lang->project->afterInfo = 'Successful and you can do:'; -$lang->project->setTeam = 'Set team'; -$lang->project->linkStory = 'Link story'; -$lang->project->createTask = 'Create task'; -$lang->project->goback = 'Go back(Automatically after 5 seconds)'; - -/* Report. */ -$lang->project->charts->burn->graph->caption = "Burndown chart"; -$lang->project->charts->burn->graph->xAxisName = "Date"; -$lang->project->charts->burn->graph->yAxisName = "HOUR"; -$lang->project->charts->burn->graph->baseFontSize = 12; -$lang->project->charts->burn->graph->formatNumber = 0; -$lang->project->charts->burn->graph->animation = 0; -$lang->project->charts->burn->graph->rotateNames = 1; -$lang->project->charts->burn->graph->showValues = 0; + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +/* Fields. */ +$lang->project->common = 'Project'; +$lang->project->id = 'ID'; +$lang->project->company = 'Company'; +$lang->project->iscat = 'Is category'; +$lang->project->type = 'Type'; +$lang->project->parent = 'Parent'; +$lang->project->name = 'Name'; +$lang->project->code = 'Code'; +$lang->project->begin = 'Begin'; +$lang->project->end = 'End'; +$lang->project->days = 'Workdays'; +$lang->project->status = 'Status'; +$lang->project->statge = 'Stage'; +$lang->project->pri = 'Priority'; +$lang->project->desc = 'Desc'; +$lang->project->goal = 'Goal'; +$lang->project->openedBy = 'Opened by'; +$lang->project->openedDate = 'Opened date'; +$lang->project->closedBy = 'Closed by'; +$lang->project->closedDate = 'Closed date'; +$lang->project->canceledBy = 'Canceled by'; +$lang->project->canceledDate = 'Canceled date'; +$lang->project->PO = 'Product owner'; +$lang->project->PM = 'Project manager'; +$lang->project->QM = 'Test manager'; +$lang->project->RM = 'Release manager'; +$lang->project->acl = 'Access limitation'; +$lang->project->teamname = 'Team name'; +$lang->project->products = 'Products'; +$lang->project->childProjects = 'Child projects'; +$lang->project->whitelist = 'Whitelist'; +$lang->project->totalEstimate = 'Est'; +$lang->project->totalConsumed = 'Done'; +$lang->project->totalLeft = 'Left'; +$lang->project->progess = 'Progess'; +$lang->project->viewBug = 'View bug'; +$lang->project->noProduct = 'No product'; +$lang->project->select = '--select project--'; + +$lang->team->account = 'Account'; +$lang->team->role = 'Role'; +$lang->team->join = 'Join date'; +$lang->team->hours = 'Hour/Day'; +$lang->team->days = 'Workdays'; +$lang->team->totalHours = 'Total'; + +/* Lists. */ +$lang->project->statusList[''] = ''; +$lang->project->statusList['wait'] = 'Waitting'; +$lang->project->statusList['doing'] = 'Doing'; +$lang->project->statusList['done'] = 'Done'; + +$lang->project->aclList['open'] = 'Default(Having the priviledge of project module can visit this project)'; +$lang->project->aclList['private'] = 'Private(Only team members can visit)'; +$lang->project->aclList['custom'] = 'Whitelist(Team members and who belongs to the whitelist grups can visit)'; + +/* Methods.*/ +$lang->project->index = "Index"; +$lang->project->task = 'Task'; +$lang->project->groupTask = 'View task by group'; +$lang->project->story = 'Story'; +$lang->project->bug = 'Bug'; +$lang->project->dynamic = 'Dynamic'; +$lang->project->build = 'Build'; +$lang->project->testtask = 'Testtask'; +$lang->project->burn = 'Burndown chart'; +$lang->project->computeBurn = 'Update burndown'; +$lang->project->burnData = 'Burndown data'; +$lang->project->team = 'Team'; +$lang->project->doc = 'Doc'; +$lang->project->manageProducts = 'Link product'; +$lang->project->linkStory = 'Link story'; +$lang->project->view = "Info"; +$lang->project->create = "Add"; +$lang->project->delete = "Delete"; +$lang->project->browse = "Browse"; +$lang->project->edit = "Edit"; +$lang->project->manageMembers = 'Manage team members'; +$lang->project->unlinkMember = 'Remove member'; +$lang->project->unlinkStory = 'Remove story'; +$lang->project->importTask = 'Import task'; +$lang->project->importBug = 'Import bug'; +$lang->project->ajaxGetProducts = "API: get project's products"; + +/* Browse. */ +$lang->project->allTasks = 'All'; +$lang->project->assignedToMe = 'To me'; +$lang->project->finishedByMe = 'My done'; +$lang->project->statusWait = 'Wait'; +$lang->project->statusDoing = 'Doing'; +$lang->project->statusDone = 'Done'; +$lang->project->statusClosed = 'Closed'; +$lang->project->delayed = 'Delayed'; +$lang->project->groups[''] = 'Group View'; +$lang->project->groups['story'] = 'Group by story'; +$lang->project->groups['status'] = 'Group by status'; +$lang->project->groups['pri'] = 'Group by priority'; +$lang->project->groups['openedby'] = 'Group by openedBy'; +$lang->project->groups['assignedTo'] = 'Group by assignedTo'; +$lang->project->groups['finishedby'] = 'Group by finishedBy'; +$lang->project->groups['closedby'] = 'Group by closedBy'; +$lang->project->groups['estimate'] = 'Group by estimate'; +$lang->project->groups['consumed'] = 'Group by consumed'; +$lang->project->groups['left'] = 'Group by left'; +$lang->project->groups['type'] = 'Group by type'; +$lang->project->groups['deadline'] = 'Group by deadline'; +$lang->project->listTaskNeedConfrim = 'Story changed'; +$lang->project->byQuery = 'Search'; + +/* Browse tabs. */ +$lang->project->allProject = 'All projects'; +$lang->project->aboveAllProduct = 'Above all products'; +$lang->project->aboveAllProject = 'Above all projects'; + +/* Notcie. */ +$lang->project->selectProject = "Select project"; +$lang->project->beginAndEnd = 'Begin and end'; +$lang->project->lblStats = 'Stats'; +$lang->project->stats = 'Total work hours is 『%s』hours,
          Total estimate is『%s』hours,
          Total confused is『%s』hours
          Total left is『%s』hours'; +$lang->project->oneLineStats = "Project『%s』, code is『%s』, products is『%s』,begin from『%s』to 『%s』,total estimate『%s』hours,consumed『%s』hours,left『%s』hours."; +$lang->project->taskSummary = "%s tasks this page, wait:%s, doing:%s, estimate %s, consumed %s, left %s hours."; +$lang->project->memberHours = "%s has %s workhours, "; +$lang->project->groupSummary = "%s tasks in this group, wait:%s, doing:%s, estimate %s, consumed %s, left %s hours."; +$lang->project->wbs = "WBS"; +$lang->project->largeBurnChart = 'View large'; +$lang->project->howToUpdateBurn = "How?"; +$lang->project->whyNoStories = "There no active stories to added to this project. Please check the linked product."; +$lang->project->doneProjects = 'Done'; +$lang->project->unDoneProjects = 'Undone'; + +/* Confirm. */ +$lang->project->confirmDelete = 'Are you sure to delete project [%s]?'; +$lang->project->confirmUnlinkMember = 'Are you sure to remove this user from this project?'; +$lang->project->confirmUnlinkStory = 'Are you sure to remove the story from this project?'; +$lang->project->errorNoLinkedProducts = 'There is no linked products, go to the link page.'; +$lang->project->accessDenied = 'Access to this project denied.'; +$lang->project->tips = 'Tips'; +$lang->project->afterInfo = 'Successful and you can do:'; +$lang->project->setTeam = 'Set team'; +$lang->project->linkStory = 'Link story'; +$lang->project->createTask = 'Create task'; +$lang->project->goback = 'Go back(Automatically after 5 seconds)'; + +/* Report. */ +$lang->project->charts->burn->graph->caption = "Burndown chart"; +$lang->project->charts->burn->graph->xAxisName = "Date"; +$lang->project->charts->burn->graph->yAxisName = "HOUR"; +$lang->project->charts->burn->graph->baseFontSize = 12; +$lang->project->charts->burn->graph->formatNumber = 0; +$lang->project->charts->burn->graph->animation = 0; +$lang->project->charts->burn->graph->rotateNames = 1; +$lang->project->charts->burn->graph->showValues = 0; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 423dc10b08..6b3aa498bd 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -2,7 +2,7 @@ /** * The project module zh-cn file of ZenTaoMS. * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) * @license LGPL (http://www.gnu.org/licenses/lgpl.html) * @author Chunsheng Wang * @package project diff --git a/module/project/lang/zh-tw.php b/module/project/lang/zh-tw.php index 134c85fbd9..a52decaddc 100644 --- a/module/project/lang/zh-tw.php +++ b/module/project/lang/zh-tw.php @@ -2,7 +2,7 @@ /** * The project module zh-tw file of ZenTaoMS. * - * @copyright Copyright 2009-2011 青島易軟天創網絡科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @copyright Copyright 2009-2012 青島易軟天創網絡科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) * @license LGPL (http://www.gnu.org/licenses/lgpl.html) * @author Chunsheng Wang * @package project diff --git a/module/project/model.php b/module/project/model.php index e017d8934c..1a6b07cdfa 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1,1033 +1,1033 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->user->account . ','; - if(strpos($this->app->company->admins, $account) !== false) return true; - - /* If project is open, return true. */ - if($project->acl == 'open') return true; - - /* Get team members. */ - $teamMembers = $this->getTeamMemberPairs($project->id); - - /* If project is private, only members can access. */ - if($project->acl == 'private') - { - return isset($teamMembers[$this->app->user->account]); - } - - /* Project's acl is custom, check the groups. */ - if($project->acl == 'custom') - { - if(isset($teamMembers[$this->app->user->account])) return true; - $userGroups = $this->loadModel('user')->getGroups($this->app->user->account); - $projectGroups = explode(',', $project->whitelist); - foreach($userGroups as $groupID) - { - if(in_array($groupID, $projectGroups)) return true; - } - return false; - } - } - - /** - * Set menu. - * - * @param array $projects - * @param int $projectID - * @access public - * @return void - */ - public function setMenu($projects, $projectID) - { - /* Check the privilege. */ - if($projects and !isset($projects[$projectID]) and !$this->checkPriv($this->getById($projectID))) - { - echo(js::alert($this->lang->project->accessDenied)); - die(js::locate('back')); - } - - $moduleName = $this->app->getModuleName(); - $methodName = $this->app->getMethodName(); - $selectHtml = $this->select($projects, $projectID, $moduleName, $methodName); - foreach($this->lang->project->menu as $key => $menu) - { - $replace = $key == 'list' ? $selectHtml . $this->lang->arrow : $projectID; - common::setMenuVars($this->lang->project->menu, $key, $replace); - } - } - - /** - * Create the select code of projects. - * - * @param array $projects - * @param int $projectID - * @param string $currentModule - * @param string $currentMethod - * @access public - * @return string - */ - public function select($projects, $projectID, $currentModule, $currentMethod) - { - /* See product's model method:select. */ - $switchCode = "switchProject($('#projectID').val(), '$currentModule', '$currentMethod');"; - $onchange = "onchange=\"$switchCode\""; - $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; - $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; - $selectHtml = html::select('projectID', $projects, $projectID, "tabindex=2 $onchange $onkeypress"); - $selectHtml .= html::commonButton($this->lang->go, "id='projectSwitcher' tabindex=3 $onclick"); - return $selectHtml; - } - - /** - * Save the project id user last visited to session. - * - * @param int $projectID - * @param array $projects - * @access public - * @return int - */ - public function saveState($projectID, $projects) - { - if($projectID > 0) $this->session->set('project', (int)$projectID); - if($projectID == 0 and $this->cookie->lastProject) $this->session->set('project', (int)$this->cookie->lastProject); - if($projectID == 0 and $this->session->project == '') $this->session->set('project', $projects[0]); - if(!in_array($this->session->project, $projects)) $this->session->set('project', $projects[0]); - return $this->session->project; - } - - /** - * Create a project. - * - * @access public - * @return void - */ - public function create() - { - $this->lang->project->team = $this->lang->project->teamname; - $project = fixer::input('post') - ->stripTags('name, code, team') - ->setIF($this->post->acl != 'custom', 'whitelist', '') - ->join('whitelist', ',') - ->remove('products') - ->get(); - $this->dao->insert(TABLE_PROJECT)->data($project) - ->autoCheck($skipFields = 'begin,end') - ->batchcheck($this->config->project->create->requiredFields, 'notempty') - ->checkIF($project->begin != '', 'begin', 'date') - ->checkIF($project->end != '', 'end', 'date') - ->checkIF($project->end != '', 'end', 'gt', $project->begin) - ->check('name', 'unique') - ->check('code', 'unique') - ->exec(); - - /* Add the creater to the team. */ - if(!dao::isError()) - { - $projectID = $this->dao->lastInsertId(); - $member->project = $projectID; - $member->account = $this->app->user->account; - $member->join = helper::today(); - $member->days = $project->days; - $member->hours = $this->config->project->defaultWorkhours; - $this->dao->insert(TABLE_TEAM)->data($member)->exec(); - return $projectID; - } - } - - /** - * Update a project. - * - * @param int $projectID - * @access public - * @return array - */ - public function update($projectID) - { - $oldProject = $this->getById($projectID); - $team = $this->getTeamMemberPairs($projectID); - $this->lang->project->team = $this->lang->project->teamname; - $projectID = (int)$projectID; - $project = fixer::input('post') - ->stripTags('name, code, team') - ->setIF($this->post->begin == '0000-00-00', 'begin', '') - ->setIF($this->post->end == '0000-00-00', 'end', '') - ->setIF($this->post->acl != 'custom', 'whitelist', '') - ->join('whitelist', ',') - ->remove('products') - ->get(); - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck($skipFields = 'begin,end') - ->batchcheck($this->config->project->edit->requiredFields, 'notempty') - ->checkIF($project->begin != '', 'begin', 'date') - ->checkIF($project->end != '', 'end', 'date') - ->checkIF($project->end != '', 'end', 'gt', $project->begin) - ->check('name', 'unique', "id!=$projectID") - ->check('code', 'unique', "id!=$projectID") - ->where('id')->eq($projectID) - ->limit(1) - ->exec(); - foreach($project as $fieldName => $value) - { - if($fieldName == 'PO' or $fieldName == 'PM' or $fieldName == 'QM' or $fieldName == 'RM' ) - { - if(!empty($value) and !isset($team[$value])) - { - $member->project = (int)$projectID; - $member->account = $value; - $member->join = helper::today(); - $member->role = $fieldName; - $member->days = $project->days; - $member->hours = $this->config->project->defaultWorkhours; - $this->dao->insert(TABLE_TEAM)->data($member)->exec(); - } - } - } - if(!dao::isError()) return common::createChanges($oldProject, $project); - } - - /** - * Get project pairs. - * - * @param string $mode all|noclosed or empty - * @access public - * @return array - */ - public function getPairs($mode = '') - { - $orderBy = !empty($this->config->project->orderBy) ? $this->config->project->orderBy : 'status, id desc'; - $mode .= $this->cookie->projectMode; - $projects = $this->dao->select('*')->from(TABLE_PROJECT) - ->where('iscat')->eq(0) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->fetchAll(); - $pairs = array(); - foreach($projects as $project) - { - if(strpos($mode, 'noclosed') !== false and $project->status == 'done') continue; - if($this->checkPriv($project)) - { - if(strpos($mode, 'nocode') === false and $project->code) - { - $firstChar = strtoupper(substr($project->code, 0, 1)); - if(ord($firstChar) < 127) $project->name = $firstChar . ':' . $project->name; - } - $pairs[$project->id] = $project->name; - } - } - - /* If the pairs is empty, to make sure there's an project in the pairs. */ - if(empty($pairs) and isset($projects[0]) and $this->checkPriv($projects[0])) - { - $firstProject = $projects[0]; - $pairs[$firstProject->id] = $firstProject->name; - } - return $pairs; - } - - /** - * Get project lists. - * - * @param string $status all|undone|wait|running - * @param int $limit - * @access public - * @return array - */ - public function getList($status = 'all', $limit = 0, $productID = 0) - { - if($productID != 0) - { - return $this->dao->select('t2.*') - ->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.product')->eq($productID) - ->andWhere('t2.deleted')->eq(0) - ->andWhere('t2.iscat')->eq(0) - ->beginIF($status == 'undone')->andWhere('t2.status')->ne('done')->fi() - ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() - ->orderBy('status, id desc') - ->beginIF($limit)->limit($limit)->fi() - ->fetchAll('id'); - } - else - { - return $this->dao->select('*')->from(TABLE_PROJECT)->where('iscat')->eq(0) - ->beginIF($status == 'undone')->andWhere('status')->ne('done')->fi() - ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy('status, id') - ->beginIF($limit)->limit($limit)->fi() - ->fetchAll('id'); - } - } - - /** - * Get projects lists grouped by product. - * - * @access public - * @return array - */ - public function getProductGroupList() - { - $list = $this->dao->select('t1.id, t1.name, t2.product')->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project') - ->where('t1.deleted')->eq(0) - ->orderBy('t1.id') - ->fetchGroup('product'); - - foreach($list as $id => $product) - { - foreach($product as $ID => $project) - { - if(!$this->checkPriv($this->getById($project->id))) - { - unset($list[$id][$ID]); - } - } - } - - return $list; - } - - /** - * Get project stats. - * - * @param string $status - * @access public - * @return array - */ - public function getProjectStats($status = 'undone', $productID = 0) - { - $this->loadModel('report'); - - $projects = $this->getList($status, 0, $productID); - $stats = array(); - - /* Get total estimate, consumed and left hours of project. */ - $emptyHour = (object)array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0); - $hours = $this->dao->select('project, SUM(estimate) AS totalEstimate, SUM(consumed) AS totalConsumed') - ->from(TABLE_TASK) - ->where('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->groupBy('project') - ->fetchAll('project'); - - $lefts = $this->dao->select('project, SUM(`left`) AS totalLeft') - ->from(TABLE_TASK) - ->where('project')->in(array_keys($projects)) - ->andWhere('closedReason')->ne('cancel') - ->andWhere('status')->ne('cancel') - ->andWhere('deleted')->eq(0) - ->groupBy('project') - ->fetchAll('project'); - foreach($lefts as $projectID => $projectLefts) $hours[$projectID]->totalLeft = $projectLefts->totalLeft; - - /* Round them. */ - foreach($hours as $hour) - { - $hour->totalEstimate = round($hour->totalEstimate, 1); - $hour->totalConsumed = round($hour->totalConsumed, 1); - $hour->totalLeft = round($hour->totalLeft, 1); - $hour->totalReal = $hour->totalConsumed + $hour->totalLeft; - $hour->progress = $hour->totalReal ? round($hour->totalConsumed / $hour->totalReal, 3) * 100 : 0; - } - - /* Get tasks stats group by status. */ - $tasks = $this->dao->select('project, status, count(status) AS count') - ->from(TABLE_TASK) - ->where('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq(0) - ->groupBy('project, status') - ->fetchGroup('project', 'status'); - - /* Process projects. */ - foreach($projects as $key => $project) - { - if($this->checkPriv($project)) - { - // Process the end time. - $project->end = date(DT_DATE4, strtotime($project->end)); - - /* Process the burns. */ - $project->burns = array(); - $burnData = $this->getBurnData($project->id); - foreach($burnData as $data) $project->burns[] = $data->value; - $stats[] = $project; - - /* Process the hours. */ - $project->hours = isset($hours[$project->id]) ? $hours[$project->id] : $emptyHour; - - /* Process the tasks. */ - $project->tasks = isset($tasks[$project->id]) ? $tasks[$project->id] : array(); - } - else - { - unset($projects[$key]); - } - } - - return $stats; - } - - /** - * Get project by id. - * - * @param int $projectID - * @access public - * @return void - */ - public function getById($projectID) - { - $project = $this->dao->findById((int)$projectID)->from(TABLE_PROJECT)->fetch(); - if(!$project) return false; - $total = $this->dao->select(' - SUM(estimate) AS totalEstimate, - SUM(consumed) AS totalConsumed, - SUM(`left`) AS totalLeft') - ->from(TABLE_TASK) - ->where('project')->eq((int)$projectID) - ->andWhere('status')->ne('cancel') - ->andWhere('deleted')->eq(0) - ->fetch(); - $project->days = $project->days ? $project->days : ''; - $project->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('project')->eq($project->id)->fetch('totalHours'); - $project->totalEstimate = round($total->totalEstimate, 1); - $project->totalConsumed = round($total->totalConsumed, 1); - $project->totalLeft = round($total->totalLeft, 1); - $project->desc = $this->loadModel('file')->setImgSize($project->desc); - $project->goal = $this->loadModel('file')->setImgSize($project->goal); - return $project; - } - - /** - * Get the default managers for a project from it's related products. - * - * @param int $projectID - * @access public - * @return object - */ - public function getDefaultManagers($projectID) - { - $managers = $this->dao->select('PO,QM,RM')->from(TABLE_PRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') - ->where('t2.project')->eq($projectID) - ->fetch(); - if($managers) return $managers; - - $managers->PO = ''; - $managers->QM = ''; - $managers->RM = ''; - return $managers; - } - - /** - * Get products of a project. - * - * @param int $projectID - * @access public - * @return array - */ - public function getProducts($projectID) - { - return $this->dao->select('t2.id, t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t1.project')->eq((int)$projectID) - ->fetchPairs(); - } - - /** - * Update products of a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function updateProducts($projectID) - { - $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$projectID)->exec(); - if(!isset($_POST['products'])) return; - $products = array_unique($_POST['products']); - foreach($products as $productID) - { - $data->project = $projectID; - $data->product = $productID; - $this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec(); - } - } - - /** - * Get related projects - * - * @param int $projectID - * @access public - * @return array - */ - public function getRelatedProjects($projectID) - { - $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$projectID)->fetchAll('product'); - if(!$products) return array(); - $products = array_keys($products); - return $this->dao->select('t1.id, t1.name')->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2') - ->on('t1.id = t2.project') - ->where('t2.product')->in($products) - ->andWhere('t1.id')->ne((int)$projectID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy('t1.id') - ->fetchPairs(); - } - - /** - * Get rasks can be imported. - * - * @param int $projectID - * @access public - * @return array - */ - public function getTasks2Imported($projectID) - { - $this->loadModel('task'); - $releatedProjects = $this->getRelatedProjects($projectID); - if(!$releatedProjects) return array(); - $tasks = array(); - foreach($releatedProjects as $releatedProjectID => $releatedProjectName) - { - $projectTasks = $this->task->getProjectTasks($releatedProjectID, 'wait,doing,cancel'); - if(!$projectTasks) continue; - $tasks = array_merge($tasks, $projectTasks); - } - return $tasks; - } - - /** - * Import tasks. - * - * @param int $projectID - * @access public - * @return void - */ - public function importTask($projectID) - { - $this->loadModel('task'); - - /* Update tasks. */ - $tasks = $this->dao->select('id, project, assignedTo, story, consumed,status')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id'); - foreach($tasks as $task) - { - /* Save the assignedToes and stories, should linked to project. */ - $assignedToes[$task->assignedTo] = $task->project; - $stories[$task->story] = $task->story; - - $data = new stdclass(); - $data->project = $projectID; - - if($task->status == 'cancel') - { - $data->canceledBy = ''; - $data->canceledDate = NULL; - } - - $data->status = $task->consumed > 0 ? 'doing' : 'wait'; - $data->statusCustom = strpos(TASKMODEL::CUSTOM_STATUS_ORDER, $data->status) + 1; - $this->dao->update(TABLE_TASK)->data($data)->where('id')->in($this->post->tasks)->exec(); - $this->loadModel('action')->create('task', $task->id, 'moved', '', $task->project); - } - - /* Remove empty story. */ - unset($stories[0]); - - /* Add members to project team. */ - $teamMembers = $this->getTeamMemberPairs($projectID); - foreach($assignedToes as $account => $preProjectID) - { - if(!isset($teamMembers[$account])) - { - $role = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($preProjectID)->andWhere('account')->eq($account)->fetch(); - $role->project = $projectID; - $role->join = helper::today(); - $this->dao->insert(TABLE_TEAM)->data($role)->exec(); - } - } - - /* Link stories. */ - $projectStories = $this->loadModel('story')->getProjectStoryPairs($projectID); - foreach($stories as $storyID) - { - if(!isset($projectStories[$storyID])) - { - $story = $this->dao->findById($storyID)->fields("$projectID as project, id as story, product, version")->from(TABLE_STORY)->fetch(); - $this->dao->insert(TABLE_PROJECTSTORY)->data($story)->exec(); - } - } - } - - /** - * Import task from Bug. - * - * @param int $projectID - * @access public - * @return void - */ - public function importBug($projectID) - { - $this->loadModel('bug'); - $bugLang = $this->app->loadLang('bug'); - $this->loadModel('task'); - $this->loadModel('story'); - - $now = helper::now(); - $BugToTasks = fixer::input('post')->get(); - foreach($BugToTasks->import as $key => $value) - { - $bug = $this->bug->getById($key); - $task->project = $projectID; - $task->story = $bug->story; - $task->storyVersion = $bug->story; - $task->fromBug = $key; - $task->name = $bug->title; - $task->type = 'devel'; - $task->pri = $BugToTasks->pri[$key]; - $task->consumed = 0; - $task->status = 'wait'; - $task->statusCustom = strpos(taskModel::CUSTOM_STATUS_ORDER, 'wait') + 1; - $task->desc = $bugLang->bug->resolve . ':' . '#' . html::a(helper::createLink('bug', 'view', "bugID=$key"), sprintf('%03d', $key)); - $task->openedDate = $now; - $task->openedBy = $this->app->user->account; - if(!empty($BugToTasks->estimate[$key])) - { - $task->estimate = $BugToTasks->estimate[$key]; - $task->left = $task->estimate; - } - if(!empty($BugToTasks->assignedTo[$key])) - { - $task->assignedTo = $BugToTasks->assignedTo[$key]; - $task->assignedDate = $now; - } - $this->dao->insert(TABLE_TASK)->data($task)->checkIF($BugToTasks->estimate[$key] != '', 'estimate', 'float')->exec(); - - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - - $taskID = $this->dao->lastInsertID(); - if($task->story != false) $this->story->setStage($task->story); - $actionID = $this->loadModel('action')->create('task', $taskID, 'Opened', ''); - $this->action->create('bug', $key, 'Totask', '', $taskID); - $this->dao->update(TABLE_BUG)->set('toTask')->eq($taskID)->where('id')->eq($key)->exec(); - $mails[$key]->taskID = $taskID; - $mails[$key]->actionID = $actionID; - } - return $mails; - } - - /** - * Get child projects. - * - * @param int $projectID - * @access public - * @return void - */ - public function getChildProjects($projectID) - { - return $this->dao->select('id, name')->from(TABLE_PROJECT)->where('parent')->eq((int)$projectID)->fetchPairs(); - } - - /** - * Update childs. - * - * @param int $projectID - * @access public - * @return void - */ - public function updateChilds($projectID) - { - $sql = "UPDATE " . TABLE_PROJECT . " SET parent = 0 WHERE parent = '$projectID'"; - $this->dbh->exec($sql); - if(!isset($_POST['childs'])) return; - $childs = array_unique($_POST['childs']); - foreach($childs as $childProjectID) - { - $sql = "UPDATE " . TABLE_PROJECT . " SET parent = '$projectID' WHERE id = '$childProjectID'"; - $this->dbh->query($sql); - } - } - - /** - * Link story. - * - * @param int $projectID - * @access public - * @return void - */ - public function linkStory($projectID) - { - if($this->post->stories == false) return false; - $this->loadModel('action'); - $versions = $this->loadModel('story')->getVersions($this->post->stories); - foreach($this->post->stories as $key => $storyID) - { - $productID = $this->post->products[$key]; - $data->project = $projectID; - $data->product = $productID; - $data->story = $storyID; - $data->version = $versions[$storyID]; - $this->dao->insert(TABLE_PROJECTSTORY)->data($data)->exec(); - $this->story->setStage($storyID); - $this->action->create('story', $storyID, 'linked2project', '', $projectID); - } - } - - /** - * Unlink story. - * - * @param int $projectID - * @param int $storyID - * @access public - * @return void - */ - public function unlinkStory($projectID, $storyID) - { - $this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('story')->eq($storyID)->limit(1)->exec(); - $this->loadModel('story')->setStage($storyID); - $this->loadModel('action')->create('story', $storyID, 'unlinkedfromproject', '', $projectID); - $tasks = $this->dao->select('id')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('project')->eq($projectID)->andWhere('status')->in('wait,doing')->fetchPairs('id'); - $this->dao->update(TABLE_TASK)->set('status')->eq('cancel')->where('id')->in($tasks)->exec(); - foreach($tasks as $taskID) - { - $changes = $this->loadModel('task')->cancel($taskID); - $actionID = $this->action->create('task', $taskID, 'Canceled'); - $this->action->logHistory($actionID, $changes); - } - } - - /** - * Get team members. - * - * @param int $projectID - * @access public - * @return array - */ - public function getTeamMembers($projectID) - { - return $this->dao->select('t1.*, t1.hours * t1.days AS totalHours, t2.realname')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') - ->where('t1.project')->eq((int)$projectID) - ->andWHere('t2.company')->eq($this->app->company->id) - ->fetchAll('account'); - } - - /** - * Get team members in pair. - * - * @param int $projectID - * @param string $params - * @access public - * @return array - */ - public function getTeamMemberPairs($projectID, $params = '') - { - $users = $this->dao->select('t1.account, t2.realname')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') - ->where('t1.project')->eq((int)$projectID) - ->andWHere('t2.company')->eq($this->app->company->id) - ->beginIF($params == 'nodeleted') - ->andWhere('t2.deleted')->eq(0) - ->fi() - ->fetchPairs(); - if(!$users) return array(); - foreach($users as $account => $realName) - { - $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; - $users[$account] = $firstLetter . ($realName ? $realName : $account); - } - return array('' => '') + $users; - } - - /** - * Manage team members. - * - * @param int $projectID - * @access public - * @return void - */ - public function manageMembers($projectID) - { - extract($_POST); - - $accounts = array_unique($accounts); - foreach($accounts as $key => $account) - { - if(empty($account)) continue; - - $member->role = $roles[$key]; - $member->days = $days[$key]; - $member->hours = $hours[$key]; - $mode = $modes[$key]; - - if($mode == 'update') - { - $this->dao->update(TABLE_TEAM)->data($member)->where('project')->eq((int)$projectID)->andWhere('account')->eq($account)->exec(); - } - else - { - $member->project = (int)$projectID; - $member->account = $account; - $member->join = helper::today(); - $this->dao->insert(TABLE_TEAM)->data($member)->exec(); - } - } - } - - /** - * Unlink a member. - * - * @param int $projectID - * @param string $account - * @access public - * @return void - */ - public function unlinkMember($projectID, $account) - { - $this->dao->delete()->from(TABLE_TEAM)->where('project')->eq((int)$projectID)->andWhere('account')->eq($account)->exec(); - } - - /** - * Compute burn of a project. - * - * @access public - * @return array - */ - public function computeBurn() - { - $today = helper::today(); - $burns = array(); - - $projects = $this->dao->select('id, name')->from(TABLE_PROJECT) - ->where("end >= '$today'") - ->orWhere('end')->eq('0000-00-00') - ->fetchPairs(); - if(!$projects) return $burns; - - $burns = $this->dao->select("project, '$today' AS date, sum(`left`) AS `left`, SUM(consumed) AS `consumed`") - ->from(TABLE_TASK) - ->where('project')->in(array_keys($projects)) - ->andWhere('deleted')->eq('0') - ->andWhere('status')->notin('cancel,closed') - ->groupBy('project') - ->fetchAll(); - - foreach($burns as $Key => $burn) - { - $this->dao->replace(TABLE_BURN)->data($burn)->exec(); - $burn->projectName = $projects[$burn->project]; - } - return $burns; - } - - /** - * Get data of burn down chart. - * - * @param int $projectID - * @param int $itemCounts - * @access public - * @return array - */ - public function getBurnData($projectID = 0, $itemCounts = 30) - { - /* Get project and burn counts. */ - $project = $this->getById($projectID); - $burnCounts = $this->dao->select('count(*) AS counts')->from(TABLE_BURN)->where('project')->eq($projectID)->fetch('counts'); - - /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ - $sql = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID); - if($burnCounts > $itemCounts) - { - $sets = $sql->orderBy('date DESC')->limit($itemCounts)->fetchAll('name'); - $sets = array_reverse($sets); - } - else - { - /* The burnCounts < itemCounts, after getting from the db, padding left dates. */ - $sets = $sql->orderBy('date ASC')->fetchAll('name'); - $current = helper::today(); - if($project->end != '0000-00-00') - { - $period = helper::diffDate($project->end, $project->begin) + 1; - $counts = $period > $itemCounts ? $itemCounts : $period; - } - else - { - $counts = $itemCounts; - } - - for($i = 0; $i < $counts - $burnCounts; $i ++) - { - if(helper::diffDate($current, $project->end) > 0) break; - if(!isset($sets[$current])) - { - $sets[$current]->name = $current; - $sets[$current]->value = ''; - } - $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); - $current = $nextDay; - } - } - foreach($sets as $set) $set->name = substr($set->name, 5); - return $sets; - } - - public function getBurnDataFlot($projectID = 0, $itemCounts = 30) - { - /* Get project and burn counts. */ - $project = $this->getById($projectID); - $burnCounts = $this->dao->select('count(*) AS counts')->from(TABLE_BURN)->where('project')->eq($projectID)->fetch('counts'); - - /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ - $sql = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID); - if($burnCounts > $itemCounts) - { - $sets = $sql->orderBy('date DESC')->limit($itemCounts)->fetchAll('name'); - $sets = array_reverse($sets); - } - else - { - /* The burnCounts < itemCounts, after getting from the db, padding left dates. */ - $sets = $sql->orderBy('date ASC')->fetchAll('name'); - $current = helper::today(); - if($project->end != '0000-00-00') - { - $period = helper::diffDate($project->end, $project->begin) + 1; - $counts = $period > $itemCounts ? $itemCounts : $period; - } - else - { - $counts = $itemCounts; - } - - for($i = 0; $i < $counts - $burnCounts; $i ++) - { - if(helper::diffDate($current, $project->end) > 0) break; - if(!isset($sets[$current])) - { - $sets[$current]->name = $current; - $sets[$current]->value = ''; - } - $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); - $current = $nextDay; - } - } - $count = 0; - foreach($sets as $set) - { - $set->name = (string)strtotime("$set->name UTC") . '000'; - $count ++; - } - $sets['count'] = $count; - return $sets; - } - - /** - * Get taskes by search. - * - * @param string $condition - * @param object $pager - * @param string $orderBy - * @access public - * @return array - */ - public function getSearchTasks($condition, $pager, $orderBy) - { - $taskIdList = $this->dao->select('id') - ->from(TABLE_TASK) - ->where($condition) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - - $tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') - ->where('t1.deleted')->eq(0) - ->andWhere('t1.id')->in(array_keys($taskIdList)) - ->orderBy($orderBy) - ->fetchAll(); - return $tasks; - } - - /** - * Get bugs by search in project. - * - * @param int $products - * @param int $projectID - * @param int $sql - * @param int $pager - * @param int $orderBy - * @access public - * @return void - */ - public function getSearchBugs($products, $projectID, $sql, $pager, $orderBy) - { - return $this->dao->select('*')->from(TABLE_BUG) - ->where($sql) - ->andWhere('status')->eq('active') - ->andWhere('toTask')->eq(0) - ->andWhere('tostory')->eq(0) - ->beginIF(!empty($products))->andWhere('product')->in(array_keys($products))->fi() - ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * Get resolved bugs of a project - * - * @param int $projectID - * @access public - * @return array - */ - public function getResolvedBugs($projectID) - { - $project = $this->getById($projectID); - $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs('product'); - return $this->dao->select('id, title, status')->from(TABLE_BUG) - ->where('status')->eq('resolved') - ->andWhere('resolvedDate')->ge($project->begin) - ->andWhere('resolution')->eq('fixed') - ->andWhere('product')->in($products) - ->fetchAll(); - } -} + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> +app->user->account . ','; + if(strpos($this->app->company->admins, $account) !== false) return true; + + /* If project is open, return true. */ + if($project->acl == 'open') return true; + + /* Get team members. */ + $teamMembers = $this->getTeamMemberPairs($project->id); + + /* If project is private, only members can access. */ + if($project->acl == 'private') + { + return isset($teamMembers[$this->app->user->account]); + } + + /* Project's acl is custom, check the groups. */ + if($project->acl == 'custom') + { + if(isset($teamMembers[$this->app->user->account])) return true; + $userGroups = $this->loadModel('user')->getGroups($this->app->user->account); + $projectGroups = explode(',', $project->whitelist); + foreach($userGroups as $groupID) + { + if(in_array($groupID, $projectGroups)) return true; + } + return false; + } + } + + /** + * Set menu. + * + * @param array $projects + * @param int $projectID + * @access public + * @return void + */ + public function setMenu($projects, $projectID) + { + /* Check the privilege. */ + if($projects and !isset($projects[$projectID]) and !$this->checkPriv($this->getById($projectID))) + { + echo(js::alert($this->lang->project->accessDenied)); + die(js::locate('back')); + } + + $moduleName = $this->app->getModuleName(); + $methodName = $this->app->getMethodName(); + $selectHtml = $this->select($projects, $projectID, $moduleName, $methodName); + foreach($this->lang->project->menu as $key => $menu) + { + $replace = $key == 'list' ? $selectHtml . $this->lang->arrow : $projectID; + common::setMenuVars($this->lang->project->menu, $key, $replace); + } + } + + /** + * Create the select code of projects. + * + * @param array $projects + * @param int $projectID + * @param string $currentModule + * @param string $currentMethod + * @access public + * @return string + */ + public function select($projects, $projectID, $currentModule, $currentMethod) + { + /* See product's model method:select. */ + $switchCode = "switchProject($('#projectID').val(), '$currentModule', '$currentMethod');"; + $onchange = "onchange=\"$switchCode\""; + $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; + $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; + $selectHtml = html::select('projectID', $projects, $projectID, "tabindex=2 $onchange $onkeypress"); + $selectHtml .= html::commonButton($this->lang->go, "id='projectSwitcher' tabindex=3 $onclick"); + return $selectHtml; + } + + /** + * Save the project id user last visited to session. + * + * @param int $projectID + * @param array $projects + * @access public + * @return int + */ + public function saveState($projectID, $projects) + { + if($projectID > 0) $this->session->set('project', (int)$projectID); + if($projectID == 0 and $this->cookie->lastProject) $this->session->set('project', (int)$this->cookie->lastProject); + if($projectID == 0 and $this->session->project == '') $this->session->set('project', $projects[0]); + if(!in_array($this->session->project, $projects)) $this->session->set('project', $projects[0]); + return $this->session->project; + } + + /** + * Create a project. + * + * @access public + * @return void + */ + public function create() + { + $this->lang->project->team = $this->lang->project->teamname; + $project = fixer::input('post') + ->stripTags('name, code, team') + ->setIF($this->post->acl != 'custom', 'whitelist', '') + ->join('whitelist', ',') + ->remove('products') + ->get(); + $this->dao->insert(TABLE_PROJECT)->data($project) + ->autoCheck($skipFields = 'begin,end') + ->batchcheck($this->config->project->create->requiredFields, 'notempty') + ->checkIF($project->begin != '', 'begin', 'date') + ->checkIF($project->end != '', 'end', 'date') + ->checkIF($project->end != '', 'end', 'gt', $project->begin) + ->check('name', 'unique') + ->check('code', 'unique') + ->exec(); + + /* Add the creater to the team. */ + if(!dao::isError()) + { + $projectID = $this->dao->lastInsertId(); + $member->project = $projectID; + $member->account = $this->app->user->account; + $member->join = helper::today(); + $member->days = $project->days; + $member->hours = $this->config->project->defaultWorkhours; + $this->dao->insert(TABLE_TEAM)->data($member)->exec(); + return $projectID; + } + } + + /** + * Update a project. + * + * @param int $projectID + * @access public + * @return array + */ + public function update($projectID) + { + $oldProject = $this->getById($projectID); + $team = $this->getTeamMemberPairs($projectID); + $this->lang->project->team = $this->lang->project->teamname; + $projectID = (int)$projectID; + $project = fixer::input('post') + ->stripTags('name, code, team') + ->setIF($this->post->begin == '0000-00-00', 'begin', '') + ->setIF($this->post->end == '0000-00-00', 'end', '') + ->setIF($this->post->acl != 'custom', 'whitelist', '') + ->join('whitelist', ',') + ->remove('products') + ->get(); + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck($skipFields = 'begin,end') + ->batchcheck($this->config->project->edit->requiredFields, 'notempty') + ->checkIF($project->begin != '', 'begin', 'date') + ->checkIF($project->end != '', 'end', 'date') + ->checkIF($project->end != '', 'end', 'gt', $project->begin) + ->check('name', 'unique', "id!=$projectID") + ->check('code', 'unique', "id!=$projectID") + ->where('id')->eq($projectID) + ->limit(1) + ->exec(); + foreach($project as $fieldName => $value) + { + if($fieldName == 'PO' or $fieldName == 'PM' or $fieldName == 'QM' or $fieldName == 'RM' ) + { + if(!empty($value) and !isset($team[$value])) + { + $member->project = (int)$projectID; + $member->account = $value; + $member->join = helper::today(); + $member->role = $fieldName; + $member->days = $project->days; + $member->hours = $this->config->project->defaultWorkhours; + $this->dao->insert(TABLE_TEAM)->data($member)->exec(); + } + } + } + if(!dao::isError()) return common::createChanges($oldProject, $project); + } + + /** + * Get project pairs. + * + * @param string $mode all|noclosed or empty + * @access public + * @return array + */ + public function getPairs($mode = '') + { + $orderBy = !empty($this->config->project->orderBy) ? $this->config->project->orderBy : 'status, id desc'; + $mode .= $this->cookie->projectMode; + $projects = $this->dao->select('*')->from(TABLE_PROJECT) + ->where('iscat')->eq(0) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->fetchAll(); + $pairs = array(); + foreach($projects as $project) + { + if(strpos($mode, 'noclosed') !== false and $project->status == 'done') continue; + if($this->checkPriv($project)) + { + if(strpos($mode, 'nocode') === false and $project->code) + { + $firstChar = strtoupper(substr($project->code, 0, 1)); + if(ord($firstChar) < 127) $project->name = $firstChar . ':' . $project->name; + } + $pairs[$project->id] = $project->name; + } + } + + /* If the pairs is empty, to make sure there's an project in the pairs. */ + if(empty($pairs) and isset($projects[0]) and $this->checkPriv($projects[0])) + { + $firstProject = $projects[0]; + $pairs[$firstProject->id] = $firstProject->name; + } + return $pairs; + } + + /** + * Get project lists. + * + * @param string $status all|undone|wait|running + * @param int $limit + * @access public + * @return array + */ + public function getList($status = 'all', $limit = 0, $productID = 0) + { + if($productID != 0) + { + return $this->dao->select('t2.*') + ->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.product')->eq($productID) + ->andWhere('t2.deleted')->eq(0) + ->andWhere('t2.iscat')->eq(0) + ->beginIF($status == 'undone')->andWhere('t2.status')->ne('done')->fi() + ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() + ->orderBy('status, id desc') + ->beginIF($limit)->limit($limit)->fi() + ->fetchAll('id'); + } + else + { + return $this->dao->select('*')->from(TABLE_PROJECT)->where('iscat')->eq(0) + ->beginIF($status == 'undone')->andWhere('status')->ne('done')->fi() + ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy('status, id') + ->beginIF($limit)->limit($limit)->fi() + ->fetchAll('id'); + } + } + + /** + * Get projects lists grouped by product. + * + * @access public + * @return array + */ + public function getProductGroupList() + { + $list = $this->dao->select('t1.id, t1.name, t2.product')->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project') + ->where('t1.deleted')->eq(0) + ->orderBy('t1.id') + ->fetchGroup('product'); + + foreach($list as $id => $product) + { + foreach($product as $ID => $project) + { + if(!$this->checkPriv($this->getById($project->id))) + { + unset($list[$id][$ID]); + } + } + } + + return $list; + } + + /** + * Get project stats. + * + * @param string $status + * @access public + * @return array + */ + public function getProjectStats($status = 'undone', $productID = 0) + { + $this->loadModel('report'); + + $projects = $this->getList($status, 0, $productID); + $stats = array(); + + /* Get total estimate, consumed and left hours of project. */ + $emptyHour = (object)array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0); + $hours = $this->dao->select('project, SUM(estimate) AS totalEstimate, SUM(consumed) AS totalConsumed') + ->from(TABLE_TASK) + ->where('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->groupBy('project') + ->fetchAll('project'); + + $lefts = $this->dao->select('project, SUM(`left`) AS totalLeft') + ->from(TABLE_TASK) + ->where('project')->in(array_keys($projects)) + ->andWhere('closedReason')->ne('cancel') + ->andWhere('status')->ne('cancel') + ->andWhere('deleted')->eq(0) + ->groupBy('project') + ->fetchAll('project'); + foreach($lefts as $projectID => $projectLefts) $hours[$projectID]->totalLeft = $projectLefts->totalLeft; + + /* Round them. */ + foreach($hours as $hour) + { + $hour->totalEstimate = round($hour->totalEstimate, 1); + $hour->totalConsumed = round($hour->totalConsumed, 1); + $hour->totalLeft = round($hour->totalLeft, 1); + $hour->totalReal = $hour->totalConsumed + $hour->totalLeft; + $hour->progress = $hour->totalReal ? round($hour->totalConsumed / $hour->totalReal, 3) * 100 : 0; + } + + /* Get tasks stats group by status. */ + $tasks = $this->dao->select('project, status, count(status) AS count') + ->from(TABLE_TASK) + ->where('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq(0) + ->groupBy('project, status') + ->fetchGroup('project', 'status'); + + /* Process projects. */ + foreach($projects as $key => $project) + { + if($this->checkPriv($project)) + { + // Process the end time. + $project->end = date(DT_DATE4, strtotime($project->end)); + + /* Process the burns. */ + $project->burns = array(); + $burnData = $this->getBurnData($project->id); + foreach($burnData as $data) $project->burns[] = $data->value; + $stats[] = $project; + + /* Process the hours. */ + $project->hours = isset($hours[$project->id]) ? $hours[$project->id] : $emptyHour; + + /* Process the tasks. */ + $project->tasks = isset($tasks[$project->id]) ? $tasks[$project->id] : array(); + } + else + { + unset($projects[$key]); + } + } + + return $stats; + } + + /** + * Get project by id. + * + * @param int $projectID + * @access public + * @return void + */ + public function getById($projectID) + { + $project = $this->dao->findById((int)$projectID)->from(TABLE_PROJECT)->fetch(); + if(!$project) return false; + $total = $this->dao->select(' + SUM(estimate) AS totalEstimate, + SUM(consumed) AS totalConsumed, + SUM(`left`) AS totalLeft') + ->from(TABLE_TASK) + ->where('project')->eq((int)$projectID) + ->andWhere('status')->ne('cancel') + ->andWhere('deleted')->eq(0) + ->fetch(); + $project->days = $project->days ? $project->days : ''; + $project->totalHours = $this->dao->select('sum(days * hours) AS totalHours')->from(TABLE_TEAM)->where('project')->eq($project->id)->fetch('totalHours'); + $project->totalEstimate = round($total->totalEstimate, 1); + $project->totalConsumed = round($total->totalConsumed, 1); + $project->totalLeft = round($total->totalLeft, 1); + $project->desc = $this->loadModel('file')->setImgSize($project->desc); + $project->goal = $this->loadModel('file')->setImgSize($project->goal); + return $project; + } + + /** + * Get the default managers for a project from it's related products. + * + * @param int $projectID + * @access public + * @return object + */ + public function getDefaultManagers($projectID) + { + $managers = $this->dao->select('PO,QM,RM')->from(TABLE_PRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') + ->where('t2.project')->eq($projectID) + ->fetch(); + if($managers) return $managers; + + $managers->PO = ''; + $managers->QM = ''; + $managers->RM = ''; + return $managers; + } + + /** + * Get products of a project. + * + * @param int $projectID + * @access public + * @return array + */ + public function getProducts($projectID) + { + return $this->dao->select('t2.id, t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t1.project')->eq((int)$projectID) + ->fetchPairs(); + } + + /** + * Update products of a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function updateProducts($projectID) + { + $this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$projectID)->exec(); + if(!isset($_POST['products'])) return; + $products = array_unique($_POST['products']); + foreach($products as $productID) + { + $data->project = $projectID; + $data->product = $productID; + $this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec(); + } + } + + /** + * Get related projects + * + * @param int $projectID + * @access public + * @return array + */ + public function getRelatedProjects($projectID) + { + $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$projectID)->fetchAll('product'); + if(!$products) return array(); + $products = array_keys($products); + return $this->dao->select('t1.id, t1.name')->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2') + ->on('t1.id = t2.project') + ->where('t2.product')->in($products) + ->andWhere('t1.id')->ne((int)$projectID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('t1.id') + ->fetchPairs(); + } + + /** + * Get rasks can be imported. + * + * @param int $projectID + * @access public + * @return array + */ + public function getTasks2Imported($projectID) + { + $this->loadModel('task'); + $releatedProjects = $this->getRelatedProjects($projectID); + if(!$releatedProjects) return array(); + $tasks = array(); + foreach($releatedProjects as $releatedProjectID => $releatedProjectName) + { + $projectTasks = $this->task->getProjectTasks($releatedProjectID, 'wait,doing,cancel'); + if(!$projectTasks) continue; + $tasks = array_merge($tasks, $projectTasks); + } + return $tasks; + } + + /** + * Import tasks. + * + * @param int $projectID + * @access public + * @return void + */ + public function importTask($projectID) + { + $this->loadModel('task'); + + /* Update tasks. */ + $tasks = $this->dao->select('id, project, assignedTo, story, consumed,status')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id'); + foreach($tasks as $task) + { + /* Save the assignedToes and stories, should linked to project. */ + $assignedToes[$task->assignedTo] = $task->project; + $stories[$task->story] = $task->story; + + $data = new stdclass(); + $data->project = $projectID; + + if($task->status == 'cancel') + { + $data->canceledBy = ''; + $data->canceledDate = NULL; + } + + $data->status = $task->consumed > 0 ? 'doing' : 'wait'; + $data->statusCustom = strpos(TASKMODEL::CUSTOM_STATUS_ORDER, $data->status) + 1; + $this->dao->update(TABLE_TASK)->data($data)->where('id')->in($this->post->tasks)->exec(); + $this->loadModel('action')->create('task', $task->id, 'moved', '', $task->project); + } + + /* Remove empty story. */ + unset($stories[0]); + + /* Add members to project team. */ + $teamMembers = $this->getTeamMemberPairs($projectID); + foreach($assignedToes as $account => $preProjectID) + { + if(!isset($teamMembers[$account])) + { + $role = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($preProjectID)->andWhere('account')->eq($account)->fetch(); + $role->project = $projectID; + $role->join = helper::today(); + $this->dao->insert(TABLE_TEAM)->data($role)->exec(); + } + } + + /* Link stories. */ + $projectStories = $this->loadModel('story')->getProjectStoryPairs($projectID); + foreach($stories as $storyID) + { + if(!isset($projectStories[$storyID])) + { + $story = $this->dao->findById($storyID)->fields("$projectID as project, id as story, product, version")->from(TABLE_STORY)->fetch(); + $this->dao->insert(TABLE_PROJECTSTORY)->data($story)->exec(); + } + } + } + + /** + * Import task from Bug. + * + * @param int $projectID + * @access public + * @return void + */ + public function importBug($projectID) + { + $this->loadModel('bug'); + $bugLang = $this->app->loadLang('bug'); + $this->loadModel('task'); + $this->loadModel('story'); + + $now = helper::now(); + $BugToTasks = fixer::input('post')->get(); + foreach($BugToTasks->import as $key => $value) + { + $bug = $this->bug->getById($key); + $task->project = $projectID; + $task->story = $bug->story; + $task->storyVersion = $bug->story; + $task->fromBug = $key; + $task->name = $bug->title; + $task->type = 'devel'; + $task->pri = $BugToTasks->pri[$key]; + $task->consumed = 0; + $task->status = 'wait'; + $task->statusCustom = strpos(taskModel::CUSTOM_STATUS_ORDER, 'wait') + 1; + $task->desc = $bugLang->bug->resolve . ':' . '#' . html::a(helper::createLink('bug', 'view', "bugID=$key"), sprintf('%03d', $key)); + $task->openedDate = $now; + $task->openedBy = $this->app->user->account; + if(!empty($BugToTasks->estimate[$key])) + { + $task->estimate = $BugToTasks->estimate[$key]; + $task->left = $task->estimate; + } + if(!empty($BugToTasks->assignedTo[$key])) + { + $task->assignedTo = $BugToTasks->assignedTo[$key]; + $task->assignedDate = $now; + } + $this->dao->insert(TABLE_TASK)->data($task)->checkIF($BugToTasks->estimate[$key] != '', 'estimate', 'float')->exec(); + + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + + $taskID = $this->dao->lastInsertID(); + if($task->story != false) $this->story->setStage($task->story); + $actionID = $this->loadModel('action')->create('task', $taskID, 'Opened', ''); + $this->action->create('bug', $key, 'Totask', '', $taskID); + $this->dao->update(TABLE_BUG)->set('toTask')->eq($taskID)->where('id')->eq($key)->exec(); + $mails[$key]->taskID = $taskID; + $mails[$key]->actionID = $actionID; + } + return $mails; + } + + /** + * Get child projects. + * + * @param int $projectID + * @access public + * @return void + */ + public function getChildProjects($projectID) + { + return $this->dao->select('id, name')->from(TABLE_PROJECT)->where('parent')->eq((int)$projectID)->fetchPairs(); + } + + /** + * Update childs. + * + * @param int $projectID + * @access public + * @return void + */ + public function updateChilds($projectID) + { + $sql = "UPDATE " . TABLE_PROJECT . " SET parent = 0 WHERE parent = '$projectID'"; + $this->dbh->exec($sql); + if(!isset($_POST['childs'])) return; + $childs = array_unique($_POST['childs']); + foreach($childs as $childProjectID) + { + $sql = "UPDATE " . TABLE_PROJECT . " SET parent = '$projectID' WHERE id = '$childProjectID'"; + $this->dbh->query($sql); + } + } + + /** + * Link story. + * + * @param int $projectID + * @access public + * @return void + */ + public function linkStory($projectID) + { + if($this->post->stories == false) return false; + $this->loadModel('action'); + $versions = $this->loadModel('story')->getVersions($this->post->stories); + foreach($this->post->stories as $key => $storyID) + { + $productID = $this->post->products[$key]; + $data->project = $projectID; + $data->product = $productID; + $data->story = $storyID; + $data->version = $versions[$storyID]; + $this->dao->insert(TABLE_PROJECTSTORY)->data($data)->exec(); + $this->story->setStage($storyID); + $this->action->create('story', $storyID, 'linked2project', '', $projectID); + } + } + + /** + * Unlink story. + * + * @param int $projectID + * @param int $storyID + * @access public + * @return void + */ + public function unlinkStory($projectID, $storyID) + { + $this->dao->delete()->from(TABLE_PROJECTSTORY)->where('project')->eq($projectID)->andWhere('story')->eq($storyID)->limit(1)->exec(); + $this->loadModel('story')->setStage($storyID); + $this->loadModel('action')->create('story', $storyID, 'unlinkedfromproject', '', $projectID); + $tasks = $this->dao->select('id')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('project')->eq($projectID)->andWhere('status')->in('wait,doing')->fetchPairs('id'); + $this->dao->update(TABLE_TASK)->set('status')->eq('cancel')->where('id')->in($tasks)->exec(); + foreach($tasks as $taskID) + { + $changes = $this->loadModel('task')->cancel($taskID); + $actionID = $this->action->create('task', $taskID, 'Canceled'); + $this->action->logHistory($actionID, $changes); + } + } + + /** + * Get team members. + * + * @param int $projectID + * @access public + * @return array + */ + public function getTeamMembers($projectID) + { + return $this->dao->select('t1.*, t1.hours * t1.days AS totalHours, t2.realname')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') + ->where('t1.project')->eq((int)$projectID) + ->andWHere('t2.company')->eq($this->app->company->id) + ->fetchAll('account'); + } + + /** + * Get team members in pair. + * + * @param int $projectID + * @param string $params + * @access public + * @return array + */ + public function getTeamMemberPairs($projectID, $params = '') + { + $users = $this->dao->select('t1.account, t2.realname')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') + ->where('t1.project')->eq((int)$projectID) + ->andWHere('t2.company')->eq($this->app->company->id) + ->beginIF($params == 'nodeleted') + ->andWhere('t2.deleted')->eq(0) + ->fi() + ->fetchPairs(); + if(!$users) return array(); + foreach($users as $account => $realName) + { + $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; + $users[$account] = $firstLetter . ($realName ? $realName : $account); + } + return array('' => '') + $users; + } + + /** + * Manage team members. + * + * @param int $projectID + * @access public + * @return void + */ + public function manageMembers($projectID) + { + extract($_POST); + + $accounts = array_unique($accounts); + foreach($accounts as $key => $account) + { + if(empty($account)) continue; + + $member->role = $roles[$key]; + $member->days = $days[$key]; + $member->hours = $hours[$key]; + $mode = $modes[$key]; + + if($mode == 'update') + { + $this->dao->update(TABLE_TEAM)->data($member)->where('project')->eq((int)$projectID)->andWhere('account')->eq($account)->exec(); + } + else + { + $member->project = (int)$projectID; + $member->account = $account; + $member->join = helper::today(); + $this->dao->insert(TABLE_TEAM)->data($member)->exec(); + } + } + } + + /** + * Unlink a member. + * + * @param int $projectID + * @param string $account + * @access public + * @return void + */ + public function unlinkMember($projectID, $account) + { + $this->dao->delete()->from(TABLE_TEAM)->where('project')->eq((int)$projectID)->andWhere('account')->eq($account)->exec(); + } + + /** + * Compute burn of a project. + * + * @access public + * @return array + */ + public function computeBurn() + { + $today = helper::today(); + $burns = array(); + + $projects = $this->dao->select('id, name')->from(TABLE_PROJECT) + ->where("end >= '$today'") + ->orWhere('end')->eq('0000-00-00') + ->fetchPairs(); + if(!$projects) return $burns; + + $burns = $this->dao->select("project, '$today' AS date, sum(`left`) AS `left`, SUM(consumed) AS `consumed`") + ->from(TABLE_TASK) + ->where('project')->in(array_keys($projects)) + ->andWhere('deleted')->eq('0') + ->andWhere('status')->notin('cancel,closed') + ->groupBy('project') + ->fetchAll(); + + foreach($burns as $Key => $burn) + { + $this->dao->replace(TABLE_BURN)->data($burn)->exec(); + $burn->projectName = $projects[$burn->project]; + } + return $burns; + } + + /** + * Get data of burn down chart. + * + * @param int $projectID + * @param int $itemCounts + * @access public + * @return array + */ + public function getBurnData($projectID = 0, $itemCounts = 30) + { + /* Get project and burn counts. */ + $project = $this->getById($projectID); + $burnCounts = $this->dao->select('count(*) AS counts')->from(TABLE_BURN)->where('project')->eq($projectID)->fetch('counts'); + + /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ + $sql = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID); + if($burnCounts > $itemCounts) + { + $sets = $sql->orderBy('date DESC')->limit($itemCounts)->fetchAll('name'); + $sets = array_reverse($sets); + } + else + { + /* The burnCounts < itemCounts, after getting from the db, padding left dates. */ + $sets = $sql->orderBy('date ASC')->fetchAll('name'); + $current = helper::today(); + if($project->end != '0000-00-00') + { + $period = helper::diffDate($project->end, $project->begin) + 1; + $counts = $period > $itemCounts ? $itemCounts : $period; + } + else + { + $counts = $itemCounts; + } + + for($i = 0; $i < $counts - $burnCounts; $i ++) + { + if(helper::diffDate($current, $project->end) > 0) break; + if(!isset($sets[$current])) + { + $sets[$current]->name = $current; + $sets[$current]->value = ''; + } + $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); + $current = $nextDay; + } + } + foreach($sets as $set) $set->name = substr($set->name, 5); + return $sets; + } + + public function getBurnDataFlot($projectID = 0, $itemCounts = 30) + { + /* Get project and burn counts. */ + $project = $this->getById($projectID); + $burnCounts = $this->dao->select('count(*) AS counts')->from(TABLE_BURN)->where('project')->eq($projectID)->fetch('counts'); + + /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ + $sql = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID); + if($burnCounts > $itemCounts) + { + $sets = $sql->orderBy('date DESC')->limit($itemCounts)->fetchAll('name'); + $sets = array_reverse($sets); + } + else + { + /* The burnCounts < itemCounts, after getting from the db, padding left dates. */ + $sets = $sql->orderBy('date ASC')->fetchAll('name'); + $current = helper::today(); + if($project->end != '0000-00-00') + { + $period = helper::diffDate($project->end, $project->begin) + 1; + $counts = $period > $itemCounts ? $itemCounts : $period; + } + else + { + $counts = $itemCounts; + } + + for($i = 0; $i < $counts - $burnCounts; $i ++) + { + if(helper::diffDate($current, $project->end) > 0) break; + if(!isset($sets[$current])) + { + $sets[$current]->name = $current; + $sets[$current]->value = ''; + } + $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); + $current = $nextDay; + } + } + $count = 0; + foreach($sets as $set) + { + $set->name = (string)strtotime("$set->name UTC") . '000'; + $count ++; + } + $sets['count'] = $count; + return $sets; + } + + /** + * Get taskes by search. + * + * @param string $condition + * @param object $pager + * @param string $orderBy + * @access public + * @return array + */ + public function getSearchTasks($condition, $pager, $orderBy) + { + $taskIdList = $this->dao->select('id') + ->from(TABLE_TASK) + ->where($condition) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + + $tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') + ->where('t1.deleted')->eq(0) + ->andWhere('t1.id')->in(array_keys($taskIdList)) + ->orderBy($orderBy) + ->fetchAll(); + return $tasks; + } + + /** + * Get bugs by search in project. + * + * @param int $products + * @param int $projectID + * @param int $sql + * @param int $pager + * @param int $orderBy + * @access public + * @return void + */ + public function getSearchBugs($products, $projectID, $sql, $pager, $orderBy) + { + return $this->dao->select('*')->from(TABLE_BUG) + ->where($sql) + ->andWhere('status')->eq('active') + ->andWhere('toTask')->eq(0) + ->andWhere('tostory')->eq(0) + ->beginIF(!empty($products))->andWhere('product')->in(array_keys($products))->fi() + ->beginIF(empty($products))->andWhere('project')->eq($projectID)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * Get resolved bugs of a project + * + * @param int $projectID + * @access public + * @return array + */ + public function getResolvedBugs($projectID) + { + $project = $this->getById($projectID); + $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->fetchPairs('product'); + return $this->dao->select('id, title, status')->from(TABLE_BUG) + ->where('status')->eq('resolved') + ->andWhere('resolvedDate')->ge($project->begin) + ->andWhere('resolution')->eq('fixed') + ->andWhere('product')->in($products) + ->fetchAll(); + } +} diff --git a/module/project/view/browse.html.php b/module/project/view/browse.html.php index 1e4fa08f52..992ea1bba2 100644 --- a/module/project/view/browse.html.php +++ b/module/project/view/browse.html.php @@ -1,154 +1,154 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          -
          - - - - - - - - - - - - - - - - - - - - - - -
          - project->selectProject;?> - id, 'onchange="selectProject(this.value);" style="width:200px"');?> -
          project->name;?>name;?>
          project->code;?>code;?>
          project->begin;?>begin;?>
          project->end;?>end;?>
          - createLink('project', 'edit', "projectID=$project->id"), $lang->project->edit); - if(common::hasPriv('project', 'delete')) echo html::a($this->createLink('project', 'delete', "projectID=$project->id"), $lang->project->delete, 'hiddenwin'); - //echo html::a($this->createLink('tree', 'browse', "productID=$productID&view=product"), $lang->tree->manage); - ?> -
          - - - - - -
          - project->products;?> -
          - $productName) echo html::a($this->createLink('product', 'browse', "productID=$productID"), $productName) . '
          ';?> -
          - createLink('project', 'manageproducts', "projectID=$project->id"), $lang->project->manageProducts); - if(common::hasPriv('project', 'linkstory')) echo html::a($this->createLink('project', 'linkstory', "projectID=$project->id"), $lang->project->linkStory); - ?> -
          -
          - - - - - - - - - - $lang->actions";?> - - - - - - - - - - " . html::a($this->createLink('project', 'unlinkmember', "projectID=$project->id&account=$member->account"), $lang->project->unlinkMember, 'hiddenwin') . '';?> - - - -
          - project->team . $lang->colon . $project->team; ?> -
          team->account;?>team->role;?>team->joinDate;?>team->workingHour;?>
          - createLink('user', 'view', "account=$member->account"), $member->realname); - else echo $member->realname; - ?> - role;?>joinDate, 2);?>workingHour;?>
          -
          - createLink('project', 'managemembers', "projectID=$project->id"), $lang->project->manageMembers) . '
          ';?> -
          - -
          -
          -
          -
          -
            - $project->name"; - echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=task"), $lang->project->tasks) . "
          • "; - echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=story"), $lang->project->stories) . "
          • "; - //echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=bug"), $lang->project->bugs) . "
          • "; - //echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=burn"), $lang->project->burndown) . "
          • "; - echo << -$("#{$tabID}tab").addClass('active'); - -EOT; - ?> -
          - -
          createLink('task', 'create', "project=$project->id"), $lang->task->create);?>
          - -
          createLink('project', 'linkstory', "project=$project->id"), $lang->project->linkStory);?>
          - -
          - -
          -
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          +
          + + + + + + + + + + + + + + + + + + + + + + +
          + project->selectProject;?> + id, 'onchange="selectProject(this.value);" style="width:200px"');?> +
          project->name;?>name;?>
          project->code;?>code;?>
          project->begin;?>begin;?>
          project->end;?>end;?>
          + createLink('project', 'edit', "projectID=$project->id"), $lang->project->edit); + if(common::hasPriv('project', 'delete')) echo html::a($this->createLink('project', 'delete', "projectID=$project->id"), $lang->project->delete, 'hiddenwin'); + //echo html::a($this->createLink('tree', 'browse', "productID=$productID&view=product"), $lang->tree->manage); + ?> +
          + + + + + +
          + project->products;?> +
          + $productName) echo html::a($this->createLink('product', 'browse', "productID=$productID"), $productName) . '
          ';?> +
          + createLink('project', 'manageproducts', "projectID=$project->id"), $lang->project->manageProducts); + if(common::hasPriv('project', 'linkstory')) echo html::a($this->createLink('project', 'linkstory', "projectID=$project->id"), $lang->project->linkStory); + ?> +
          +
          + + + + + + + + + + $lang->actions";?> + + + + + + + + + + " . html::a($this->createLink('project', 'unlinkmember', "projectID=$project->id&account=$member->account"), $lang->project->unlinkMember, 'hiddenwin') . '';?> + + + +
          + project->team . $lang->colon . $project->team; ?> +
          team->account;?>team->role;?>team->joinDate;?>team->workingHour;?>
          + createLink('user', 'view', "account=$member->account"), $member->realname); + else echo $member->realname; + ?> + role;?>joinDate, 2);?>workingHour;?>
          +
          + createLink('project', 'managemembers', "projectID=$project->id"), $lang->project->manageMembers) . '
          ';?> +
          + +
          +
          +
          +
          +
            + $project->name"; + echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=task"), $lang->project->tasks) . "
          • "; + echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=story"), $lang->project->stories) . "
          • "; + //echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=bug"), $lang->project->bugs) . "
          • "; + //echo "
          • " . html::a($this->createLink('project', 'browse', "projectID=$project->id&tabID=burn"), $lang->project->burndown) . "
          • "; + echo << +$("#{$tabID}tab").addClass('active'); + +EOT; + ?> +
          + +
          createLink('task', 'create', "project=$project->id"), $lang->task->create);?>
          + +
          createLink('project', 'linkstory', "project=$project->id"), $lang->project->linkStory);?>
          + +
          + +
          +
          +
          + diff --git a/module/project/view/bug.html.php b/module/project/view/bug.html.php index 03dded5348..c18f37359f 100644 --- a/module/project/view/bug.html.php +++ b/module/project/view/bug.html.php @@ -1,63 +1,63 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - id}&orderBy=%s&build=$buildID&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          - project->bug; - if($build) echo '(Build:' . $build->name . ')'; - ?> -
          -
          id", $lang->bug->create);?>
          -
          idAB);?>bug->severityAB);?> priAB);?> bug->title);?> openedByAB);?> assignedToAB);?> bug->resolvedBy);?>bug->resolutionAB);?>actions;?>
          createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> - id"; - if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; - if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; - common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); - ?> -
          show();?>
          - - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + id}&orderBy=%s&build=$buildID&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          + project->bug; + if($build) echo '(Build:' . $build->name . ')'; + ?> +
          +
          id", $lang->bug->create);?>
          +
          idAB);?>bug->severityAB);?> priAB);?> bug->title);?> openedByAB);?> assignedToAB);?> bug->resolvedBy);?>bug->resolutionAB);?>actions;?>
          createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> + id"; + if(!($bug->status == 'active' and common::printLink('bug', 'resolve', $params, $lang->bug->buttonResolve))) echo $lang->bug->buttonResolve . ' '; + if(!($bug->status == 'resolved' and common::printLink('bug', 'close', $params, $lang->bug->buttonClose))) echo $lang->bug->buttonClose . ' '; + common::printLink('bug', 'edit', $params, $lang->bug->buttonEdit); + ?> +
          show();?>
          + + diff --git a/module/project/view/build.html.php b/module/project/view/build.html.php index 2946eda68a..baecbb725a 100644 --- a/module/project/view/build.html.php +++ b/module/project/view/build.html.php @@ -1,54 +1,54 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          project->build;?>
          -
          id", $lang->build->create);?>
          -
          build->id;?>build->product;?>build->name;?>build->scmPath;?>build->filePath;?>build->date;?>build->builder;?>actions;?>
          id;?>productName;?>createLink('build', 'view', "build=$build->id"), $build->name);?>scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>date?>builder]?> - id&build=$build->id", $lang->testtask->create); - common::printLink('project', 'bug', "project=$project->id&orderBy=status&build=$build->id", $lang->project->viewBug); - common::printLink('build', 'edit', "buildID=$build->id", $lang->edit); - common::printLink('build', 'delete', "buildID=$build->id", $lang->delete, 'hiddenwin'); - ?> -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          project->build;?>
          +
          id", $lang->build->create);?>
          +
          build->id;?>build->product;?>build->name;?>build->scmPath;?>build->filePath;?>build->date;?>build->builder;?>actions;?>
          id;?>productName;?>createLink('build', 'view', "build=$build->id"), $build->name);?>scmPath, 'http') === 0 ? printf(html::a($build->scmPath)) : printf($build->scmPath);?>filePath, 'http') === 0 ? printf(html::a($build->filePath)) : printf($build->filePath);?>date?>builder]?> + id&build=$build->id", $lang->testtask->create); + common::printLink('project', 'bug', "project=$project->id&orderBy=status&build=$build->id", $lang->project->viewBug); + common::printLink('build', 'edit', "buildID=$build->id", $lang->edit); + common::printLink('build', 'delete', "buildID=$build->id", $lang->delete, 'hiddenwin'); + ?> +
          + diff --git a/module/project/view/burn.html.php b/module/project/view/burn.html.php index aa7b12e30d..23954406d3 100644 --- a/module/project/view/burn.html.php +++ b/module/project/view/burn.html.php @@ -1,21 +1,21 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - project->computeBurn, 'hiddenwin'); - printf($lang->project->howToUpdateBurn, $this->createLink('help', 'field', 'module=project&method-burn&field=updateburn')); - ?> -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + project->computeBurn, 'hiddenwin'); + printf($lang->project->howToUpdateBurn, $this->createLink('help', 'field', 'module=project&method-burn&field=updateburn')); + ?> +
          + diff --git a/module/project/view/computeburn.html.php b/module/project/view/computeburn.html.php index 00e115219a..fd8d3e2bac 100644 --- a/module/project/view/computeburn.html.php +++ b/module/project/view/computeburn.html.php @@ -1,18 +1,18 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> -project . "\t" . $burn->projectName . "\t" . $burn->date . "\t" . $burn->left . "\n"; -} -?> + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> +project . "\t" . $burn->projectName . "\t" . $burn->date . "\t" . $burn->left . "\n"; +} +?> diff --git a/module/project/view/create.html.php b/module/project/view/create.html.php index e19fd23491..f3a13fb01b 100644 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -1,87 +1,87 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          project->create;?>
          project->name;?>
          project->code;?>
          project->begin;?>
          project->end;?>
          project->days;?>
          project->teamname;?>
          project->manageProducts;?>
          project->goal;?>
          project->desc;?>
          project->acl;?>project->aclList, 'open', "onclick='setWhite(this.value);'"));?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          project->create;?>
          project->name;?>
          project->code;?>
          project->begin;?>
          project->end;?>
          project->days;?>
          project->teamname;?>
          project->manageProducts;?>
          project->goal;?>
          project->desc;?>
          project->acl;?>project->aclList, 'open', "onclick='setWhite(this.value);'"));?>
          +
          + diff --git a/module/project/view/doc.html.php b/module/project/view/doc.html.php index 02ebe9ebff..aa9165566a 100644 --- a/module/project/view/doc.html.php +++ b/module/project/view/doc.html.php @@ -1,51 +1,51 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - $doc):?> - createLink('doc', 'view', "docID=$doc->id"); - $canView = common::hasPriv('doc', 'view'); - ?> - - - - - - - - - - -
          id&from=project", $lang->doc->create);?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module]);?>title);?>addedBy];?>addedDate;?> - id}"; - if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; - if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; - ?> -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + $doc):?> + createLink('doc', 'view', "docID=$doc->id"); + $canView = common::hasPriv('doc', 'view'); + ?> + + + + + + + + + + +
          id&from=project", $lang->doc->create);?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module]);?>title);?>addedBy];?>addedDate;?> + id}"; + if(!common::printLink('doc', 'edit', $vars, $lang->edit)) echo $lang->edit; + if(!common::printLink('doc', 'delete', $vars, $lang->delete, 'hiddenwin')) echo $lang->delete; + ?> +
          + diff --git a/module/project/view/dynamic.html.php b/module/project/view/dynamic.html.php index 5c7899015c..d708729b6a 100755 --- a/module/project/view/dynamic.html.php +++ b/module/project/view/dynamic.html.php @@ -1,56 +1,56 @@ -dynamic view file of dashboard module of ZenTaoPMS. - * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) - * @license LGPL (http://www.gnu.org/licenses/lgpl.html) - * @author Chunsheng Wang - * @package dashboard - * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ - * @link http://www.zentao.net - */ -?> - - -
          - ' . html::a(inlink('dynamic', "projectID=$projectID&type=today"), $lang->action->dynamic->today) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=yesterday"), $lang->action->dynamic->yesterday) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=thisweek"), $lang->action->dynamic->thisWeek) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=lastweek"), $lang->action->dynamic->lastWeek) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=thismonth"), $lang->action->dynamic->thisMonth) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; - echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=all"), $lang->action->dynamic->all) . ''; - echo "" . html::select('account', $users, $account, "onchange=changeUser(this.value,$projectID)") . ''; - ?> -
          - - - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - -
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @license LGPL (http://www.gnu.org/licenses/lgpl.html) + * @author Chunsheng Wang + * @package dashboard + * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ + * @link http://www.zentao.net + */ +?> + + +
          + ' . html::a(inlink('dynamic', "projectID=$projectID&type=today"), $lang->action->dynamic->today) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=yesterday"), $lang->action->dynamic->yesterday) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=twodaysago"), $lang->action->dynamic->twoDaysAgo) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=thisweek"), $lang->action->dynamic->thisWeek) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=lastweek"), $lang->action->dynamic->lastWeek) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=thismonth"), $lang->action->dynamic->thisMonth) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=lastmonth"), $lang->action->dynamic->lastMonth) . ''; + echo '' . html::a(inlink('dynamic', "projectID=$projectID&type=all"), $lang->action->dynamic->all) . ''; + echo "" . html::select('account', $users, $account, "onchange=changeUser(this.value,$projectID)") . ''; + ?> +
          + + + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + +
          action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
          date;?>actor]) ? print($users[$action->actor]) : print($action->actor);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
          show();?>
          + + diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index e5773c002e..d63f15cbb9 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -1,86 +1,86 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - acl != 'custom') echo "class='hidden'";?>> - - - - -
          project->edit;?>
          project->name;?>name, "class='text-3'");?>
          project->code;?>code, "class='text-3'");?>
          project->begin;?>begin, "class='text-3 date' onchange='computeDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeDays()'");?>
          project->days;?>days, "class='text-3'");?>
          project->teamname;?>team, "class='text-3'");?>
          project->status;?>project->statusList, $project->status, 'class=text-3');?>
          project->PO;?>PO, 'class=text-3');?>
          project->PM;?>PM, 'class=text-3');?>
          project->QM;?>QM, 'class=text-3');?>
          project->RM;?>RM, 'class=text-3');?>
          project->manageProducts;?>
          project->goal;?>goal), "rows='6' class='area-1'");?>
          project->desc;?>desc), "rows='6' class='area-1'");?>
          project->acl;?>project->aclList, $project->acl, "onclick='setWhite(this.value);'"));?>
          project->whitelist;?>whitelist);?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + acl != 'custom') echo "class='hidden'";?>> + + + + +
          project->edit;?>
          project->name;?>name, "class='text-3'");?>
          project->code;?>code, "class='text-3'");?>
          project->begin;?>begin, "class='text-3 date' onchange='computeDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeDays()'");?>
          project->days;?>days, "class='text-3'");?>
          project->teamname;?>team, "class='text-3'");?>
          project->status;?>project->statusList, $project->status, 'class=text-3');?>
          project->PO;?>PO, 'class=text-3');?>
          project->PM;?>PM, 'class=text-3');?>
          project->QM;?>QM, 'class=text-3');?>
          project->RM;?>RM, 'class=text-3');?>
          project->manageProducts;?>
          project->goal;?>goal), "rows='6' class='area-1'");?>
          project->desc;?>desc), "rows='6' class='area-1'");?>
          project->acl;?>project->aclList, $project->acl, "onclick='setWhite(this.value);'"));?>
          project->whitelist;?>whitelist);?>
          +
          + diff --git a/module/project/view/grouptask.html.php b/module/project/view/grouptask.html.php index 491460f313..a256b33e2a 100644 --- a/module/project/view/grouptask.html.php +++ b/module/project/view/grouptask.html.php @@ -1,118 +1,118 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - $groupTasks):?> - - - - - - - - assignedTo == $app->user->account ? 'style=color:red' : '';?> - createLink('task','view',"taskID=$task->id"); ?> - estimate; - $totalConsumed += $task->consumed; - $totalLeft += ($task->status == 'cancel' ? 0 : $task->left); - - $groupEstimate += $task->estimate; - $groupConsumed += $task->consumed; - $groupLeft += ($task->status == 'cancel' ? 0 : $task->left); - - if($task->status == 'wait') - { - $statusWait++; - $groupWait++; - } - elseif($task->status == 'doing') - { - $statusDoing++; - $groupDoing++; - } - elseif($task->status == 'done') - { - $statusDone++; - $groupDone++; - } - elseif($task->status == 'closed') - { - $statusClosed++; - $groupClosed++; - } - $groupSum = count($groupTasks); - $taskSum += count($tasks); - ?> - - - - - - - - - - - - - - - - - - - -
          task->name;?> priAB;?>task->assignedTo;?>task->finishedBy;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>typeAB;?>task->deadlineAB;?>task->status;?>
           id . $lang->colon; if(common::hasPriv('task', 'view')) echo html::a($this->createLink('task', 'view', "task=$task->id"), $task->name); else echo $task->name;?>pri;?>>assignedToRealName;?>finishedBy];?>estimate;?>consumed;?>left;?>task->typeList[$task->type];?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>status;?> >task->statusList[$task->status];?> - createLink('task', 'edit', "taskid=$task->id"), $lang->edit);?> - createLink('task', 'delete', "projectID=$task->project&taskid=$task->id"), $lang->delete, 'hiddenwin');?> -
          - assignedTo])) printf($lang->project->memberHours, $users[$task->assignedTo], $members[$task->assignedTo]->totalHours);?> - project->groupSummary, $groupSum, $groupWait, $groupDoing, $groupEstimate, $groupConsumed, $groupLeft);?> -
          - - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + $groupTasks):?> + + + + + + + + assignedTo == $app->user->account ? 'style=color:red' : '';?> + createLink('task','view',"taskID=$task->id"); ?> + estimate; + $totalConsumed += $task->consumed; + $totalLeft += ($task->status == 'cancel' ? 0 : $task->left); + + $groupEstimate += $task->estimate; + $groupConsumed += $task->consumed; + $groupLeft += ($task->status == 'cancel' ? 0 : $task->left); + + if($task->status == 'wait') + { + $statusWait++; + $groupWait++; + } + elseif($task->status == 'doing') + { + $statusDoing++; + $groupDoing++; + } + elseif($task->status == 'done') + { + $statusDone++; + $groupDone++; + } + elseif($task->status == 'closed') + { + $statusClosed++; + $groupClosed++; + } + $groupSum = count($groupTasks); + $taskSum += count($tasks); + ?> + + + + + + + + + + + + + + + + + + + +
          task->name;?> priAB;?>task->assignedTo;?>task->finishedBy;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>typeAB;?>task->deadlineAB;?>task->status;?>
           id . $lang->colon; if(common::hasPriv('task', 'view')) echo html::a($this->createLink('task', 'view', "task=$task->id"), $task->name); else echo $task->name;?>pri;?>>assignedToRealName;?>finishedBy];?>estimate;?>consumed;?>left;?>task->typeList[$task->type];?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>status;?> >task->statusList[$task->status];?> + createLink('task', 'edit', "taskid=$task->id"), $lang->edit);?> + createLink('task', 'delete', "projectID=$task->project&taskid=$task->id"), $lang->delete, 'hiddenwin');?> +
          + assignedTo])) printf($lang->project->memberHours, $users[$task->assignedTo], $members[$task->assignedTo]->totalHours);?> + project->groupSummary, $groupSum, $groupWait, $groupDoing, $groupEstimate, $groupConsumed, $groupLeft);?> +
          + + diff --git a/module/project/view/importbug.html.php b/module/project/view/importbug.html.php index 69cb35f265..4a90fb8145 100755 --- a/module/project/view/importbug.html.php +++ b/module/project/view/importbug.html.php @@ -1,62 +1,62 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          import;?> idAB;?> bug->severityAB;?> priAB;?>bug->title;?>bug->statusAB;?>task->pri;?>task->assignedTo;?>task->estimate;?>
          id]", '');?> id) . html::hidden("id[$bug->id]", $bug->id);?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>id", $bug->title, '', "class='preview'");?>bug->statusList[$bug->status];?>id]", $lang->task->priList, 3);?>id]", $users, '');?>id]", '', 'size=4');?>
          show();?>
          -
          import) . html::resetButton();?>
          -
          -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          import;?> idAB;?> bug->severityAB;?> priAB;?>bug->title;?>bug->statusAB;?>task->pri;?>task->assignedTo;?>task->estimate;?>
          id]", '');?> id) . html::hidden("id[$bug->id]", $bug->id);?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>id", $bug->title, '', "class='preview'");?>bug->statusList[$bug->status];?>id]", $lang->task->priList, 3);?>id]", $users, '');?>id]", '', 'size=4');?>
          show();?>
          +
          import) . html::resetButton();?>
          +
          +
          + diff --git a/module/project/view/importtask.html.php b/module/project/view/importtask.html.php index 5a135ce1bf..1634b151c9 100644 --- a/module/project/view/importtask.html.php +++ b/module/project/view/importtask.html.php @@ -1,59 +1,59 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - assignedTo == $app->user->account ? 'style=color:red' : '';?> - - - - - - - - - - - - - - -
          task->project;?>idAB;?>priAB;?>task->name;?>task->assignedTo;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>task->story;?>import;?>
          project];?>id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>pri;?>id", $task->name)) echo $task->name;?>>assignedToRealName;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>status;?> >task->statusList[$task->status];?> - storyID) - { - if(common::hasPriv('story', 'view')) echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); - else echo $task->storyTitle; - } - ?> -
          -
          project->importTask);?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + assignedTo == $app->user->account ? 'style=color:red' : '';?> + + + + + + + + + + + + + + +
          task->project;?>idAB;?>priAB;?>task->name;?>task->assignedTo;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>task->story;?>import;?>
          project];?>id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>pri;?>id", $task->name)) echo $task->name;?>>assignedToRealName;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>status;?> >task->statusList[$task->status];?> + storyID) + { + if(common::hasPriv('story', 'view')) echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); + else echo $task->storyTitle; + } + ?> +
          +
          project->importTask);?>
          +
          + diff --git a/module/project/view/index.html.php b/module/project/view/index.html.php index ec99acb7b3..4ae81bd4c7 100644 --- a/module/project/view/index.html.php +++ b/module/project/view/index.html.php @@ -1,48 +1,48 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - -

          - project->unDoneProjects);?> - project->doneProjects);?> -

          - - - - - - - - - - - - - - - - - - - - - - - - - -
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'task', 'project=' . $project->id), $project->name, '_parent');?>code;?>end;?>project->statusList[$project->status];?>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> - hours->progress;?> height='13' text-align: /> - hours->progress;?>% - burns);?>'>
          - + + * @package ZenTaoPMS + * @version $Id$ + */ +?> + + + +

          + project->unDoneProjects);?> + project->doneProjects);?> +

          + + + + + + + + + + + + + + + + + + + + + + + + + +
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'task', 'project=' . $project->id), $project->name, '_parent');?>code;?>end;?>project->statusList[$project->status];?>hours->totalEstimate;?>hours->totalConsumed;?>hours->totalLeft;?> + hours->progress;?> height='13' text-align: /> + hours->progress;?>% + burns);?>'>
          + diff --git a/module/project/view/linkstory.html.php b/module/project/view/linkstory.html.php index 291a18cfba..814bbc49da 100644 --- a/module/project/view/linkstory.html.php +++ b/module/project/view/linkstory.html.php @@ -1,53 +1,53 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - id])) continue;?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - - - - - - - - -
          idAB;?>priAB;?>story->product;?>story->title;?>story->plan;?>openedByAB;?>story->estimateAB;?>link;?>
          id);?>story->priList[$story->pri];?>createLink('product', 'browse', "productID=$story->product"), $products[$story->product], '_blank');?>title);?>planTitle;?>openedBy];?>estimate;?> - - -
          project->whyNoStories);?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + id])) continue;?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + + + + + + + + +
          idAB;?>priAB;?>story->product;?>story->title;?>story->plan;?>openedByAB;?>story->estimateAB;?>link;?>
          id);?>story->priList[$story->pri];?>createLink('product', 'browse', "productID=$story->product"), $products[$story->product], '_blank');?>title);?>planTitle;?>openedBy];?>estimate;?> + + +
          project->whyNoStories);?>
          +
          + diff --git a/module/project/view/managechilds.html.php b/module/project/view/managechilds.html.php index 66207c30d6..e1bb56fc4b 100644 --- a/module/project/view/managechilds.html.php +++ b/module/project/view/managechilds.html.php @@ -1,29 +1,29 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          - - - - - - -
          project->manageChilds;?>
          - -
          -
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          + + + + + + +
          project->manageChilds;?>
          + +
          +
          +
          + diff --git a/module/project/view/managemembers.html.php b/module/project/view/managemembers.html.php index e640242593..704507d904 100644 --- a/module/project/view/managemembers.html.php +++ b/module/project/view/managemembers.html.php @@ -1,60 +1,60 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - $member):?> - account], 2);?> - account]);?> - - - - - - - - - PROJECTMODEL::LINK_MEMBERS_ONE_TIME) $count = PROJECTMODEL::LINK_MEMBERS_ONE_TIME; - ?> - - - - - - - - - - - - -
          project->manageMembers;?>
          team->account;?>team->role;?>team->days;?>team->hours;?>
          - - -
          - - -
          - -
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + $member):?> + account], 2);?> + account]);?> + + + + + + + + + PROJECTMODEL::LINK_MEMBERS_ONE_TIME) $count = PROJECTMODEL::LINK_MEMBERS_ONE_TIME; + ?> + + + + + + + + + + + + +
          project->manageMembers;?>
          team->account;?>team->role;?>team->days;?>team->hours;?>
          + + +
          + + +
          + +
          +
          + diff --git a/module/project/view/manageproducts.html.php b/module/project/view/manageproducts.html.php index 469766492d..dab3b90a3d 100644 --- a/module/project/view/manageproducts.html.php +++ b/module/project/view/manageproducts.html.php @@ -1,23 +1,23 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - -
          project->manageProducts;?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + +
          project->manageProducts;?>
          +
          + diff --git a/module/project/view/sendmail.html.php b/module/project/view/sendmail.html.php index 8499f675d0..0315536249 100644 --- a/module/project/view/sendmail.html.php +++ b/module/project/view/sendmail.html.php @@ -1,22 +1,22 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          - TASK #id . "=>$task->assignedTo " . html::a(common::getSysURL() . $this->createLink('task', 'view', "taskID=$task->id"), $task->name);?> -
          + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          + TASK #id . "=>$task->assignedTo " . html::a(common::getSysURL() . $this->createLink('task', 'view', "taskID=$task->id"), $task->name);?> +
          diff --git a/module/project/view/story.html.php b/module/project/view/story.html.php index b7361326fa..9742c2e7f7 100644 --- a/module/project/view/story.html.php +++ b/module/project/view/story.html.php @@ -1,74 +1,74 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - id}&orderBy=%s"; ?> - - - - - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - $totalEstimate += $story->estimate; - ?> - - - - - - - - - - - - - - - -
          -
          project->story;?>
          -
          - id", $lang->story->create); - if(common::hasPriv('project', 'linkstory')) echo html::a($this->createLink('project', 'linkstory', "project=$project->id"), $lang->project->linkStory); - ?> -
          -
          idAB);?> priAB);?> story->title);?> openedByAB);?> assignedToAB);?> story->estimateAB);?> statusAB);?> story->stageAB);?> story->taskCount;?> actions;?>
          id));?>story->priList[$story->pri];?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - id}&story={$story->id}"; - common::printLink('task', 'create', $param, $lang->project->wbs); - common::printLink('project', 'unlinkStory', $param, $lang->unlink, 'hiddenwin'); - ?> -
          product->storySummary, count($stories), $totalEstimate);?>
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + id}&orderBy=%s"; ?> + + + + + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id"); + $totalEstimate += $story->estimate; + ?> + + + + + + + + + + + + + + + +
          +
          project->story;?>
          +
          + id", $lang->story->create); + if(common::hasPriv('project', 'linkstory')) echo html::a($this->createLink('project', 'linkstory', "project=$project->id"), $lang->project->linkStory); + ?> +
          +
          idAB);?> priAB);?> story->title);?> openedByAB);?> assignedToAB);?> story->estimateAB);?> statusAB);?> story->stageAB);?> story->taskCount;?> actions;?>
          id));?>story->priList[$story->pri];?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + id}&story={$story->id}"; + common::printLink('task', 'create', $param, $lang->project->wbs); + common::printLink('project', 'unlinkStory', $param, $lang->unlink, 'hiddenwin'); + ?> +
          product->storySummary, count($stories), $totalEstimate);?>
          + diff --git a/module/project/view/task.html.php b/module/project/view/task.html.php index ddee741161..0ab4c8d7d1 100644 --- a/module/project/view/task.html.php +++ b/module/project/view/task.html.php @@ -1,124 +1,124 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          '>
          - - id&status=$status&parma=$param&orderBy=%s&recTotal=$recTotal&recPerPage=$recPerPage"; ?> - - - - - - - - - cookie->windowWidth > $this->config->wideSize):?> - - - - - - - cookie->windowWidth > $this->config->wideSize):?> - - - - - - - - - - - - - - assignedTo == $app->user->account ? 'style=color:red' : '';?> - estimate; - $totalConsumed += $task->consumed; - $totalLeft += (($task->status == 'cancel' or $task->closedReason == 'cancel') ? 0 : $task->left); - $statusVar = 'status' . ucfirst($task->status); - $$statusVar ++; - ?> - - - - - - - - - cookie->windowWidth > $this->config->wideSize):?> - - - - cookie->windowWidth > $this->config->wideSize):?> - - - - - - - - - - - cookie->windowWidth > $this->config->wideSize ? 14 : 12;?> - - - -
          idAB);?> priAB);?> task->name);?>statusAB);?> task->deadlineAB);?> task->openedDateAB);?> task->assignedToAB);?> task->finishedByAB);?> task->finishedDateAB);?> task->estimateAB);?> task->consumedAB);?> task->leftAB);?>task->story);?>actions;?>
          id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>task->priList[$task->pri];?> - fromBug != 0) echo "[BUG] "; - else echo "[TASK] "; - if(!common::printLink('task', 'view', "task=$task->id", $task->name)) echo $task->name; - ?> - status;?> > - storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion); - $storyChanged ? print("{$lang->story->changed} ") : print($lang->task->statusList[$task->status]); - ?> - delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo substr($task->deadline, 5, 6);?>openedDate, 5, 6);?> - - - >assignedToRealName;?>finishedBy];?>finishedDate, 5, 6);?> - - - estimate;?>consumed;?>left;?> - storyID and common::hasPriv('story', 'view')) $story = html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); - if($task->storyID and !common::hasPriv('story', 'view')) $story = $task->storyTitle; - echo $story; - ?> - - status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; - if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; - if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; - if($browseType == 'needconfirm') common::printLink('task', 'confirmStoryChange', "taskid=$task->id", $lang->confirm, 'hiddenwin'); - ?> -
          -
          project->taskSummary, count($tasks), $statusWait, $statusDoing, $totalEstimate, $totalConsumed, $totalLeft);?>
          - show();?> -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          '>
          + + id&status=$status&parma=$param&orderBy=%s&recTotal=$recTotal&recPerPage=$recPerPage"; ?> + + + + + + + + + cookie->windowWidth > $this->config->wideSize):?> + + + + + + + cookie->windowWidth > $this->config->wideSize):?> + + + + + + + + + + + + + + assignedTo == $app->user->account ? 'style=color:red' : '';?> + estimate; + $totalConsumed += $task->consumed; + $totalLeft += (($task->status == 'cancel' or $task->closedReason == 'cancel') ? 0 : $task->left); + $statusVar = 'status' . ucfirst($task->status); + $$statusVar ++; + ?> + + + + + + + + + cookie->windowWidth > $this->config->wideSize):?> + + + + cookie->windowWidth > $this->config->wideSize):?> + + + + + + + + + + + cookie->windowWidth > $this->config->wideSize ? 14 : 12;?> + + + +
          idAB);?> priAB);?> task->name);?>statusAB);?> task->deadlineAB);?> task->openedDateAB);?> task->assignedToAB);?> task->finishedByAB);?> task->finishedDateAB);?> task->estimateAB);?> task->consumedAB);?> task->leftAB);?>task->story);?>actions;?>
          id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>task->priList[$task->pri];?> + fromBug != 0) echo "[BUG] "; + else echo "[TASK] "; + if(!common::printLink('task', 'view', "task=$task->id", $task->name)) echo $task->name; + ?> + status;?> > + storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion); + $storyChanged ? print("{$lang->story->changed} ") : print($lang->task->statusList[$task->status]); + ?> + delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo substr($task->deadline, 5, 6);?>openedDate, 5, 6);?> + + + >assignedToRealName;?>finishedBy];?>finishedDate, 5, 6);?> + + + estimate;?>consumed;?>left;?> + storyID and common::hasPriv('story', 'view')) $story = html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); + if($task->storyID and !common::hasPriv('story', 'view')) $story = $task->storyTitle; + echo $story; + ?> + + status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; + if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; + if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; + if($browseType == 'needconfirm') common::printLink('task', 'confirmStoryChange', "taskid=$task->id", $lang->confirm, 'hiddenwin'); + ?> +
          +
          project->taskSummary, count($tasks), $statusWait, $statusDoing, $totalEstimate, $totalConsumed, $totalLeft);?>
          + show();?> +
          + diff --git a/module/project/view/team.html.php b/module/project/view/team.html.php index 53032248af..c038f3aa0e 100644 --- a/module/project/view/team.html.php +++ b/module/project/view/team.html.php @@ -1,56 +1,56 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - $lang->actions";?> - - - - - - - - - - - - - " . html::a($this->createLink('project', 'unlinkmember', "projectID=$project->id&account=$member->account"), $lang->project->unlinkMember, 'hiddenwin') . '';?> - - - - - - - - -
          team->account;?>team->role;?>team->join;?>team->days;?>team->hours;?>team->totalHours;?>
          - createLink('user', 'view', "account=$member->account"), $member->realname)) : print($member->realname); - $memberHours = $member->days * $member->hours; - $totalHours += $memberHours; - ?> - role;?>join, 2);?>days;?>hours;?>
          -
          team->totalHours . ':' . "$totalHours";?>
          -
          id", $lang->project->manageMembers);?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + $lang->actions";?> + + + + + + + + + + + + + " . html::a($this->createLink('project', 'unlinkmember', "projectID=$project->id&account=$member->account"), $lang->project->unlinkMember, 'hiddenwin') . '';?> + + + + + + + + +
          team->account;?>team->role;?>team->join;?>team->days;?>team->hours;?>team->totalHours;?>
          + createLink('user', 'view', "account=$member->account"), $member->realname)) : print($member->realname); + $memberHours = $member->days * $member->hours; + $totalHours += $memberHours; + ?> + role;?>join, 2);?>days;?>hours;?>
          +
          team->totalHours . ':' . "$totalHours";?>
          +
          id", $lang->project->manageMembers);?>
          +
          + diff --git a/module/project/view/testtask.html.php b/module/project/view/testtask.html.php index f66872187e..2594d4a75e 100644 --- a/module/project/view/testtask.html.php +++ b/module/project/view/testtask.html.php @@ -1,54 +1,54 @@ - - * @package testtask - * @version $Id: browse.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          testtask->browse;?>
          -
          testtask->create);?>
          -
          idAB;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          id"), sprintf('%03d', $task->id));?>id"), $task->name);?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>owner];?>begin?>end?>testtask->statusList[$task->status];?> - id", $lang->testtask->cases); - common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); - common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); - common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); - ?> -
          - + + * @package testtask + * @version $Id: browse.html.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          testtask->browse;?>
          +
          testtask->create);?>
          +
          idAB;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          id"), sprintf('%03d', $task->id));?>id"), $task->name);?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>owner];?>begin?>end?>testtask->statusList[$task->status];?> + id", $lang->testtask->cases); + common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); + common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); + common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); + ?> +
          + diff --git a/module/project/view/view.html.php b/module/project/view/view.html.php index e5067cf665..d4b0240cf1 100644 --- a/module/project/view/view.html.php +++ b/module/project/view/view.html.php @@ -1,96 +1,96 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          name;?>
          project->name;?>'>name;?>
          project->code;?>code;?>
          project->beginAndEnd;?>begin . ' ~ ' . $project->end;?>
          project->days;?>days;?>
          project->goal;?>goal;?>
          project->desc;?>desc;?>
          project->status;?>show($lang->project->statusList, $project->status);?>
          project->PM;?>PM];?>
          project->PO;?>PO];?>
          project->QM;?>QM];?>
          project->RM;?>RM];?>
          project->lblStats;?>project->stats, $project->totalHours, $project->totalEstimate, $project->totalConsumed, $project->totalLeft, 10)?>
          project->products;?> - $productName) echo html::a($this->createLink('product', 'browse', "productID=$productID"), $productName) . '
          ';?> -
          project->acl;?>project->aclList[$project->acl];?>
          project->whitelist;?> - whitelist); - foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; - ?> -
          -
          -session->projectList ? $this->session->projectList : inlink('task', "projectID=$project->id"); -if(!$project->deleted) -{ - common::printLink('project', 'edit', "projectID=$project->id", $lang->project->edit); - common::printLink('project', 'delete', "projectID=$project->id", $lang->project->delete, 'hiddenwin'); -} -echo html::a($browseLink, $lang->goback); -?> -
          - - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          name;?>
          project->name;?>'>name;?>
          project->code;?>code;?>
          project->beginAndEnd;?>begin . ' ~ ' . $project->end;?>
          project->days;?>days;?>
          project->goal;?>goal;?>
          project->desc;?>desc;?>
          project->status;?>show($lang->project->statusList, $project->status);?>
          project->PM;?>PM];?>
          project->PO;?>PO];?>
          project->QM;?>QM];?>
          project->RM;?>RM];?>
          project->lblStats;?>project->stats, $project->totalHours, $project->totalEstimate, $project->totalConsumed, $project->totalLeft, 10)?>
          project->products;?> + $productName) echo html::a($this->createLink('product', 'browse', "productID=$productID"), $productName) . '
          ';?> +
          project->acl;?>project->aclList[$project->acl];?>
          project->whitelist;?> + whitelist); + foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; + ?> +
          +
          +session->projectList ? $this->session->projectList : inlink('task', "projectID=$project->id"); +if(!$project->deleted) +{ + common::printLink('project', 'edit', "projectID=$project->id", $lang->project->edit); + common::printLink('project', 'delete', "projectID=$project->id", $lang->project->delete, 'hiddenwin'); +} +echo html::a($browseLink, $lang->goback); +?> +
          + + diff --git a/module/qa/control.php b/module/qa/control.php index 3baf15e775..a233144c15 100644 --- a/module/qa/control.php +++ b/module/qa/control.php @@ -1,24 +1,24 @@ - - * @package qa - * @version $Id$ - * @link http://www.zentao.net - */ -class qa extends control -{ - /** - * The index of qa, go to bug's browse page. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('bug', 'browse')); - } -} + + * @package qa + * @version $Id$ + * @link http://www.zentao.net + */ +class qa extends control +{ + /** + * The index of qa, go to bug's browse page. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('bug', 'browse')); + } +} diff --git a/module/qa/lang/en.php b/module/qa/lang/en.php index 1761a8bfd3..e9061dc30d 100644 --- a/module/qa/lang/en.php +++ b/module/qa/lang/en.php @@ -1,13 +1,13 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->qa->common = 'Test'; -$lang->qa->index = "Index"; + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->qa->common = 'Test'; +$lang->qa->index = "Index"; diff --git a/module/qa/lang/zh-cn.php b/module/qa/lang/zh-cn.php index 9e284c7af9..0ea13ee4d9 100644 --- a/module/qa/lang/zh-cn.php +++ b/module/qa/lang/zh-cn.php @@ -1,13 +1,13 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->qa->common = '测试视图'; -$lang->qa->index = "测试首页"; + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->qa->common = '测试视图'; +$lang->qa->index = "测试首页"; diff --git a/module/qa/lang/zh-tw.php b/module/qa/lang/zh-tw.php index 81f0bcbd6b..22a8e19ca9 100644 --- a/module/qa/lang/zh-tw.php +++ b/module/qa/lang/zh-tw.php @@ -1,13 +1,13 @@ - - * @package company - * @version $Id: zh-tw.php 2007 2011-07-03 08:18:16Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->qa->common = '測試視圖'; -$lang->qa->index = "測試首頁"; + + * @package company + * @version $Id: zh-tw.php 2007 2011-07-03 08:18:16Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->qa->common = '測試視圖'; +$lang->qa->index = "測試首頁"; diff --git a/module/qa/model.php b/module/qa/model.php index e65e39d146..fcf232038a 100644 --- a/module/qa/model.php +++ b/module/qa/model.php @@ -1,15 +1,15 @@ - - * @package qa - * @version $Id$ - * @link http://www.zentao.net - */ -class qaModel extends model -{ -} - + + * @package qa + * @version $Id$ + * @link http://www.zentao.net + */ +class qaModel extends model +{ +} + diff --git a/module/qa/view/index.html.php b/module/qa/view/index.html.php index 91aa8a7703..72e1811063 100644 --- a/module/qa/view/index.html.php +++ b/module/qa/view/index.html.php @@ -1,16 +1,16 @@ - - * @package company - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          - + + * @package company + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          + diff --git a/module/release/control.php b/module/release/control.php index bfec1bd511..3ee2a3cd4b 100644 --- a/module/release/control.php +++ b/module/release/control.php @@ -1,194 +1,194 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -class release extends control -{ - /** - * Common actions. - * - * @param int $productID - * @access public - * @return void - */ - public function commonAction($productID) - { - $this->loadModel('product'); - $this->view->product = $this->product->getById($productID); - $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}"), $this->view->product->name); - $this->product->setMenu($this->product->getPairs(), $productID); - } - - /** - * Browse releases. - * - * @param int $productID - * @access public - * @return void - */ - public function browse($productID) - { - $this->commonAction($productID); - $this->session->set('releaseList', $this->app->getURI(true)); - $this->view->header->title = $this->lang->release->browse; - $this->view->position[] = $this->lang->release->browse; - $this->view->releases = $this->release->getList($productID); - $this->display(); - } - - /** - * Create a release. - * - * @param int $productID - * @access public - * @return void - */ - public function create($productID) - { - if(!empty($_POST)) - { - $releaseID = $this->release->create($productID); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('release', $releaseID, 'opened'); - die(js::locate(inlink('view', "releaseID=$releaseID"), 'parent')); - } - - $builds = $this->loadModel('build')->getProductBuildPairs($productID); - unset($builds['trunk']); - - $this->commonAction($productID); - $this->view->header->title = $this->lang->release->create; - $this->view->position[] = $this->lang->release->create; - $this->view->builds = $builds; - $this->view->productID = $productID; - $this->display(); - } - - /** - * Edit a release. - * - * @param int $releaseID - * @access public - * @return void - */ - public function edit($releaseID) - { - if(!empty($_POST)) - { - $changes = $this->release->update($releaseID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('release', $releaseID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "releaseID=$releaseID"), 'parent')); - } - $this->loadModel('story'); - $this->loadModel('bug'); - $this->loadModel('project'); - $this->loadModel('build'); - - /* Get release and build. */ - $release = $this->release->getById((int)$releaseID); - $this->commonAction($release->product); - $build = $this->build->getById($release->build); - - /* Get stories and bugs. */ - $orderBy = 'status_asc, stage_asc, id_desc'; - $stories = $this->story->getProjectStories($build->project, $orderBy); - $bugs = $this->project->getResolvedBugs($build->project); - - $this->view->header->title = $this->lang->release->edit; - $this->view->position[] = $this->lang->release->edit; - $this->view->release = $release; - $this->view->build = $build; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($release->product); - unset($this->view->builds['trunk']); - $this->display(); - } - - /** - * View a release. - * - * @param int $releaseID - * @access public - * @return void - */ - public function view($releaseID) - { - $this->loadModel('story'); - $this->loadModel('bug'); - $release = $this->release->getById((int)$releaseID); - if(!$release) die(js::error($this->lang->notFound) . js::locate('back')); - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->fetchAll(); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->fetchAll(); - - $this->commonAction($release->product); - - $this->view->header->title = $this->lang->release->view; - $this->view->position[] = $this->lang->release->view; - $this->view->release = $release; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->actions = $this->loadModel('action')->getList('release', $releaseID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Delete a release. - * - * @param int $releaseID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($releaseID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->release->confirmDelete, $this->createLink('release', 'delete', "releaseID=$releaseID&confirm=yes"))); - } - else - { - $this->release->delete(TABLE_RELEASE, $releaseID); - die(js::locate($this->session->releaseList, 'parent')); - } - } - - /** - * Ajax get stories and bugs - * - * @param int $buildID - * @access public - * @return void - */ - public function ajaxGetStoriesAndBugs($buildID, $productID) - { - $orderBy = 'status_asc,stage_asc,id_desc'; - $stories = array(); - $bugs = array(); - $this->loadModel('bug'); - $build = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch(); - if(!empty($build)) - { - $stories = $this->loadModel('story')->getProjectStories($build->project, $orderBy); - $bugs = $this->loadModel('project')->getResolvedBugs($build->project); - } - $this->view->productID = $productID; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->orderBy = $orderBy; - die($this->display()); - } -} + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +class release extends control +{ + /** + * Common actions. + * + * @param int $productID + * @access public + * @return void + */ + public function commonAction($productID) + { + $this->loadModel('product'); + $this->view->product = $this->product->getById($productID); + $this->view->position[] = html::a($this->createLink('product', 'browse', "productID={$this->view->product->id}"), $this->view->product->name); + $this->product->setMenu($this->product->getPairs(), $productID); + } + + /** + * Browse releases. + * + * @param int $productID + * @access public + * @return void + */ + public function browse($productID) + { + $this->commonAction($productID); + $this->session->set('releaseList', $this->app->getURI(true)); + $this->view->header->title = $this->lang->release->browse; + $this->view->position[] = $this->lang->release->browse; + $this->view->releases = $this->release->getList($productID); + $this->display(); + } + + /** + * Create a release. + * + * @param int $productID + * @access public + * @return void + */ + public function create($productID) + { + if(!empty($_POST)) + { + $releaseID = $this->release->create($productID); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('release', $releaseID, 'opened'); + die(js::locate(inlink('view', "releaseID=$releaseID"), 'parent')); + } + + $builds = $this->loadModel('build')->getProductBuildPairs($productID); + unset($builds['trunk']); + + $this->commonAction($productID); + $this->view->header->title = $this->lang->release->create; + $this->view->position[] = $this->lang->release->create; + $this->view->builds = $builds; + $this->view->productID = $productID; + $this->display(); + } + + /** + * Edit a release. + * + * @param int $releaseID + * @access public + * @return void + */ + public function edit($releaseID) + { + if(!empty($_POST)) + { + $changes = $this->release->update($releaseID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('release', $releaseID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "releaseID=$releaseID"), 'parent')); + } + $this->loadModel('story'); + $this->loadModel('bug'); + $this->loadModel('project'); + $this->loadModel('build'); + + /* Get release and build. */ + $release = $this->release->getById((int)$releaseID); + $this->commonAction($release->product); + $build = $this->build->getById($release->build); + + /* Get stories and bugs. */ + $orderBy = 'status_asc, stage_asc, id_desc'; + $stories = $this->story->getProjectStories($build->project, $orderBy); + $bugs = $this->project->getResolvedBugs($build->project); + + $this->view->header->title = $this->lang->release->edit; + $this->view->position[] = $this->lang->release->edit; + $this->view->release = $release; + $this->view->build = $build; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($release->product); + unset($this->view->builds['trunk']); + $this->display(); + } + + /** + * View a release. + * + * @param int $releaseID + * @access public + * @return void + */ + public function view($releaseID) + { + $this->loadModel('story'); + $this->loadModel('bug'); + $release = $this->release->getById((int)$releaseID); + if(!$release) die(js::error($this->lang->notFound) . js::locate('back')); + $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->fetchAll(); + $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->fetchAll(); + + $this->commonAction($release->product); + + $this->view->header->title = $this->lang->release->view; + $this->view->position[] = $this->lang->release->view; + $this->view->release = $release; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->actions = $this->loadModel('action')->getList('release', $releaseID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Delete a release. + * + * @param int $releaseID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($releaseID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->release->confirmDelete, $this->createLink('release', 'delete', "releaseID=$releaseID&confirm=yes"))); + } + else + { + $this->release->delete(TABLE_RELEASE, $releaseID); + die(js::locate($this->session->releaseList, 'parent')); + } + } + + /** + * Ajax get stories and bugs + * + * @param int $buildID + * @access public + * @return void + */ + public function ajaxGetStoriesAndBugs($buildID, $productID) + { + $orderBy = 'status_asc,stage_asc,id_desc'; + $stories = array(); + $bugs = array(); + $this->loadModel('bug'); + $build = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch(); + if(!empty($build)) + { + $stories = $this->loadModel('story')->getProjectStories($build->project, $orderBy); + $bugs = $this->loadModel('project')->getResolvedBugs($build->project); + } + $this->view->productID = $productID; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->orderBy = $orderBy; + die($this->display()); + } +} diff --git a/module/release/lang/en.php b/module/release/lang/en.php index c872554173..a39e02408c 100644 --- a/module/release/lang/en.php +++ b/module/release/lang/en.php @@ -1,32 +1,32 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->release->common = 'Release'; -$lang->release->create = "Create"; -$lang->release->edit = "Edit"; -$lang->release->delete = "Delete"; -$lang->release->view = "Info"; -$lang->release->browse = "Browse"; - -$lang->release->confirmDelete = "Are sure to delete this release?"; - -$lang->release->id = 'ID'; -$lang->release->product = 'Product'; -$lang->release->build = 'Build'; -$lang->release->name = 'Name'; -$lang->release->date = 'Date'; -$lang->release->desc = 'Desc'; -$lang->release->linkStoriesAndBugs = 'Stories and bugs'; -$lang->release->linkStories = 'Stories'; -$lang->release->linkBugs = 'Bugs'; -$lang->release->stories = 'Linked stories'; -$lang->release->bugs = 'Linked bugs'; -$lang->release->ajaxGetStoriesAndBugs = 'API: Get storeis and bugs'; + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->release->common = 'Release'; +$lang->release->create = "Create"; +$lang->release->edit = "Edit"; +$lang->release->delete = "Delete"; +$lang->release->view = "Info"; +$lang->release->browse = "Browse"; + +$lang->release->confirmDelete = "Are sure to delete this release?"; + +$lang->release->id = 'ID'; +$lang->release->product = 'Product'; +$lang->release->build = 'Build'; +$lang->release->name = 'Name'; +$lang->release->date = 'Date'; +$lang->release->desc = 'Desc'; +$lang->release->linkStoriesAndBugs = 'Stories and bugs'; +$lang->release->linkStories = 'Stories'; +$lang->release->linkBugs = 'Bugs'; +$lang->release->stories = 'Linked stories'; +$lang->release->bugs = 'Linked bugs'; +$lang->release->ajaxGetStoriesAndBugs = 'API: Get storeis and bugs'; diff --git a/module/release/lang/zh-cn.php b/module/release/lang/zh-cn.php index ff683948c3..40d2d4dc7b 100644 --- a/module/release/lang/zh-cn.php +++ b/module/release/lang/zh-cn.php @@ -1,32 +1,32 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->release->common = '发布'; -$lang->release->create = "创建发布"; -$lang->release->edit = "编辑发布"; -$lang->release->delete = "删除发布"; -$lang->release->view = "发布详情"; -$lang->release->browse = "浏览发布"; - -$lang->release->confirmDelete = "您确认删除该release吗?"; - -$lang->release->id = 'ID'; -$lang->release->product = '产品'; -$lang->release->build = 'Build'; -$lang->release->name = '发布名称'; -$lang->release->date = '发布日期'; -$lang->release->desc = '描述'; -$lang->release->linkStoriesAndBugs = '需求和Bug'; -$lang->release->linkStories = '相关需求'; -$lang->release->linkBugs = '相关Bug'; -$lang->release->stories = '已关联需求'; -$lang->release->bugs = '已关联Bugs'; -$lang->release->ajaxGetStoriesAndBugs = '接口:获得需求和Bug'; + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->release->common = '发布'; +$lang->release->create = "创建发布"; +$lang->release->edit = "编辑发布"; +$lang->release->delete = "删除发布"; +$lang->release->view = "发布详情"; +$lang->release->browse = "浏览发布"; + +$lang->release->confirmDelete = "您确认删除该release吗?"; + +$lang->release->id = 'ID'; +$lang->release->product = '产品'; +$lang->release->build = 'Build'; +$lang->release->name = '发布名称'; +$lang->release->date = '发布日期'; +$lang->release->desc = '描述'; +$lang->release->linkStoriesAndBugs = '需求和Bug'; +$lang->release->linkStories = '相关需求'; +$lang->release->linkBugs = '相关Bug'; +$lang->release->stories = '已关联需求'; +$lang->release->bugs = '已关联Bugs'; +$lang->release->ajaxGetStoriesAndBugs = '接口:获得需求和Bug'; diff --git a/module/release/lang/zh-tw.php b/module/release/lang/zh-tw.php index 0d9389f545..425bc909eb 100644 --- a/module/release/lang/zh-tw.php +++ b/module/release/lang/zh-tw.php @@ -1,32 +1,32 @@ - - * @package release - * @version $Id: zh-tw.php 2520 2012-01-03 03:02:48Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->release->common = '發佈'; -$lang->release->create = "創建發佈"; -$lang->release->edit = "編輯發佈"; -$lang->release->delete = "刪除發佈"; -$lang->release->view = "發佈詳情"; -$lang->release->browse = "瀏覽發佈"; - -$lang->release->confirmDelete = "您確認刪除該release嗎?"; - -$lang->release->id = 'ID'; -$lang->release->product = '產品'; -$lang->release->build = 'Build'; -$lang->release->name = '發佈名稱'; -$lang->release->date = '發佈日期'; -$lang->release->desc = '描述'; -$lang->release->linkStoriesAndBugs = '需求和Bug'; -$lang->release->linkStories = '相關需求'; -$lang->release->linkBugs = '相關Bug'; -$lang->release->stories = '已關聯需求'; -$lang->release->bugs = '已關聯Bugs'; -$lang->release->ajaxGetStoriesAndBugs = '介面:獲得需求和Bug'; + + * @package release + * @version $Id: zh-tw.php 2520 2012-01-03 03:02:48Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->release->common = '發佈'; +$lang->release->create = "創建發佈"; +$lang->release->edit = "編輯發佈"; +$lang->release->delete = "刪除發佈"; +$lang->release->view = "發佈詳情"; +$lang->release->browse = "瀏覽發佈"; + +$lang->release->confirmDelete = "您確認刪除該release嗎?"; + +$lang->release->id = 'ID'; +$lang->release->product = '產品'; +$lang->release->build = 'Build'; +$lang->release->name = '發佈名稱'; +$lang->release->date = '發佈日期'; +$lang->release->desc = '描述'; +$lang->release->linkStoriesAndBugs = '需求和Bug'; +$lang->release->linkStories = '相關需求'; +$lang->release->linkBugs = '相關Bug'; +$lang->release->stories = '已關聯需求'; +$lang->release->bugs = '已關聯Bugs'; +$lang->release->ajaxGetStoriesAndBugs = '介面:獲得需求和Bug'; diff --git a/module/release/model.php b/module/release/model.php index 8ed35f7f0b..b407d4db24 100644 --- a/module/release/model.php +++ b/module/release/model.php @@ -1,102 +1,102 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->select('t1.*, t2.name as buildName, t3.name as productName') - ->from(TABLE_RELEASE)->alias('t1') - ->leftJoin(TABLE_BUILD)->alias('t2')->on('t1.build = t2.id') - ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') - ->where('t1.id')->eq((int)$releaseID) - ->orderBy('t1.id DESC') - ->fetch(); - $release->desc = $this->loadModel('file')->setImgSize($release->desc); - return $release; - } - - /** - * Get list of releases. - * - * @param int $productID - * @access public - * @return array - */ - public function getList($productID) - { - return $this->dao->select('t1.*, t2.name as productName, t3.name as buildName') - ->from(TABLE_RELEASE)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') - ->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build = t3.id') - ->where('t1.product')->eq((int)$productID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy('t1.date DESC') - ->fetchAll(); - } - - /** - * Create a release. - * - * @param int $productID - * @access public - * @return int - */ - public function create($productID) - { - $release = fixer::input('post') - ->stripTags('name') - ->add('product', (int)$productID) - ->join('stories', ',') - ->join('bugs', ',') - ->get(); - $this->dao->insert(TABLE_RELEASE)->data($release)->autoCheck()->batchCheck($this->config->release->create->requiredFields, 'notempty')->check('name','unique')->exec(); - $releaseID = $this->dao->lastInsertID(); - $this->dao->update(TABLE_STORY)->set('stage')->eq('released')->where('id')->in($release->stories)->exec(); - if(!dao::isError()) return $releaseID; - } - - /** - * Update a release. - * - * @param int $releaseID - * @access public - * @return void - */ - public function update($releaseID) - { - $oldRelease = $this->getByID($releaseID); - $release = fixer::input('post') - ->stripTags('name') - ->setDefault('stories', '') - ->setDefault('bugs', '') - ->join('stories', ',') - ->join('bugs', ',') - ->get(); - $this->dao->update(TABLE_RELEASE)->data($release) - ->autoCheck() - ->batchCheck($this->config->release->edit->requiredFields, 'notempty') - ->check('name','unique', "id != $releaseID") - ->where('id')->eq((int)$releaseID) - ->exec(); - $this->dao->update(TABLE_STORY)->set('stage')->eq('released')->where('id')->in($release->stories)->exec(); - if(!dao::isError()) return common::createChanges($oldRelease, $release); - } -} + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->select('t1.*, t2.name as buildName, t3.name as productName') + ->from(TABLE_RELEASE)->alias('t1') + ->leftJoin(TABLE_BUILD)->alias('t2')->on('t1.build = t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') + ->where('t1.id')->eq((int)$releaseID) + ->orderBy('t1.id DESC') + ->fetch(); + $release->desc = $this->loadModel('file')->setImgSize($release->desc); + return $release; + } + + /** + * Get list of releases. + * + * @param int $productID + * @access public + * @return array + */ + public function getList($productID) + { + return $this->dao->select('t1.*, t2.name as productName, t3.name as buildName') + ->from(TABLE_RELEASE)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build = t3.id') + ->where('t1.product')->eq((int)$productID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy('t1.date DESC') + ->fetchAll(); + } + + /** + * Create a release. + * + * @param int $productID + * @access public + * @return int + */ + public function create($productID) + { + $release = fixer::input('post') + ->stripTags('name') + ->add('product', (int)$productID) + ->join('stories', ',') + ->join('bugs', ',') + ->get(); + $this->dao->insert(TABLE_RELEASE)->data($release)->autoCheck()->batchCheck($this->config->release->create->requiredFields, 'notempty')->check('name','unique')->exec(); + $releaseID = $this->dao->lastInsertID(); + $this->dao->update(TABLE_STORY)->set('stage')->eq('released')->where('id')->in($release->stories)->exec(); + if(!dao::isError()) return $releaseID; + } + + /** + * Update a release. + * + * @param int $releaseID + * @access public + * @return void + */ + public function update($releaseID) + { + $oldRelease = $this->getByID($releaseID); + $release = fixer::input('post') + ->stripTags('name') + ->setDefault('stories', '') + ->setDefault('bugs', '') + ->join('stories', ',') + ->join('bugs', ',') + ->get(); + $this->dao->update(TABLE_RELEASE)->data($release) + ->autoCheck() + ->batchCheck($this->config->release->edit->requiredFields, 'notempty') + ->check('name','unique', "id != $releaseID") + ->where('id')->eq((int)$releaseID) + ->exec(); + $this->dao->update(TABLE_STORY)->set('stage')->eq('released')->where('id')->in($release->stories)->exec(); + if(!dao::isError()) return common::createChanges($oldRelease, $release); + } +} diff --git a/module/release/view/browse.html.php b/module/release/view/browse.html.php index 3e5c2f0850..3cd0d5d184 100644 --- a/module/release/view/browse.html.php +++ b/module/release/view/browse.html.php @@ -1,46 +1,46 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          release->browse;?>
          -
          id", $lang->release->create);?>
          -
          release->id;?>release->name;?>release->build;?>release->date;?>actions;?>
          id;?>id"), $release->name);?>buildName;?>date;?> - id", $lang->edit); - common::printLink('release', 'delete', "release=$release->id", $lang->delete, 'hiddenwin'); - ?> -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          release->browse;?>
          +
          id", $lang->release->create);?>
          +
          release->id;?>release->name;?>release->build;?>release->date;?>actions;?>
          id;?>id"), $release->name);?>buildName;?>date;?> + id", $lang->edit); + common::printLink('release', 'delete', "release=$release->id", $lang->delete, 'hiddenwin'); + ?> +
          + diff --git a/module/release/view/create.html.php b/module/release/view/create.html.php index cb147631d9..af90bc7667 100644 --- a/module/release/view/create.html.php +++ b/module/release/view/create.html.php @@ -1,40 +1,40 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - -
          release->create;?>
          release->name;?>
          release->build;?>
          release->date;?>
          release->desc;?>
          -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + +
          release->create;?>
          release->name;?>
          release->build;?>
          release->date;?>
          release->desc;?>
          +
          + diff --git a/module/release/view/edit.html.php b/module/release/view/edit.html.php index f38a38cd59..c829c30631 100644 --- a/module/release/view/edit.html.php +++ b/module/release/view/edit.html.php @@ -1,87 +1,87 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - -
          release->edit;?>
          release->name;?>name, "class='text-3'");?>
          release->build;?>build, "class='select-3' onchange=loadStoriesAndBugs(this.value,$release->product)"); ?>
          release->date;?>date, "class='text-3 date'");?>
          release->linkStoriesAndBugs;?> -
          -
          - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - ?> - - - - - - - -
          release->linkStories;?>
          idAB;?>story->title;?>statusAB;?>story->stageAB;?>
          stories, $story->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          -
          -
          - - - - - - - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - -
          release->linkBugs;?>
          idAB;?>bug->title;?>bug->status;?>
          bugs, $bug->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>
          -
          -
          -
          release->desc;?>desc), "rows='20' class='area-1'");?>
          product);?>
          -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + +
          release->edit;?>
          release->name;?>name, "class='text-3'");?>
          release->build;?>build, "class='select-3' onchange=loadStoriesAndBugs(this.value,$release->product)"); ?>
          release->date;?>date, "class='text-3 date'");?>
          release->linkStoriesAndBugs;?> +
          +
          + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id"); + ?> + + + + + + + +
          release->linkStories;?>
          idAB;?>story->title;?>statusAB;?>story->stageAB;?>
          stories, $story->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          +
          +
          + + + + + + + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + +
          release->linkBugs;?>
          idAB;?>bug->title;?>bug->status;?>
          bugs, $bug->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>
          +
          +
          +
          release->desc;?>desc), "rows='20' class='area-1'");?>
          product);?>
          +
          + diff --git a/module/release/view/view.html.php b/module/release/view/view.html.php index e46da5d93e..42277f4ac8 100644 --- a/module/release/view/view.html.php +++ b/module/release/view/view.html.php @@ -1,109 +1,109 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          release->view;?>
          release->product;?>productName;?>
          release->name;?>'>name;?>
          release->build;?>buildName;?>
          release->date;?>date;?>
          release->stories;?> -
          - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - - - - -
          idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
          id);?>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          -
          -
          release->bugs;?> -
          - - - - - - - - - - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - - - - - -
          idAB;?>bug->title;?>bug->status;?>openedByAB;?>bug->openedDateAB;?>bug->resolvedByAB;?>bug->resolvedDateAB;?>
          id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>openedBy];?>openedDate, 5, 11)?>resolvedBy];?>resolvedDate, 5, 11)?>
          -
          -
          release->desc;?>desc;?>
          -
          - session->releaseList ? $this->session->releaseList : inlink('browse', "productID=$release->product"); - if(!$release->deleted) - { - common::printLink('release', 'edit', "releaseID=$release->id", $lang->edit); - common::printLink('release', 'delete', "releaseID=$release->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          release->view;?>
          release->product;?>productName;?>
          release->name;?>'>name;?>
          release->build;?>buildName;?>
          release->date;?>date;?>
          release->stories;?> +
          + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + + + + +
          idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
          id);?>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          +
          +
          release->bugs;?> +
          + + + + + + + + + + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + + + + + +
          idAB;?>bug->title;?>bug->status;?>openedByAB;?>bug->openedDateAB;?>bug->resolvedByAB;?>bug->resolvedDateAB;?>
          id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>openedBy];?>openedDate, 5, 11)?>resolvedBy];?>resolvedDate, 5, 11)?>
          +
          +
          release->desc;?>desc;?>
          +
          + session->releaseList ? $this->session->releaseList : inlink('browse', "productID=$release->product"); + if(!$release->deleted) + { + common::printLink('release', 'edit', "releaseID=$release->id", $lang->edit); + common::printLink('release', 'delete', "releaseID=$release->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + + diff --git a/module/report/control.php b/module/report/control.php index a7f961c3b0..03371fab93 100644 --- a/module/report/control.php +++ b/module/report/control.php @@ -1,14 +1,14 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -class report extends control -{ -} + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +class report extends control +{ +} diff --git a/module/report/lang/en.php b/module/report/lang/en.php index eea79f2bca..f0c71a480c 100644 --- a/module/report/lang/en.php +++ b/module/report/lang/en.php @@ -1,31 +1,31 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->report->common = 'Report'; -$lang->report->item = 'Item'; -$lang->report->value = 'Value'; -$lang->report->percent = 'Percent'; -$lang->report->undefined = 'Undefined'; - -$lang->report->colors[] = 'AFD8F8'; -$lang->report->colors[] = 'F6BD0F'; -$lang->report->colors[] = '8BBA00'; -$lang->report->colors[] = 'FF8E46'; -$lang->report->colors[] = '008E8E'; -$lang->report->colors[] = 'D64646'; -$lang->report->colors[] = '8E468E'; -$lang->report->colors[] = '588526'; -$lang->report->colors[] = 'B3AA00'; -$lang->report->colors[] = '008ED6'; -$lang->report->colors[] = '9D080D'; -$lang->report->colors[] = 'A186BE'; - -$lang->report->singleColor[] = 'F6BD0F'; + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->report->common = 'Report'; +$lang->report->item = 'Item'; +$lang->report->value = 'Value'; +$lang->report->percent = 'Percent'; +$lang->report->undefined = 'Undefined'; + +$lang->report->colors[] = 'AFD8F8'; +$lang->report->colors[] = 'F6BD0F'; +$lang->report->colors[] = '8BBA00'; +$lang->report->colors[] = 'FF8E46'; +$lang->report->colors[] = '008E8E'; +$lang->report->colors[] = 'D64646'; +$lang->report->colors[] = '8E468E'; +$lang->report->colors[] = '588526'; +$lang->report->colors[] = 'B3AA00'; +$lang->report->colors[] = '008ED6'; +$lang->report->colors[] = '9D080D'; +$lang->report->colors[] = 'A186BE'; + +$lang->report->singleColor[] = 'F6BD0F'; diff --git a/module/report/lang/zh-cn.php b/module/report/lang/zh-cn.php index 9ee8426cf0..2fb2dc0fcc 100644 --- a/module/report/lang/zh-cn.php +++ b/module/report/lang/zh-cn.php @@ -1,31 +1,31 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->report->common = '报表'; -$lang->report->item = '条目'; -$lang->report->value = '值'; -$lang->report->percent = '百分比'; -$lang->report->undefined = '未设定'; - -$lang->report->colors[] = 'AFD8F8'; -$lang->report->colors[] = 'F6BD0F'; -$lang->report->colors[] = '8BBA00'; -$lang->report->colors[] = 'FF8E46'; -$lang->report->colors[] = '008E8E'; -$lang->report->colors[] = 'D64646'; -$lang->report->colors[] = '8E468E'; -$lang->report->colors[] = '588526'; -$lang->report->colors[] = 'B3AA00'; -$lang->report->colors[] = '008ED6'; -$lang->report->colors[] = '9D080D'; -$lang->report->colors[] = 'A186BE'; - -$lang->report->singleColor[] = 'F6BD0F'; + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->report->common = '报表'; +$lang->report->item = '条目'; +$lang->report->value = '值'; +$lang->report->percent = '百分比'; +$lang->report->undefined = '未设定'; + +$lang->report->colors[] = 'AFD8F8'; +$lang->report->colors[] = 'F6BD0F'; +$lang->report->colors[] = '8BBA00'; +$lang->report->colors[] = 'FF8E46'; +$lang->report->colors[] = '008E8E'; +$lang->report->colors[] = 'D64646'; +$lang->report->colors[] = '8E468E'; +$lang->report->colors[] = '588526'; +$lang->report->colors[] = 'B3AA00'; +$lang->report->colors[] = '008ED6'; +$lang->report->colors[] = '9D080D'; +$lang->report->colors[] = 'A186BE'; + +$lang->report->singleColor[] = 'F6BD0F'; diff --git a/module/report/lang/zh-tw.php b/module/report/lang/zh-tw.php index 0dbae78369..a1d8a2c5c2 100644 --- a/module/report/lang/zh-tw.php +++ b/module/report/lang/zh-tw.php @@ -1,31 +1,31 @@ - - * @package report - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->report->common = '報表'; -$lang->report->item = '條目'; -$lang->report->value = '值'; -$lang->report->percent = '百分比'; -$lang->report->undefined = '未設定'; - -$lang->report->colors[] = 'AFD8F8'; -$lang->report->colors[] = 'F6BD0F'; -$lang->report->colors[] = '8BBA00'; -$lang->report->colors[] = 'FF8E46'; -$lang->report->colors[] = '008E8E'; -$lang->report->colors[] = 'D64646'; -$lang->report->colors[] = '8E468E'; -$lang->report->colors[] = '588526'; -$lang->report->colors[] = 'B3AA00'; -$lang->report->colors[] = '008ED6'; -$lang->report->colors[] = '9D080D'; -$lang->report->colors[] = 'A186BE'; - -$lang->report->singleColor[] = 'F6BD0F'; + + * @package report + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->report->common = '報表'; +$lang->report->item = '條目'; +$lang->report->value = '值'; +$lang->report->percent = '百分比'; +$lang->report->undefined = '未設定'; + +$lang->report->colors[] = 'AFD8F8'; +$lang->report->colors[] = 'F6BD0F'; +$lang->report->colors[] = '8BBA00'; +$lang->report->colors[] = 'FF8E46'; +$lang->report->colors[] = '008E8E'; +$lang->report->colors[] = 'D64646'; +$lang->report->colors[] = '8E468E'; +$lang->report->colors[] = '588526'; +$lang->report->colors[] = 'B3AA00'; +$lang->report->colors[] = '008ED6'; +$lang->report->colors[] = '9D080D'; +$lang->report->colors[] = 'A186BE'; + +$lang->report->singleColor[] = 'F6BD0F'; diff --git a/module/report/model.php b/module/report/model.php index c22435341e..72584be0f6 100644 --- a/module/report/model.php +++ b/module/report/model.php @@ -1,231 +1,231 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->getWebRoot() . 'fusioncharts/'; - $swfFile = "fcf_$swf.swf"; - return << - - - - - - -EOT; - } - - /** - * Create the js code of chart. - * - * @param string $swf the swf type - * @param string $dataURL the date url - * @param int $width - * @param int $height - * @access public - * @return string - */ - public function createJSChart($swf, $dataXML, $width = 'auto', $height = 500) - { - $jsRoot = $this->app->getWebRoot() . 'js/'; - static $count = 0; - $count ++; - $chartRoot = $this->app->getWebRoot() . 'fusioncharts/'; - $swfFile = "fcf_$swf.swf"; - $divID = "chart{$count}div"; - $chartID = "chart{$count}"; - - $js = ''; - if($count == 1) $js = ""; - return << - -EOT; - } - - public function createJSChartFlot($projectName, $dataJSON, $count, $width = 'auto', $height = 500) - { - $this->app->loadLang('project'); - $jsRoot = $this->app->getWebRoot() . 'js/'; - $width = $width . 'px'; - $height = $height . 'px'; -return << - -

          $projectName {$this->lang->project->burn}

          -
          - -EOT; - } - - /** - * Create xml data of single charts. - * - * @param array $sets - * @param array $chartOptions - * @param array $colors - * @access public - * @return string the xml data. - */ - public function createSingleXML($sets, $chartOptions = array(), $colors = array()) - { - $data = pack("CCC", 0xef, 0xbb, 0xbf); // utf-8 bom. - $data .=""; - - $data .= ' $value) $data .= " $key='$value'"; - $data .= ">"; - - if(empty($colors)) $colors = $this->lang->report->colors; - $colorCount = count($colors); - $i = 0; - foreach($sets as $set) - { - if($i == $colorCount) $i = 0; - $color = $colors[$i]; - $i ++; - $data .= ""; - } - $data .= ""; - return $data; - } - - public function createSingleJSON($sets) - { - $data = '['; - foreach($sets as $set) - { - $data .= " [$set->name, $set->value],"; - } - $data = rtrim($data, ','); - $data .= ']'; - return $data; - } - - /** - * Create the js code to render chart. - * - * @param int $chartCount - * @access public - * @return string - */ - public function renderJsCharts($chartCount) - { - $js = ''; - return $js; - } - - /** - * Compute percent of every item. - * - * @param array $datas - * @access public - * @return array - */ - public function computePercent($datas) - { - $sum = 0; - foreach($datas as $data) $sum += $data->value; - foreach($datas as $data) $data->percent = round($data->value / $sum, 2); - return $datas; - } -} + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +?> +app->getWebRoot() . 'fusioncharts/'; + $swfFile = "fcf_$swf.swf"; + return << + + + + + + +EOT; + } + + /** + * Create the js code of chart. + * + * @param string $swf the swf type + * @param string $dataURL the date url + * @param int $width + * @param int $height + * @access public + * @return string + */ + public function createJSChart($swf, $dataXML, $width = 'auto', $height = 500) + { + $jsRoot = $this->app->getWebRoot() . 'js/'; + static $count = 0; + $count ++; + $chartRoot = $this->app->getWebRoot() . 'fusioncharts/'; + $swfFile = "fcf_$swf.swf"; + $divID = "chart{$count}div"; + $chartID = "chart{$count}"; + + $js = ''; + if($count == 1) $js = ""; + return << + +EOT; + } + + public function createJSChartFlot($projectName, $dataJSON, $count, $width = 'auto', $height = 500) + { + $this->app->loadLang('project'); + $jsRoot = $this->app->getWebRoot() . 'js/'; + $width = $width . 'px'; + $height = $height . 'px'; +return << + +

          $projectName {$this->lang->project->burn}

          +
          + +EOT; + } + + /** + * Create xml data of single charts. + * + * @param array $sets + * @param array $chartOptions + * @param array $colors + * @access public + * @return string the xml data. + */ + public function createSingleXML($sets, $chartOptions = array(), $colors = array()) + { + $data = pack("CCC", 0xef, 0xbb, 0xbf); // utf-8 bom. + $data .=""; + + $data .= ' $value) $data .= " $key='$value'"; + $data .= ">"; + + if(empty($colors)) $colors = $this->lang->report->colors; + $colorCount = count($colors); + $i = 0; + foreach($sets as $set) + { + if($i == $colorCount) $i = 0; + $color = $colors[$i]; + $i ++; + $data .= ""; + } + $data .= ""; + return $data; + } + + public function createSingleJSON($sets) + { + $data = '['; + foreach($sets as $set) + { + $data .= " [$set->name, $set->value],"; + } + $data = rtrim($data, ','); + $data .= ']'; + return $data; + } + + /** + * Create the js code to render chart. + * + * @param int $chartCount + * @access public + * @return string + */ + public function renderJsCharts($chartCount) + { + $js = ''; + return $js; + } + + /** + * Compute percent of every item. + * + * @param array $datas + * @access public + * @return array + */ + public function computePercent($datas) + { + $sum = 0; + foreach($datas as $data) $sum += $data->value; + foreach($datas as $data) $data->percent = round($data->value / $sum, 2); + return $datas; + } +} diff --git a/module/search/control.php b/module/search/control.php index c26ecacc6f..90992be7f5 100644 --- a/module/search/control.php +++ b/module/search/control.php @@ -1,116 +1,116 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -class search extends control -{ - /** - * Build search form. - * - * @param string $module - * @param array $searchFields - * @param array $fieldParams - * @param string $actionURL - * @param int $queryID - * @access public - * @return void - */ - public function buildForm($module, $searchFields, $fieldParams, $actionURL, $queryID = 0) - { - $this->search->initSession($module, $searchFields, $fieldParams); - - $this->view->module = $module; - $this->view->groupItems = $this->config->search->groupItems; - $this->view->searchFields = $searchFields; - $this->view->actionURL = $actionURL; - $this->view->fieldParams = $this->search->setDefaultParams($searchFields, $fieldParams); - $this->view->queries = $this->search->getQueryPairs($module); - $this->view->queryID = $queryID; - $this->display(); - } - - /** - * Build query - * - * @access public - * @return void - */ - public function buildQuery() - { - $this->search->buildQuery(); - die(js::locate($this->post->actionURL, 'parent')); - } - - /** - * Save search query. - * - * @access public - * @return void - */ - public function saveQuery() - { - $this->search->saveQuery(); - if(dao::isError()) die(js::error(dao::getError())); - die('success'); - } - - /** - * Delete a query - * - * @param int $queryID - * @access public - * @return void - */ - public function deleteQuery($queryID) - { - $this->dao->delete()->from(TABLE_USERQUERY)->where('id')->eq($queryID)->andWhere('account')->eq($this->app->user->account)->exec(); - die(js::reload('parent')); - } - - /** - * Create a select page of stories or tasks. - * - * @param int $productID - * @param int $projectID - * @param string $module - * @param int $moduleID - * @access public - * @return void - */ - public function select($productID, $projectID, $module, $moduleID) - { - $this->loadModel('product'); - $this->loadModel('task'); - - if($module == 'story') - { - $fieldParams = $this->config->product->search; - $moduleTitles = $projectID ? $this->loadModel('story')->getProjectStoryPairs($projectID, $productID) : $this->loadModel('story')->getProductStoryPairs($productID); - } - else if($module == 'task') - { - $fieldParams = $this->config->task->search; - $moduleTitles = $this->loadModel('task')->getProjectTaskPairs($projectID); - } - $searchFields = $fieldParams['fields']; - $fieldParams = $fieldParams['params']; - $this->search->initSession($module, $searchFields, $fieldParams); - - if(!empty($_POST['value1'])) $moduleTitles = $this->search->getBySelect($module, array_keys($moduleTitles), $_POST); - - $this->view->module = $module; - $this->view->moduleID = $moduleID; - $this->view->moduleTitles = $moduleTitles; - $this->view->searchFields = $searchFields; - $this->view->fieldParams = $this->search->setDefaultParams($searchFields, $fieldParams); - - die($this->display()); - } -} + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +class search extends control +{ + /** + * Build search form. + * + * @param string $module + * @param array $searchFields + * @param array $fieldParams + * @param string $actionURL + * @param int $queryID + * @access public + * @return void + */ + public function buildForm($module, $searchFields, $fieldParams, $actionURL, $queryID = 0) + { + $this->search->initSession($module, $searchFields, $fieldParams); + + $this->view->module = $module; + $this->view->groupItems = $this->config->search->groupItems; + $this->view->searchFields = $searchFields; + $this->view->actionURL = $actionURL; + $this->view->fieldParams = $this->search->setDefaultParams($searchFields, $fieldParams); + $this->view->queries = $this->search->getQueryPairs($module); + $this->view->queryID = $queryID; + $this->display(); + } + + /** + * Build query + * + * @access public + * @return void + */ + public function buildQuery() + { + $this->search->buildQuery(); + die(js::locate($this->post->actionURL, 'parent')); + } + + /** + * Save search query. + * + * @access public + * @return void + */ + public function saveQuery() + { + $this->search->saveQuery(); + if(dao::isError()) die(js::error(dao::getError())); + die('success'); + } + + /** + * Delete a query + * + * @param int $queryID + * @access public + * @return void + */ + public function deleteQuery($queryID) + { + $this->dao->delete()->from(TABLE_USERQUERY)->where('id')->eq($queryID)->andWhere('account')->eq($this->app->user->account)->exec(); + die(js::reload('parent')); + } + + /** + * Create a select page of stories or tasks. + * + * @param int $productID + * @param int $projectID + * @param string $module + * @param int $moduleID + * @access public + * @return void + */ + public function select($productID, $projectID, $module, $moduleID) + { + $this->loadModel('product'); + $this->loadModel('task'); + + if($module == 'story') + { + $fieldParams = $this->config->product->search; + $moduleTitles = $projectID ? $this->loadModel('story')->getProjectStoryPairs($projectID, $productID) : $this->loadModel('story')->getProductStoryPairs($productID); + } + else if($module == 'task') + { + $fieldParams = $this->config->task->search; + $moduleTitles = $this->loadModel('task')->getProjectTaskPairs($projectID); + } + $searchFields = $fieldParams['fields']; + $fieldParams = $fieldParams['params']; + $this->search->initSession($module, $searchFields, $fieldParams); + + if(!empty($_POST['value1'])) $moduleTitles = $this->search->getBySelect($module, array_keys($moduleTitles), $_POST); + + $this->view->module = $module; + $this->view->moduleID = $moduleID; + $this->view->moduleTitles = $moduleTitles; + $this->view->searchFields = $searchFields; + $this->view->fieldParams = $this->search->setDefaultParams($searchFields, $fieldParams); + + die($this->display()); + } +} diff --git a/module/search/lang/en.php b/module/search/lang/en.php index 1bf4fa0ed0..8f8cfb4a33 100644 --- a/module/search/lang/en.php +++ b/module/search/lang/en.php @@ -1,46 +1,46 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->search->common = 'Search'; -$lang->search->reset = 'Reset'; -$lang->search->more = 'More'; -$lang->search->lite = 'Lite'; -$lang->search->saveQuery = 'Save'; -$lang->search->myQuery = 'My queries'; -$lang->search->group1 = '1'; -$lang->search->group2 = '2'; -$lang->search->buildForm = 'Search form'; -$lang->search->buildQuery = 'Execute query'; -$lang->search->saveQuery = 'Save query'; -$lang->search->deleteQuery = 'Delete query'; -$lang->search->setQueryTitle = 'Please input the title(execute searching before save):'; -$lang->search->storyTitle = 'Story title'; -$lang->search->taskTitle = 'Task title'; -$lang->search->select = 'Stories/Tasks filter'; - -$lang->search->operators['='] = '='; -$lang->search->operators['!='] = '!='; -$lang->search->operators['>'] = '>'; -$lang->search->operators['>='] = '>='; -$lang->search->operators['<'] = '<'; -$lang->search->operators['<='] = '<='; -$lang->search->operators['include'] = 'include'; -$lang->search->operators['notinclude'] = 'not include'; - -$lang->search->andor['and'] = 'And'; -$lang->search->andor['or'] = 'Or'; - -$lang->search->null = 'Null'; - -$lang->userquery->title = 'Title'; -$lang->userquery->myQueries = 'My queries'; -$lang->userquery->execut = 'Execute'; -$lang->userquery->delete = 'Delete'; + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->search->common = 'Search'; +$lang->search->reset = 'Reset'; +$lang->search->more = 'More'; +$lang->search->lite = 'Lite'; +$lang->search->saveQuery = 'Save'; +$lang->search->myQuery = 'My queries'; +$lang->search->group1 = '1'; +$lang->search->group2 = '2'; +$lang->search->buildForm = 'Search form'; +$lang->search->buildQuery = 'Execute query'; +$lang->search->saveQuery = 'Save query'; +$lang->search->deleteQuery = 'Delete query'; +$lang->search->setQueryTitle = 'Please input the title(execute searching before save):'; +$lang->search->storyTitle = 'Story title'; +$lang->search->taskTitle = 'Task title'; +$lang->search->select = 'Stories/Tasks filter'; + +$lang->search->operators['='] = '='; +$lang->search->operators['!='] = '!='; +$lang->search->operators['>'] = '>'; +$lang->search->operators['>='] = '>='; +$lang->search->operators['<'] = '<'; +$lang->search->operators['<='] = '<='; +$lang->search->operators['include'] = 'include'; +$lang->search->operators['notinclude'] = 'not include'; + +$lang->search->andor['and'] = 'And'; +$lang->search->andor['or'] = 'Or'; + +$lang->search->null = 'Null'; + +$lang->userquery->title = 'Title'; +$lang->userquery->myQueries = 'My queries'; +$lang->userquery->execut = 'Execute'; +$lang->userquery->delete = 'Delete'; diff --git a/module/search/lang/zh-cn.php b/module/search/lang/zh-cn.php index 5de1259d60..3800bf3f42 100644 --- a/module/search/lang/zh-cn.php +++ b/module/search/lang/zh-cn.php @@ -1,46 +1,46 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->search->common = '搜索'; -$lang->search->reset = '重置'; -$lang->search->more = '更多'; -$lang->search->lite = '简洁'; -$lang->search->saveQuery = '保存'; -$lang->search->myQuery = '我的查询'; -$lang->search->group1 = '第一组'; -$lang->search->group2 = '第二组'; -$lang->search->buildForm = '搜索表单'; -$lang->search->buildQuery = '执行搜索'; -$lang->search->saveQuery = '保存查询'; -$lang->search->deleteQuery = '删除查询'; -$lang->search->setQueryTitle = '请输入查询标题(保存之前请先查询):'; -$lang->search->storyTitle = '需求名称'; -$lang->search->taskTitle = '任务名称'; -$lang->search->select = '需求/任务筛选'; - -$lang->search->operators['='] = '='; -$lang->search->operators['!='] = '!='; -$lang->search->operators['>'] = '>'; -$lang->search->operators['>='] = '>='; -$lang->search->operators['<'] = '<'; -$lang->search->operators['<='] = '<='; -$lang->search->operators['include'] = '包含'; -$lang->search->operators['notinclude'] = '不包含'; - -$lang->search->andor['and'] = '并且'; -$lang->search->andor['or'] = '或者'; - -$lang->search->null = '空'; - -$lang->userquery->title = '查询标题'; -$lang->userquery->myQueries = '我的查询'; -$lang->userquery->execut = '执行'; -$lang->userquery->delete = '删除'; + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->search->common = '搜索'; +$lang->search->reset = '重置'; +$lang->search->more = '更多'; +$lang->search->lite = '简洁'; +$lang->search->saveQuery = '保存'; +$lang->search->myQuery = '我的查询'; +$lang->search->group1 = '第一组'; +$lang->search->group2 = '第二组'; +$lang->search->buildForm = '搜索表单'; +$lang->search->buildQuery = '执行搜索'; +$lang->search->saveQuery = '保存查询'; +$lang->search->deleteQuery = '删除查询'; +$lang->search->setQueryTitle = '请输入查询标题(保存之前请先查询):'; +$lang->search->storyTitle = '需求名称'; +$lang->search->taskTitle = '任务名称'; +$lang->search->select = '需求/任务筛选'; + +$lang->search->operators['='] = '='; +$lang->search->operators['!='] = '!='; +$lang->search->operators['>'] = '>'; +$lang->search->operators['>='] = '>='; +$lang->search->operators['<'] = '<'; +$lang->search->operators['<='] = '<='; +$lang->search->operators['include'] = '包含'; +$lang->search->operators['notinclude'] = '不包含'; + +$lang->search->andor['and'] = '并且'; +$lang->search->andor['or'] = '或者'; + +$lang->search->null = '空'; + +$lang->userquery->title = '查询标题'; +$lang->userquery->myQueries = '我的查询'; +$lang->userquery->execut = '执行'; +$lang->userquery->delete = '删除'; diff --git a/module/search/lang/zh-tw.php b/module/search/lang/zh-tw.php index 3ce2571a7c..1ee313a830 100644 --- a/module/search/lang/zh-tw.php +++ b/module/search/lang/zh-tw.php @@ -1,45 +1,45 @@ - - * @package search - * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ - * @link http://www.zentao.net - */ -$lang->search->common = '搜索'; -$lang->search->reset = '重置'; -$lang->search->more = '更多'; -$lang->search->lite = '簡潔'; -$lang->search->saveQuery = '保存'; -$lang->search->myQuery = '我的查詢'; -$lang->search->group1 = '第一組'; -$lang->search->group2 = '第二組'; -$lang->search->buildForm = '搜索表單'; -$lang->search->buildQuery = '執行搜索'; -$lang->search->saveQuery = '保存查詢'; -$lang->search->deleteQuery = '刪除查詢'; -$lang->search->setQueryTitle = '請輸入查詢標題(保存之前請先查詢):'; -$lang->search->storyTitle = '需求名稱'; -$lang->search->taskTitle = '任務名稱'; -$lang->search->select = '需求/任務篩選'; - -$lang->search->operators['='] = '='; -$lang->search->operators['!='] = '!='; -$lang->search->operators['>'] = '>'; -$lang->search->operators['>='] = '>='; -$lang->search->operators['<'] = '<'; -$lang->search->operators['<='] = '<='; -$lang->search->operators['include'] = '包含'; - -$lang->search->andor['and'] = '並且'; -$lang->search->andor['or'] = '或者'; - -$lang->search->null = '空'; - -$lang->userquery->title = '查詢標題'; -$lang->userquery->myQueries = '我的查詢'; -$lang->userquery->execut = '執行'; -$lang->userquery->delete = '刪除'; + + * @package search + * @version $Id: zh-tw.php 1914 2011-06-24 10:11:25Z yidong@cnezsoft.com $ + * @link http://www.zentao.net + */ +$lang->search->common = '搜索'; +$lang->search->reset = '重置'; +$lang->search->more = '更多'; +$lang->search->lite = '簡潔'; +$lang->search->saveQuery = '保存'; +$lang->search->myQuery = '我的查詢'; +$lang->search->group1 = '第一組'; +$lang->search->group2 = '第二組'; +$lang->search->buildForm = '搜索表單'; +$lang->search->buildQuery = '執行搜索'; +$lang->search->saveQuery = '保存查詢'; +$lang->search->deleteQuery = '刪除查詢'; +$lang->search->setQueryTitle = '請輸入查詢標題(保存之前請先查詢):'; +$lang->search->storyTitle = '需求名稱'; +$lang->search->taskTitle = '任務名稱'; +$lang->search->select = '需求/任務篩選'; + +$lang->search->operators['='] = '='; +$lang->search->operators['!='] = '!='; +$lang->search->operators['>'] = '>'; +$lang->search->operators['>='] = '>='; +$lang->search->operators['<'] = '<'; +$lang->search->operators['<='] = '<='; +$lang->search->operators['include'] = '包含'; + +$lang->search->andor['and'] = '並且'; +$lang->search->andor['or'] = '或者'; + +$lang->search->null = '空'; + +$lang->userquery->title = '查詢標題'; +$lang->userquery->myQueries = '我的查詢'; +$lang->userquery->execut = '執行'; +$lang->userquery->delete = '刪除'; diff --git a/module/search/model.php b/module/search/model.php index 6facf57f6b..2ff13e3957 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -1,269 +1,269 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -?> -config->search->groupItems; - $groupAndOr = strtoupper($this->post->groupAndOr); - if($groupAndOr != 'AND' and $groupAndOr != 'OR') $groupAndOr = 'AND'; - - for($i = 1; $i <= $groupItems * 2; $i ++) - { - /* The and or between two groups. */ - if($i == 1) $where .= '( 1 '; - if($i == $groupItems + 1) $where .= " ) $groupAndOr ( 1 "; - - /* Set var names. */ - $fieldName = "field$i"; - $andOrName = "andOr$i"; - $operatorName = "operator$i"; - $valueName = "value$i"; - - /* Skip empty vales. */ - if($this->post->$valueName == false) continue; - if($this->post->$valueName == 'null') $this->post->$valueName = ''; // Null is special, stands to empty. - - /* Set and or. */ - $andOr = strtoupper($this->post->$andOrName); - if($andOr != 'AND' and $andOr != 'OR') $andOr = 'AND'; - $where .= " $andOr "; - - /* Set filed name. */ - $where .= '`' . $this->post->$fieldName . '` '; - - /* Set operator. */ - $value = $this->post->$valueName; - $operator = $this->post->$operatorName; - if(!isset($this->lang->search->operators[$operator])) $operator = '='; - if($operator == "include") - { - $where .= ' LIKE ' . $this->dbh->quote("%$value%"); - } - elseif($operator == "notinclude") - { - $where .= ' NOT LIKE ' . $this->dbh->quote("%$value%"); - } - else - { - $where .= $operator . ' ' . $this->dbh->quote($value) . ' '; - } - } - - $where .=" )"; - - /* Save to session. */ - $querySessionName = $this->post->module . 'Query'; - $formSessionName = $this->post->module . 'Form'; - $this->session->set($querySessionName, $where); - $this->session->set($formSessionName, $_POST); - } - - /** - * Init the search session for the first time search. - * - * @param string $module - * @param array $fields - * @param array $fieldParams - * @access public - * @return void - */ - public function initSession($module, $fields, $fieldParams) - { - $formSessionName = $module . 'Form'; - if($this->session->$formSessionName != false) return; - - for($i = 1; $i <= $this->config->search->groupItems * 2; $i ++) - { - /* Var names. */ - $fieldName = "field$i"; - $andOrName = "andOr$i"; - $operatorName = "operator$i"; - $valueName = "value$i"; - - $currentField = key($fields); - $operator = isset($fieldParams[$currentField]['operator']) ? $fieldParams[$currentField]['operator'] : '='; - - $queryForm[$fieldName] = key($fields); - $queryForm[$andOrName] = 'and'; - $queryForm[$operatorName] = $operator; - $queryForm[$valueName] = ''; - - if(!next($fields)) reset($fields); - } - $queryForm['groupAndOr'] = 'and'; - $this->session->set($formSessionName, $queryForm); - } - - /** - * Set default params for selection. - * - * @param array $fields - * @param array $params - * @access public - * @return array - */ - public function setDefaultParams($fields, $params) - { - $users = $this->loadModel('user')->getPairs(); - $products = array('' => '') + $this->loadModel('product')->getPairs(); - $projects = array('' => '') + $this->loadModel('project')->getPairs(); - $fields = array_keys($fields); - foreach($fields as $fieldName) - { - if(!isset($params[$fieldName])) $params[$fieldName] = array('operator' => '=', 'control' => 'input', 'values' => ''); - if($params[$fieldName]['values'] == 'users') $params[$fieldName]['values'] = $users; - if($params[$fieldName]['values'] == 'products') $params[$fieldName]['values'] = $products; - if($params[$fieldName]['values'] == 'projects') $params[$fieldName]['values'] = $projects; - if(is_array($params[$fieldName]['values'])) $params[$fieldName]['values'] = $params[$fieldName]['values'] + array('null' => $this->lang->search->null); - } - return $params; - } - - /** - * Get a query. - * - * @param int $queryID - * @access public - * @return string - */ - public function getQuery($queryID) - { - $query = $this->dao->findByID($queryID)->from(TABLE_USERQUERY)->fetch(); - if(!$query) return false; - $query->form = unserialize($query->form); - return $query; - } - - /** - * Save current query to db. - * - * @access public - * @return void - */ - public function saveQuery() - { - $sqlVar = $this->post->module . 'Query'; - $formVar = $this->post->module . 'Form'; - $sql = $this->session->$sqlVar; - if(!$sql) $sql = ' 1 = 1 '; - - $query = fixer::input('post') - ->specialChars('title') - ->add('account', $this->app->user->account) - ->add('form', serialize($this->session->$formVar)) - ->add('sql', $sql) - ->get(); - $this->dao->insert(TABLE_USERQUERY)->data($query)->autoCheck()->check('title', 'notempty')->exec(); - } - - /** - * Get title => id pairs of a user. - * - * @param string $module - * @access public - * @return array - */ - public function getQueryPairs($module) - { - $queries = $this->dao->select('id, title') - ->from(TABLE_USERQUERY) - ->where('account')->eq($this->app->user->account) - ->andWhere('module')->eq($module) - ->orderBy('id_asc') - ->fetchPairs(); - if(!$queries) return array('' => $this->lang->search->myQuery); - $queries = array('' => $this->lang->search->myQuery) + $queries; - return $queries; - } - - /** - * Get records by the conditon. - * - * @param string $module - * @param string $moduleIds - * @param string $conditions - * @access public - * @return array - */ - public function getBySelect($module, $moduleIds, $conditions) - { - if($module == 'story') - { - $pairs = 'id,title'; - $table = 'zt_story'; - } - else if($module == 'task') - { - $pairs = 'id,name'; - $table = 'zt_task'; - } - $query = '`' . $conditions['field1'] . '`'; - $operator = $conditions['operator1']; - $value = $conditions['value1']; - - if(!isset($this->lang->search->operators[$operator])) $operator = '='; - if($operator == "include") - { - $query .= ' LIKE ' . $this->dbh->quote("%$value%"); - } - elseif($operator == "notinclude") - { - $where .= ' NOT LIKE ' . $this->dbh->quote("%$value%"); - } - else - { - $query .= $operator . ' ' . $this->dbh->quote($value) . ' '; - } - - foreach($moduleIds as $id) - { - if(!$id) continue; - $title = $this->dao->select($pairs) - ->from($table) - ->where('id')->eq((int)$id) - ->andWhere($query) - ->fetch(); - if($title) $results[$id] = $title; - } - if(!isset($results)) return array(); - return $this->formatResults($results, $module); - } - - /** - * Format the results. - * - * @param array $results - * @param string $module - * @access private - * @return array - */ - private function formatResults($results, $module) - { - /* Get title field. */ - $title = ($module == 'story') ? 'title' : 'name'; - $resultPairs = array('' => ''); - foreach($results as $result) $resultPairs[$result->id] = $result->id . ':' . $result->$title; - return $resultPairs; - } - -} + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +?> +config->search->groupItems; + $groupAndOr = strtoupper($this->post->groupAndOr); + if($groupAndOr != 'AND' and $groupAndOr != 'OR') $groupAndOr = 'AND'; + + for($i = 1; $i <= $groupItems * 2; $i ++) + { + /* The and or between two groups. */ + if($i == 1) $where .= '( 1 '; + if($i == $groupItems + 1) $where .= " ) $groupAndOr ( 1 "; + + /* Set var names. */ + $fieldName = "field$i"; + $andOrName = "andOr$i"; + $operatorName = "operator$i"; + $valueName = "value$i"; + + /* Skip empty vales. */ + if($this->post->$valueName == false) continue; + if($this->post->$valueName == 'null') $this->post->$valueName = ''; // Null is special, stands to empty. + + /* Set and or. */ + $andOr = strtoupper($this->post->$andOrName); + if($andOr != 'AND' and $andOr != 'OR') $andOr = 'AND'; + $where .= " $andOr "; + + /* Set filed name. */ + $where .= '`' . $this->post->$fieldName . '` '; + + /* Set operator. */ + $value = $this->post->$valueName; + $operator = $this->post->$operatorName; + if(!isset($this->lang->search->operators[$operator])) $operator = '='; + if($operator == "include") + { + $where .= ' LIKE ' . $this->dbh->quote("%$value%"); + } + elseif($operator == "notinclude") + { + $where .= ' NOT LIKE ' . $this->dbh->quote("%$value%"); + } + else + { + $where .= $operator . ' ' . $this->dbh->quote($value) . ' '; + } + } + + $where .=" )"; + + /* Save to session. */ + $querySessionName = $this->post->module . 'Query'; + $formSessionName = $this->post->module . 'Form'; + $this->session->set($querySessionName, $where); + $this->session->set($formSessionName, $_POST); + } + + /** + * Init the search session for the first time search. + * + * @param string $module + * @param array $fields + * @param array $fieldParams + * @access public + * @return void + */ + public function initSession($module, $fields, $fieldParams) + { + $formSessionName = $module . 'Form'; + if($this->session->$formSessionName != false) return; + + for($i = 1; $i <= $this->config->search->groupItems * 2; $i ++) + { + /* Var names. */ + $fieldName = "field$i"; + $andOrName = "andOr$i"; + $operatorName = "operator$i"; + $valueName = "value$i"; + + $currentField = key($fields); + $operator = isset($fieldParams[$currentField]['operator']) ? $fieldParams[$currentField]['operator'] : '='; + + $queryForm[$fieldName] = key($fields); + $queryForm[$andOrName] = 'and'; + $queryForm[$operatorName] = $operator; + $queryForm[$valueName] = ''; + + if(!next($fields)) reset($fields); + } + $queryForm['groupAndOr'] = 'and'; + $this->session->set($formSessionName, $queryForm); + } + + /** + * Set default params for selection. + * + * @param array $fields + * @param array $params + * @access public + * @return array + */ + public function setDefaultParams($fields, $params) + { + $users = $this->loadModel('user')->getPairs(); + $products = array('' => '') + $this->loadModel('product')->getPairs(); + $projects = array('' => '') + $this->loadModel('project')->getPairs(); + $fields = array_keys($fields); + foreach($fields as $fieldName) + { + if(!isset($params[$fieldName])) $params[$fieldName] = array('operator' => '=', 'control' => 'input', 'values' => ''); + if($params[$fieldName]['values'] == 'users') $params[$fieldName]['values'] = $users; + if($params[$fieldName]['values'] == 'products') $params[$fieldName]['values'] = $products; + if($params[$fieldName]['values'] == 'projects') $params[$fieldName]['values'] = $projects; + if(is_array($params[$fieldName]['values'])) $params[$fieldName]['values'] = $params[$fieldName]['values'] + array('null' => $this->lang->search->null); + } + return $params; + } + + /** + * Get a query. + * + * @param int $queryID + * @access public + * @return string + */ + public function getQuery($queryID) + { + $query = $this->dao->findByID($queryID)->from(TABLE_USERQUERY)->fetch(); + if(!$query) return false; + $query->form = unserialize($query->form); + return $query; + } + + /** + * Save current query to db. + * + * @access public + * @return void + */ + public function saveQuery() + { + $sqlVar = $this->post->module . 'Query'; + $formVar = $this->post->module . 'Form'; + $sql = $this->session->$sqlVar; + if(!$sql) $sql = ' 1 = 1 '; + + $query = fixer::input('post') + ->specialChars('title') + ->add('account', $this->app->user->account) + ->add('form', serialize($this->session->$formVar)) + ->add('sql', $sql) + ->get(); + $this->dao->insert(TABLE_USERQUERY)->data($query)->autoCheck()->check('title', 'notempty')->exec(); + } + + /** + * Get title => id pairs of a user. + * + * @param string $module + * @access public + * @return array + */ + public function getQueryPairs($module) + { + $queries = $this->dao->select('id, title') + ->from(TABLE_USERQUERY) + ->where('account')->eq($this->app->user->account) + ->andWhere('module')->eq($module) + ->orderBy('id_asc') + ->fetchPairs(); + if(!$queries) return array('' => $this->lang->search->myQuery); + $queries = array('' => $this->lang->search->myQuery) + $queries; + return $queries; + } + + /** + * Get records by the conditon. + * + * @param string $module + * @param string $moduleIds + * @param string $conditions + * @access public + * @return array + */ + public function getBySelect($module, $moduleIds, $conditions) + { + if($module == 'story') + { + $pairs = 'id,title'; + $table = 'zt_story'; + } + else if($module == 'task') + { + $pairs = 'id,name'; + $table = 'zt_task'; + } + $query = '`' . $conditions['field1'] . '`'; + $operator = $conditions['operator1']; + $value = $conditions['value1']; + + if(!isset($this->lang->search->operators[$operator])) $operator = '='; + if($operator == "include") + { + $query .= ' LIKE ' . $this->dbh->quote("%$value%"); + } + elseif($operator == "notinclude") + { + $where .= ' NOT LIKE ' . $this->dbh->quote("%$value%"); + } + else + { + $query .= $operator . ' ' . $this->dbh->quote($value) . ' '; + } + + foreach($moduleIds as $id) + { + if(!$id) continue; + $title = $this->dao->select($pairs) + ->from($table) + ->where('id')->eq((int)$id) + ->andWhere($query) + ->fetch(); + if($title) $results[$id] = $title; + } + if(!isset($results)) return array(); + return $this->formatResults($results, $module); + } + + /** + * Format the results. + * + * @param array $results + * @param string $module + * @access private + * @return array + */ + private function formatResults($results, $module) + { + /* Get title field. */ + $title = ($module == 'story') ? 'title' : 'name'; + $resultPairs = array('' => ''); + foreach($results as $result) $resultPairs[$result->id] = $result->id . ':' . $result->$title; + return $resultPairs; + } + +} diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php index a53a6426aa..afa548dd75 100644 --- a/module/search/view/buildform.html.php +++ b/module/search/view/buildform.html.php @@ -1,262 +1,262 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          ' target='hiddenwin' id='searchform'> - - - - - - - - - - -
          search->common;?> - - session->$formSessionName; - - $fieldNO = 1; - for($i = 1; $i <= $groupItems; $i ++) - { - $spanClass = $i == 1 ? 'inline' : 'hidden'; - echo ""; - - /* Get params of current field. */ - $currentField = $formSession["field$fieldNO"]; - $param = $fieldParams[$currentField]; - - /* Print and or. */ - if($i == 1) echo "{$lang->search->group1}" . html::hidden("andOr$fieldNO", 'AND'); - if($i > 1) echo "
          " . html::select("andOr$fieldNO", $lang->search->andor, $formSession["andOr$fieldNO"]); - - /* Print field. */ - echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); - - /* Print operator. */ - echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); - - /* Print value. */ - echo ""; - if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-2'); - if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-2'); - echo ''; - - $fieldNO ++; - echo '
          '; - } - ?> -
          -
          search->andor, $formSession['groupAndOr'])?> - - "; - - /* Get params of current field. */ - $currentField = $formSession["field$fieldNO"]; - $param = $fieldParams[$currentField]; - - /* Print and or. */ - if($i == 1) echo "{$lang->search->group2}" . html::hidden("andOr$fieldNO", 'AND'); - if($i > 1) echo "
          " . html::select("andOr$fieldNO", $lang->search->andor, $formSession["andOr$fieldNO"]); - - /* Print field. */ - echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); - - /* Print operator. */ - echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); - - /* Print value. */ - echo ""; - if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-2'); - if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-2'); - echo ''; - - $fieldNO ++; - echo ''; - } - ?> -
          -
          - - search->common); - echo html::commonButton($lang->search->reset, 'onclick=resetForm();'); - echo html::commonButton($lang->save, 'onclick=saveQuery()'); - ?> - - - - - search->more;?> - - -
          -
          - + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          ' target='hiddenwin' id='searchform'> + + + + + + + + + + +
          search->common;?> + + session->$formSessionName; + + $fieldNO = 1; + for($i = 1; $i <= $groupItems; $i ++) + { + $spanClass = $i == 1 ? 'inline' : 'hidden'; + echo ""; + + /* Get params of current field. */ + $currentField = $formSession["field$fieldNO"]; + $param = $fieldParams[$currentField]; + + /* Print and or. */ + if($i == 1) echo "{$lang->search->group1}" . html::hidden("andOr$fieldNO", 'AND'); + if($i > 1) echo "
          " . html::select("andOr$fieldNO", $lang->search->andor, $formSession["andOr$fieldNO"]); + + /* Print field. */ + echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); + + /* Print operator. */ + echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); + + /* Print value. */ + echo ""; + if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-2'); + if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-2'); + echo ''; + + $fieldNO ++; + echo '
          '; + } + ?> +
          +
          search->andor, $formSession['groupAndOr'])?> + + "; + + /* Get params of current field. */ + $currentField = $formSession["field$fieldNO"]; + $param = $fieldParams[$currentField]; + + /* Print and or. */ + if($i == 1) echo "{$lang->search->group2}" . html::hidden("andOr$fieldNO", 'AND'); + if($i > 1) echo "
          " . html::select("andOr$fieldNO", $lang->search->andor, $formSession["andOr$fieldNO"]); + + /* Print field. */ + echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); + + /* Print operator. */ + echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); + + /* Print value. */ + echo ""; + if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-2'); + if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-2'); + echo ''; + + $fieldNO ++; + echo ''; + } + ?> +
          +
          + + search->common); + echo html::commonButton($lang->search->reset, 'onclick=resetForm();'); + echo html::commonButton($lang->save, 'onclick=saveQuery()'); + ?> + + + + + search->more;?> + + +
          +
          + diff --git a/module/search/view/select.html.php b/module/search/view/select.html.php index 97b9077781..5c8503c937 100644 --- a/module/search/view/select.html.php +++ b/module/search/view/select.html.php @@ -1,91 +1,91 @@ - - * @package search - * @version $Id: select.html.php 942 2010-07-06 10:03:51Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          - - - session->$formSessionName; - $fieldNO = 1; - - /* 取当前字段的设置。*/ - $currentField = $formSession["field$fieldNO"]; - $param = $fieldParams[$currentField]; - /* 打印字段。*/ - echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); - - /* 打印操作符。*/ - echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); - - /* 打印值。*/ - echo ""; - if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-4'); - if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-4'); - echo ''; - ?> - - search->common);?> - - - - - - - - $title):?> - - - - - - - -
          search->{$module . 'Title'};?>search->select;?>
          >
          -
          + + * @package search + * @version $Id: select.html.php 942 2010-07-06 10:03:51Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          + + + session->$formSessionName; + $fieldNO = 1; + + /* 取当前字段的设置。*/ + $currentField = $formSession["field$fieldNO"]; + $param = $fieldParams[$currentField]; + /* 打印字段。*/ + echo html::select("field$fieldNO", $searchFields, $formSession["field$fieldNO"], "onchange='setField(this.value, $fieldNO)'"); + + /* 打印操作符。*/ + echo html::select("operator$fieldNO", $lang->search->operators, $formSession["operator$fieldNO"]); + + /* 打印值。*/ + echo ""; + if($param['control'] == 'select') echo html::select("value$fieldNO", $param['values'], $formSession["value$fieldNO"], 'class=select-4'); + if($param['control'] == 'input') echo html::input("value$fieldNO", $formSession["value$fieldNO"], 'class=text-4'); + echo ''; + ?> + + search->common);?> + + + + + + + + $title):?> + + + + + + + +
          search->{$module . 'Title'};?>search->select;?>
          >
          +
          diff --git a/module/setting/model.php b/module/setting/model.php index ae29dcf500..886a7a1a15 100644 --- a/module/setting/model.php +++ b/module/setting/model.php @@ -1,124 +1,124 @@ - - * @package setting - * @version $Id$ - * @link http://www.zentao.net - */ -?> -getItem('system', 'global', 'version'); - if($version) return $version; - return '0.3 beta'; - } - - /** - * Get value of an item. - * - * @param string $owner - * @param string $section - * @param string $key - * @access public - * @return misc - */ - public function getItem($owner, $section, $key) - { - return $this->dao->select('`value`')->from(TABLE_CONFIG) - ->where('company')->eq(0) - ->andWhere('owner')->eq($owner) - ->andWhere('section')->eq($section) - ->andWhere('`key`')->eq($key) - ->fetch('value', $autoCompany = false); - } - - /** - * Compute a SN. Use the server ip, and server software string as seed, and an rand number, two micro time - * - * Note: this sn just to unique this zentaopms. No any private info. - * - * @access public - * @return string - */ - public function computeSN() - { - $seed = $this->server->SERVER_ADDR . $this->server->SERVER_SOFTWARE; - $sn = md5(str_shuffle(md5($seed . mt_rand(0, 99999999) . microtime())) . microtime()); - return $sn; - } - - /** - * Set the sn of current zentaopms. - * - * @access public - * @return void - */ - public function setSN() - { - $item->company = 0; - $item->owner = 'system'; - $item->section = 'global'; - $item->key = 'sn'; - $item->value = $this->computeSN(); - - $config = $this->dao->select('id, value')->from(TABLE_CONFIG) - ->where('company')->eq(0) - ->andWhere('owner')->eq('system') - ->andWhere('section')->eq('global') - ->andWhere('`key`')->eq('sn') - ->fetch('', $autoComapny = false); - if(!$config) - { - $this->dao->insert(TABLE_CONFIG)->data($item)->exec($autoCompany = false); - } - elseif($config->value == '281602d8ff5ee7533eeafd26eda4e776' or $config->value == '9bed3108092c94a0db2b934a46268b4a') - { - $this->dao->update(TABLE_CONFIG)->data($item)->where('id')->eq($config->id)->exec($autoCompany = false); - } - } - - /** - * Update version - * - * @param string $version - * @access public - * @return void - */ - public function updateVersion($version) - { - $item->company = 0; - $item->owner = 'system'; - $item->section = 'global'; - $item->key = 'version'; - $item->value = $version; - - $configID = $this->dao->select('id')->from(TABLE_CONFIG) - ->where('company')->eq(0) - ->andWhere('owner')->eq('system') - ->andWhere('section')->eq('global') - ->andWhere('`key`')->eq('version') - ->fetch('id', $autoComapny = false); - if($configID > 0) - { - $this->dao->update(TABLE_CONFIG)->data($item)->where('id')->eq($configID)->exec($autoCompany = false); - } - else - { - $this->dao->insert(TABLE_CONFIG)->data($item)->exec($autoCompany = false); - } - } -} + + * @package setting + * @version $Id$ + * @link http://www.zentao.net + */ +?> +getItem('system', 'global', 'version'); + if($version) return $version; + return '0.3 beta'; + } + + /** + * Get value of an item. + * + * @param string $owner + * @param string $section + * @param string $key + * @access public + * @return misc + */ + public function getItem($owner, $section, $key) + { + return $this->dao->select('`value`')->from(TABLE_CONFIG) + ->where('company')->eq(0) + ->andWhere('owner')->eq($owner) + ->andWhere('section')->eq($section) + ->andWhere('`key`')->eq($key) + ->fetch('value', $autoCompany = false); + } + + /** + * Compute a SN. Use the server ip, and server software string as seed, and an rand number, two micro time + * + * Note: this sn just to unique this zentaopms. No any private info. + * + * @access public + * @return string + */ + public function computeSN() + { + $seed = $this->server->SERVER_ADDR . $this->server->SERVER_SOFTWARE; + $sn = md5(str_shuffle(md5($seed . mt_rand(0, 99999999) . microtime())) . microtime()); + return $sn; + } + + /** + * Set the sn of current zentaopms. + * + * @access public + * @return void + */ + public function setSN() + { + $item->company = 0; + $item->owner = 'system'; + $item->section = 'global'; + $item->key = 'sn'; + $item->value = $this->computeSN(); + + $config = $this->dao->select('id, value')->from(TABLE_CONFIG) + ->where('company')->eq(0) + ->andWhere('owner')->eq('system') + ->andWhere('section')->eq('global') + ->andWhere('`key`')->eq('sn') + ->fetch('', $autoComapny = false); + if(!$config) + { + $this->dao->insert(TABLE_CONFIG)->data($item)->exec($autoCompany = false); + } + elseif($config->value == '281602d8ff5ee7533eeafd26eda4e776' or $config->value == '9bed3108092c94a0db2b934a46268b4a') + { + $this->dao->update(TABLE_CONFIG)->data($item)->where('id')->eq($config->id)->exec($autoCompany = false); + } + } + + /** + * Update version + * + * @param string $version + * @access public + * @return void + */ + public function updateVersion($version) + { + $item->company = 0; + $item->owner = 'system'; + $item->section = 'global'; + $item->key = 'version'; + $item->value = $version; + + $configID = $this->dao->select('id')->from(TABLE_CONFIG) + ->where('company')->eq(0) + ->andWhere('owner')->eq('system') + ->andWhere('section')->eq('global') + ->andWhere('`key`')->eq('version') + ->fetch('id', $autoComapny = false); + if($configID > 0) + { + $this->dao->update(TABLE_CONFIG)->data($item)->where('id')->eq($configID)->exec($autoCompany = false); + } + else + { + $this->dao->insert(TABLE_CONFIG)->data($item)->exec($autoCompany = false); + } + } +} diff --git a/module/story/control.php b/module/story/control.php index a49a078eba..e0dcea00ee 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -1,815 +1,815 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -class story extends control -{ - /** - * The construct function, load product, tree, user auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('product'); - $this->loadModel('tree'); - $this->loadModel('user'); - } - - /** - * Create a story. - * - * @param int $productID - * @param int $moduleID - * @access public - * @return void - */ - public function create($productID = 0, $moduleID = 0, $storyID = 0, $projectID = 0, $bugID = 0) - { - if(!empty($_POST)) - { - $storyID = $this->story->create($projectID, $bugID); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action'); - if($bugID == 0) - { - $actionID = $this->action->create('story', $storyID, 'Opened', ''); - } - else - { - $actionID = $this->action->create('story', $storyID, 'Frombug', '', $bugID); - } - $this->sendMail($storyID, $actionID); - if($projectID == 0) - { - die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); - } - else - { - die(js::locate($this->createLink('project', 'story', "projectID=$projectID"), 'parent')); - } - } - - /* Set products, users and module. */ - if($productID != 0) - { - $product = $this->product->getById($productID); - $products = $this->product->getPairs(); - } - else - { - $products = $this->product->getProductsByProject($projectID); - foreach($products as $key => $title) - { - $product = $this->product->getById($key); - break; - } - } - $users = $this->user->getPairs('nodeleted'); - $moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); - - /* Set menu. */ - $this->product->setMenu($products, $product->id); - - /* Init vars. */ - $planID = 0; - $source = ''; - $pri = 0; - $estimate = ''; - $title = ''; - $spec = ''; - $verify = ''; - $keywords = ''; - $mailto = ''; - - if($storyID > 0) - { - $story = $this->story->getByID($storyID); - $planID = $story->plan; - $source = $story->source; - $pri = $story->pri; - $productID = $story->product; - $moduleID = $story->module; - $estimate = $story->estimate; - $title = $story->title; - $spec = htmlspecialchars($story->spec); - $verify = htmlspecialchars($story->verify); - $keywords = $story->keywords; - $mailto = $story->mailto; - } - - if($bugID > 0) - { - $oldBug = $this->loadModel('bug')->getById($bugID); - $productID = $oldBug->product; - $source = 'bug'; - $title = $oldBug->title; - $keywords = $oldBug->keywords; - $spec = $oldBug->steps; - $pri = $oldBug->pri; - $mailto = $oldBug->mailto; - } - - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->create; - $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$productID"), $product->name); - $this->view->position[] = $this->lang->story->create; - $this->view->products = $products; - $this->view->users = $users; - $this->view->moduleID = $moduleID; - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->view->plans = $this->loadModel('productplan')->getPairs($productID, 'unexpired'); - $this->view->planID = $planID; - $this->view->source = $source; - $this->view->pri = $pri; - $this->view->productID = $productID; - $this->view->estimate = $estimate; - $this->view->title = $title; - $this->view->spec = $spec; - $this->view->verify = $verify; - $this->view->keywords = $keywords; - $this->view->mailto = $mailto; - - $this->display(); - } - - /** - * Create a batch stories. - * - * @param int $productID - * @param int $moduleID - * @access public - * @return void - */ - public function batchCreate($productID = 0, $moduleID = 0) - { - if(!empty($_POST)) - { - $mails = $this->story->batchCreate($productID); - if(dao::isError()) die(js::error(dao::getError())); - - foreach($mails as $mail) - { - $this->sendMail($mail->storyID, $mail->actionID); - } - die(js::locate($this->createLink('product', 'browse', "productID=$productID"), 'parent')); - } - - /* Set products, users and module. */ - $product = $this->product->getById($productID); - $products = $this->product->getPairs(); - $moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); - - /* Set menu. */ - $this->product->setMenu($products, $product->id); - - /* Init vars. */ - $planID = 0; - $pri = 0; - $estimate = ''; - $title = ''; - $spec = ''; - - $moduleOptionMenu['same'] = $this->lang->story->same; - $plans = $this->loadModel('productplan')->getPairs($productID, 'unexpired'); - $plans['same'] = $this->lang->story->same; - - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->create; - $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$productID"), $product->name); - $this->view->position[] = $this->lang->story->create; - $this->view->products = $products; - $this->view->moduleID = $moduleID; - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->view->plans = $plans; - $this->view->planID = $planID; - $this->view->pri = $pri; - $this->view->productID = $productID; - $this->view->estimate = $estimate; - $this->view->title = $title; - $this->view->spec = $spec; - - $this->display(); - } - - /** - * The common action when edit or change a story. - * - * @param int $storyID - * @access private - * @return void - */ - private function commonAction($storyID) - { - /* Get datas. */ - $story = $this->story->getById($storyID); - $product = $this->product->getById($story->product); - $products = $this->product->getPairs(); - $users = $this->user->getPairs('nodeleted'); - $moduleOptionMenu = $this->tree->getOptionMenu($product->id, $viewType = 'story'); - - /* Set menu. */ - $this->product->setMenu($products, $product->id); - - /* Assign. */ - $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); - $this->view->product = $product; - $this->view->products = $products; - $this->view->story = $story; - $this->view->users = $users; - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->view->plans = $this->loadModel('productplan')->getPairs($product->id); - $this->view->actions = $this->action->getList('story', $storyID); - } - - /** - * Edit a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function edit($storyID) - { - $this->loadModel('action'); - if(!empty($_POST)) - { - $changes = $this->story->update($storyID); - if(dao::isError()) die(js::error(dao::getError())); - if($this->post->comment != '' or !empty($changes)) - { - $action = !empty($changes) ? 'Edited' : 'Commented'; - $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendMail($storyID, $actionID); - } - die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); - } - - $this->commonAction($storyID); - - /* Assign. */ - $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->edit . $this->lang->colon . $this->view->story->title; - $this->view->position[] = $this->lang->story->edit; - $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), $this->view->story->assignedTo); - $this->display(); - } - - /** - * Change a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function change($storyID) - { - $this->loadModel('action'); - if(!empty($_POST)) - { - $changes = $this->story->change($storyID); - if(dao::isError()) die(js::error(dao::getError())); - $version = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch('version'); - $files = $this->loadModel('file')->saveUpload('story', $storyID, $version); - if($this->post->comment != '' or !empty($changes) or !empty($files)) - { - $action = (!empty($changes) or !empty($files)) ? 'Changed' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; - $actionID = $this->action->create('story', $storyID, $action, $fileAction . $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendMail($storyID, $actionID); - } - die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); - } - - $this->commonAction($storyID); - $this->story->getAffectedScope($this->view->story); - $this->app->loadLang('task'); - $this->app->loadLang('bug'); - $this->app->loadLang('testcase'); - $this->app->loadLang('project'); - - /* Assign. */ - $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->change . $this->lang->colon . $this->view->story->title; - $this->view->position[] = $this->lang->story->change; - $this->display(); - } - - /** - * Activate a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function activate($storyID) - { - $this->loadModel('action'); - if(!empty($_POST)) - { - $this->story->activate($storyID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('story', $storyID, 'Activated', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendMail($storyID, $actionID); - die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); - } - - $this->commonAction($storyID); - - /* Assign. */ - $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->activate . $this->lang->colon . $this->view->story->title; - $this->view->position[] = $this->lang->story->activate; - $this->display(); - } - - /** - * View a story. - * - * @param int $storyID - * @param int $version - * @access public - * @return void - */ - public function view($storyID, $version = 0) - { - $this->loadModel('action'); - $storyID = (int)$storyID; - $story = $this->story->getById($storyID, $version); - if(!$story) die(js::error($this->lang->notFound) . js::locate('back')); - - $story->files = $this->loadModel('file')->getByObject('story', $storyID); - $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); - $plan = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title'); - $bugs = $this->dao->select('id,title')->from(TABLE_BUG)->where('story')->eq($storyID)->fetchAll(); - $fromBug = $this->dao->select('id,title')->from(TABLE_BUG)->where('toStory')->eq($storyID)->fetch(); - $cases = $this->dao->select('id,title')->from(TABLE_CASE)->where('story')->eq($storyID)->fetchAll(); - $modulePath = $this->tree->getParents($story->module); - $users = $this->user->getPairs('noletter'); - - /* Set the menu. */ - $this->product->setMenu($this->product->getPairs(), $product->id); - - $header['title'] = $product->name . $this->lang->colon . $this->lang->story->view . $this->lang->colon . $story->title; - $position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); - $position[] = $this->lang->story->view; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->product = $product; - $this->view->plan = $plan; - $this->view->bugs = $bugs; - $this->view->fromBug = $fromBug; - $this->view->cases = $cases; - $this->view->story = $story; - $this->view->users = $users; - $this->view->actions = $this->action->getList('story', $storyID); - $this->view->modulePath = $modulePath; - $this->view->version = $version == 0 ? $story->version : $version; - $this->display(); - } - - /** - * Delete a story. - * - * @param int $storyID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($storyID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->story->confirmDelete, $this->createLink('story', 'delete', "story=$storyID&confirm=yes"), ''); - exit; - } - else - { - $this->story->delete(TABLE_STORY, $storyID); - die(js::locate($this->session->storyList, 'parent')); - } - } - - /** - * Review a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function review($storyID) - { - $this->loadModel('action'); - - if(!empty($_POST)) - { - $this->story->review($storyID); - if(dao::isError()) die(js::error(dao::getError())); - $result = $this->post->result; - if($this->post->closedReason != '' and strpos('done,postponed,subdivided', $this->post->closedReason) !== false) $result = 'pass'; - $actionID = $this->action->create('story', $storyID, 'Reviewed', $this->post->comment, ucfirst($result)); - $this->action->logHistory($actionID, array()); - $this->sendMail($storyID, $actionID); - if($this->post->result == 'reject') - { - $this->action->create('story', $storyID, 'Closed', '', ucfirst($this->post->closedReason)); - } - die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); - } - - /* Get story and product. */ - $story = $this->story->getById($storyID); - $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); - - /* Set menu. */ - $this->product->setMenu($this->product->getPairs(), $product->id); - - /* Set the review result options. */ - if($story->status == 'draft' and $story->version == 1) unset($this->lang->story->reviewResultList['revert']); - if($story->status == 'changed') unset($this->lang->story->reviewResultList['reject']); - - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->view . $this->lang->colon . $story->title; - $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); - $this->view->position[] = $this->lang->story->view; - - $this->view->product = $product; - $this->view->story = $story; - $this->view->actions = $this->action->getList('story', $storyID); - $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); - - /* Get the affcected things. */ - $this->story->getAffectedScope($this->view->story); - $this->app->loadLang('task'); - $this->app->loadLang('bug'); - $this->app->loadLang('testcase'); - $this->app->loadLang('project'); - - $this->display(); - } - - /** - * Close a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function close($storyID) - { - $this->loadModel('action'); - - if(!empty($_POST)) - { - $this->story->close($storyID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason)); - $this->action->logHistory($actionID); - $this->sendMail($storyID, $actionID); - die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); - } - - /* Get story and product. */ - $story = $this->story->getById($storyID); - $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); - - /* Set menu. */ - $this->product->setMenu($this->product->getPairs(), $product->id); - - /* Set the closed reason options. */ - if($story->status == 'draft') unset($this->lang->story->reasonList['cancel']); - - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->close . $this->lang->colon . $story->title; - $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); - $this->view->position[] = $this->lang->close; - - $this->view->product = $product; - $this->view->story = $story; - $this->view->actions = $this->action->getList('story', $storyID); - $this->view->users = $this->loadModel('user')->getPairs(); - $this->display(); - } - - /** - * Tasks of a story. - * - * @param int $storyID - * @param int $projectID - * @access public - * @return void - */ - public function tasks($storyID, $projectID = 0) - { - $this->loadModel('task'); - $this->view->tasks = $this->task->getStoryTaskPairs($storyID, $projectID); - $this->display(); - exit; - } - - /** - * AJAX: get stories of a project in html select. - * - * @param int $projectID - * @param int $productID - * @param int $storyID - * @access public - * @return void - */ - public function ajaxGetProjectStories($projectID, $productID = 0, $storyID = 0) - { - $stories = $this->story->getProjectStoryPairs($projectID, $productID); - die(html::select('story', $stories, $storyID)); - } - - /** - * AJAX: get stories of a product in html select. - * - * @param int $productID - * @param int $moduleID - * @param int $storyID - * @access public - * @return void - */ - public function ajaxGetProductStories($productID, $moduleID = 0, $storyID = 0) - { - $stories = $this->story->getProductStoryPairs($productID, $moduleID); - die(html::select('story', $stories, $storyID, "class=''")); - } - - /** - * Send email. - * - * @param int $storyID - * @param int $actionID - * @access private - * @return void - */ - private function sendmail($storyID, $actionID) - { - $story = $this->story->getById($storyID); - $productName = $this->product->getById($story->product)->name; - - /* Get actions. */ - $action = $this->loadModel('action')->getById($actionID); - $history = $this->action->getHistory($actionID); - $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); - if(strtolower($action->action) == 'opened') $action->comment = $story->spec; - - /* Set toList and ccList. */ - $toList = $story->assignedTo; - $ccList = str_replace(' ', '', trim($story->mailto, ',')); - - /* If the action is changed or reviewed, mail to the project team. */ - if(strtolower($action->action) == 'changed' or strtolower($action->action) == 'reviewed') - { - $prjMembers = $this->story->getProjectMembers($storyID); - if($prjMembers) - { - $ccList .= ',' . join(',', $prjMembers); - $ccList = ltrim(',', $ccList); - } - } - - if($toList == '') - { - if($ccList == '') return; - if(strpos($ccList, ',') === false) - { - $toList = $ccList; - $ccList = ''; - } - else - { - $commaPos = strpos($ccList, ','); - $toList = substr($ccList, 0, $commaPos); - $ccList = substr($ccList, $commaPos + 1); - } - } - elseif($toList == 'closed') - { - $toList = $story->openedBy; - } - - /* Get the mail content. */ - $this->view->story = $story; - $this->view->action = $action; - $this->view->users = $this->user->getPairs('noletter'); - $mailContent = $this->parse($this->moduleName, 'sendmail'); - - /* Send it. */ - $this->loadModel('mail')->send($toList, $productName . ':' . 'STORY #' . $story->id . $this->lang->colon . $story->title, $mailContent, $ccList); - if($this->mail->isError()) echo js::error($this->mail->getError()); - } - /** - * The report page. - * - * @param int $productID - * @param string $browseType - * @param int $moduleID - * @access public - * @return void - */ - public function report($productID, $browseType, $moduleID) - { - $this->loadModel('report'); - $this->view->charts = array(); - $this->view->renderJS = ''; - - if(!empty($_POST)) - { - foreach($this->post->charts as $chart) - { - $chartFunc = 'getDataOf' . $chart; - $chartData = $this->story->$chartFunc(); - $chartOption = $this->lang->story->report->$chart; - $this->story->mergeChartOption($chart); - - $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); - $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); - $this->view->datas[$chart] = $this->report->computePercent($chartData); - } - $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); - } - $this->products = $this->product->getPairs(); - $this->product->setMenu($this->products, $productID); - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->story->common; - $this->view->productID = $productID; - $this->view->browseType = $browseType; - $this->view->moduleID = $moduleID; - $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; - $this->display(); - } - - /** - * get data to export - * - * @param int $productID - * @param string $orderBy - * @access public - * @return void - */ - public function export($productID, $orderBy) - { - /* format the fields of every story in order to export data. */ - if($_POST) - { - $storyLang = $this->lang->story; - $storyConfig = $this->config->story; - - /* Create field lists. */ - $fields = explode(',', $storyConfig->list->exportFields); - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($storyLang->$fieldName) ? $storyLang->$fieldName : $fieldName; - unset($fields[$key]); - } - - /* Get stories. */ - $stories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyReport)->orderBy($orderBy)->fetchAll('id'); - - /* Get users, products and projects. */ - $users = $this->loadModel('user')->getPairs('noletter'); - $products = $this->loadModel('product')->getPairs(); - - /* Get related objects id lists. */ - $relatedModuleIdList = array(); - $relatedStoryIdList = array(); - $relatedPlanIdList = array(); - - foreach($stories as $story) - { - $relatedModuleIdList[$story->module] = $story->module; - $relatedPlanIdList[$story->plan] = $story->plan; - - /* Process related stories. */ - $relatedStories = $story->childStories . ',' . $story->linkStories . ',' . $story->duplicateStory; - $relatedStories = explode(',', $relatedStories); - foreach($relatedStories as $storyID) - { - if($storyID) $relatedStoryIdList[$storyID] = trim($storyID); - } - } - - /* Get related objects title or names. */ - $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); - $relatedPlans = $this->dao->select('id, title')->from(TABLE_PRODUCTPLAN)->where('id')->in($relatedPlanIdList)->fetchPairs(); - $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); - $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->in(@array_keys($stories))->fetchGroup('objectID'); - $relatedSpecs = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('`story`')->in(@array_keys($stories))->orderBy('version desc')->fetchGroup('story'); - - foreach($stories as $story) - { - $story->spec = ''; - $story->verify = ''; - if(isset($relatedSpecs[$story->id])) - { - $storySpec = $relatedSpecs[$story->id][0]; - $story->title = $storySpec->title; - $story->spec = $storySpec->spec; - $story->verify = $storySpec->verify; - } - - if($this->post->fileType == 'csv') - { - $story->spec = htmlspecialchars_decode($story->spec); - $story->spec = str_replace("
          ", "\n", $story->spec); - $story->spec = str_replace('"', '""', $story->spec); - - $story->verify = htmlspecialchars_decode($story->verify); - $story->verify = str_replace("
          ", "\n", $story->verify); - $story->verify = str_replace('"', '""', $story->verify); - } - - /* fill some field with useful value. */ - if(isset($products[$story->product])) $story->product = $products[$story->product]; - if(isset($relatedModules[$story->module])) $story->module = $relatedModules[$story->module]; - if(isset($relatedPlans[$story->plan])) $story->plan = $relatedPlans[$story->plan]; - if(isset($relatedStories[$story->duplicateStory])) $story->duplicateStory = $relatedStories[$story->duplicateStory]; - - if(isset($storyLang->priList[$story->pri])) $story->pri = $storyLang->priList[$story->pri]; - if(isset($storyLang->statusList[$story->status])) $story->status = $storyLang->statusList[$story->status]; - if(isset($storyLang->stageList[$story->stage])) $story->stage = $storyLang->stageList[$story->stage]; - if(isset($storyLang->reasonList[$story->closedReason])) $story->closedReason = $storyLang->reasonList[$story->closedReason]; - - if(isset($users[$story->openedBy])) $story->openedBy = $users[$story->openedBy]; - if(isset($users[$story->assignedTo])) $story->assignedTo = $users[$story->assignedTo]; - if(isset($users[$story->lastEditedBy])) $story->lastEditedBy = $users[$story->lastEditedBy]; - if(isset($users[$story->closedBy])) $story->closedBy = $users[$story->closedBy]; - - $story->openedDate = substr($story->openedDate, 0, 10); - $story->assignedDate = substr($story->assignedDate, 0, 10); - $story->lastEditedDate = substr($story->lastEditedDate, 0, 10); - $story->closedDate = substr($story->closedDate, 0, 10); - - - if($story->linkStories) - { - $tmpLinkStories = array(); - $linkStoriesIdList = explode(',', $story->linkStories); - foreach($linkStoriesIdList as $linkStoryID) - { - $linkStoryID = trim($linkStoryID); - $tmpLinkStories[] = isset($relatedStories[$linkStoryID]) ? $relatedStories[$linkStoryID] : $linkStoryID; - } - $story->linkStories = join("; \n", $tmpLinkStories); - } - - if($story->childStories) - { - $tmpChildStories = array(); - $childStoriesIdList = explode(',', $story->childStories); - foreach($childStoriesIdList as $childStoryID) - { - $childStoryID = trim($childStoryID); - $tmpChildStories[] = isset($relatedStories[$childStoryID]) ? $relatedStories[$childStoryID] : $childStoryID; - } - $story->childStories = join("; \n", $tmpChildStories); - } - - /* Set related files. */ - if(isset($relatedFiles[$story->id])) - { - foreach($relatedFiles[$story->id] as $file) - { - $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$story->company/" . $file->pathname; - $story->files .= html::a($fileURL, $file->title, '_blank') . '
          '; - } - } - - $story->mailto = trim(trim($story->mailto), ','); - $mailtos = explode(',', $story->mailto); - $story->mailto = ''; - foreach($mailtos as $mailto) - { - $mailto = trim($mailto); - if(isset($users[$mailto])) $story->mailto .= $users[$mailto] . ','; - } - - $story->reviewedBy = trim(trim($story->reviewedBy), ','); - $reviewedBys = explode(',', $story->reviewedBy); - $story->reviewedBy = ''; - foreach($reviewedBys as $reviewedBy) - { - $reviewedBy = trim($reviewedBy); - if(isset($users[$reviewedBy])) $story->reviewedBy .= $users[$reviewedBy] . ','; - } - - } - - $this->post->set('fields', $fields); - $this->post->set('rows', $stories); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +class story extends control +{ + /** + * The construct function, load product, tree, user auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('product'); + $this->loadModel('tree'); + $this->loadModel('user'); + } + + /** + * Create a story. + * + * @param int $productID + * @param int $moduleID + * @access public + * @return void + */ + public function create($productID = 0, $moduleID = 0, $storyID = 0, $projectID = 0, $bugID = 0) + { + if(!empty($_POST)) + { + $storyID = $this->story->create($projectID, $bugID); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action'); + if($bugID == 0) + { + $actionID = $this->action->create('story', $storyID, 'Opened', ''); + } + else + { + $actionID = $this->action->create('story', $storyID, 'Frombug', '', $bugID); + } + $this->sendMail($storyID, $actionID); + if($projectID == 0) + { + die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + } + else + { + die(js::locate($this->createLink('project', 'story', "projectID=$projectID"), 'parent')); + } + } + + /* Set products, users and module. */ + if($productID != 0) + { + $product = $this->product->getById($productID); + $products = $this->product->getPairs(); + } + else + { + $products = $this->product->getProductsByProject($projectID); + foreach($products as $key => $title) + { + $product = $this->product->getById($key); + break; + } + } + $users = $this->user->getPairs('nodeleted'); + $moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); + + /* Set menu. */ + $this->product->setMenu($products, $product->id); + + /* Init vars. */ + $planID = 0; + $source = ''; + $pri = 0; + $estimate = ''; + $title = ''; + $spec = ''; + $verify = ''; + $keywords = ''; + $mailto = ''; + + if($storyID > 0) + { + $story = $this->story->getByID($storyID); + $planID = $story->plan; + $source = $story->source; + $pri = $story->pri; + $productID = $story->product; + $moduleID = $story->module; + $estimate = $story->estimate; + $title = $story->title; + $spec = htmlspecialchars($story->spec); + $verify = htmlspecialchars($story->verify); + $keywords = $story->keywords; + $mailto = $story->mailto; + } + + if($bugID > 0) + { + $oldBug = $this->loadModel('bug')->getById($bugID); + $productID = $oldBug->product; + $source = 'bug'; + $title = $oldBug->title; + $keywords = $oldBug->keywords; + $spec = $oldBug->steps; + $pri = $oldBug->pri; + $mailto = $oldBug->mailto; + } + + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->create; + $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$productID"), $product->name); + $this->view->position[] = $this->lang->story->create; + $this->view->products = $products; + $this->view->users = $users; + $this->view->moduleID = $moduleID; + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->view->plans = $this->loadModel('productplan')->getPairs($productID, 'unexpired'); + $this->view->planID = $planID; + $this->view->source = $source; + $this->view->pri = $pri; + $this->view->productID = $productID; + $this->view->estimate = $estimate; + $this->view->title = $title; + $this->view->spec = $spec; + $this->view->verify = $verify; + $this->view->keywords = $keywords; + $this->view->mailto = $mailto; + + $this->display(); + } + + /** + * Create a batch stories. + * + * @param int $productID + * @param int $moduleID + * @access public + * @return void + */ + public function batchCreate($productID = 0, $moduleID = 0) + { + if(!empty($_POST)) + { + $mails = $this->story->batchCreate($productID); + if(dao::isError()) die(js::error(dao::getError())); + + foreach($mails as $mail) + { + $this->sendMail($mail->storyID, $mail->actionID); + } + die(js::locate($this->createLink('product', 'browse', "productID=$productID"), 'parent')); + } + + /* Set products, users and module. */ + $product = $this->product->getById($productID); + $products = $this->product->getPairs(); + $moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); + + /* Set menu. */ + $this->product->setMenu($products, $product->id); + + /* Init vars. */ + $planID = 0; + $pri = 0; + $estimate = ''; + $title = ''; + $spec = ''; + + $moduleOptionMenu['same'] = $this->lang->story->same; + $plans = $this->loadModel('productplan')->getPairs($productID, 'unexpired'); + $plans['same'] = $this->lang->story->same; + + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->create; + $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$productID"), $product->name); + $this->view->position[] = $this->lang->story->create; + $this->view->products = $products; + $this->view->moduleID = $moduleID; + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->view->plans = $plans; + $this->view->planID = $planID; + $this->view->pri = $pri; + $this->view->productID = $productID; + $this->view->estimate = $estimate; + $this->view->title = $title; + $this->view->spec = $spec; + + $this->display(); + } + + /** + * The common action when edit or change a story. + * + * @param int $storyID + * @access private + * @return void + */ + private function commonAction($storyID) + { + /* Get datas. */ + $story = $this->story->getById($storyID); + $product = $this->product->getById($story->product); + $products = $this->product->getPairs(); + $users = $this->user->getPairs('nodeleted'); + $moduleOptionMenu = $this->tree->getOptionMenu($product->id, $viewType = 'story'); + + /* Set menu. */ + $this->product->setMenu($products, $product->id); + + /* Assign. */ + $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); + $this->view->product = $product; + $this->view->products = $products; + $this->view->story = $story; + $this->view->users = $users; + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->view->plans = $this->loadModel('productplan')->getPairs($product->id); + $this->view->actions = $this->action->getList('story', $storyID); + } + + /** + * Edit a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function edit($storyID) + { + $this->loadModel('action'); + if(!empty($_POST)) + { + $changes = $this->story->update($storyID); + if(dao::isError()) die(js::error(dao::getError())); + if($this->post->comment != '' or !empty($changes)) + { + $action = !empty($changes) ? 'Edited' : 'Commented'; + $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendMail($storyID, $actionID); + } + die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + } + + $this->commonAction($storyID); + + /* Assign. */ + $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->edit . $this->lang->colon . $this->view->story->title; + $this->view->position[] = $this->lang->story->edit; + $this->view->users = $this->user->appendDeleted($this->user->getPairs('nodeleted'), $this->view->story->assignedTo); + $this->display(); + } + + /** + * Change a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function change($storyID) + { + $this->loadModel('action'); + if(!empty($_POST)) + { + $changes = $this->story->change($storyID); + if(dao::isError()) die(js::error(dao::getError())); + $version = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch('version'); + $files = $this->loadModel('file')->saveUpload('story', $storyID, $version); + if($this->post->comment != '' or !empty($changes) or !empty($files)) + { + $action = (!empty($changes) or !empty($files)) ? 'Changed' : 'Commented'; + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; + $actionID = $this->action->create('story', $storyID, $action, $fileAction . $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendMail($storyID, $actionID); + } + die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + } + + $this->commonAction($storyID); + $this->story->getAffectedScope($this->view->story); + $this->app->loadLang('task'); + $this->app->loadLang('bug'); + $this->app->loadLang('testcase'); + $this->app->loadLang('project'); + + /* Assign. */ + $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->change . $this->lang->colon . $this->view->story->title; + $this->view->position[] = $this->lang->story->change; + $this->display(); + } + + /** + * Activate a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function activate($storyID) + { + $this->loadModel('action'); + if(!empty($_POST)) + { + $this->story->activate($storyID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('story', $storyID, 'Activated', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendMail($storyID, $actionID); + die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + } + + $this->commonAction($storyID); + + /* Assign. */ + $this->view->header->title = $this->view->product->name . $this->lang->colon . $this->lang->story->activate . $this->lang->colon . $this->view->story->title; + $this->view->position[] = $this->lang->story->activate; + $this->display(); + } + + /** + * View a story. + * + * @param int $storyID + * @param int $version + * @access public + * @return void + */ + public function view($storyID, $version = 0) + { + $this->loadModel('action'); + $storyID = (int)$storyID; + $story = $this->story->getById($storyID, $version); + if(!$story) die(js::error($this->lang->notFound) . js::locate('back')); + + $story->files = $this->loadModel('file')->getByObject('story', $storyID); + $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); + $plan = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title'); + $bugs = $this->dao->select('id,title')->from(TABLE_BUG)->where('story')->eq($storyID)->fetchAll(); + $fromBug = $this->dao->select('id,title')->from(TABLE_BUG)->where('toStory')->eq($storyID)->fetch(); + $cases = $this->dao->select('id,title')->from(TABLE_CASE)->where('story')->eq($storyID)->fetchAll(); + $modulePath = $this->tree->getParents($story->module); + $users = $this->user->getPairs('noletter'); + + /* Set the menu. */ + $this->product->setMenu($this->product->getPairs(), $product->id); + + $header['title'] = $product->name . $this->lang->colon . $this->lang->story->view . $this->lang->colon . $story->title; + $position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); + $position[] = $this->lang->story->view; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->product = $product; + $this->view->plan = $plan; + $this->view->bugs = $bugs; + $this->view->fromBug = $fromBug; + $this->view->cases = $cases; + $this->view->story = $story; + $this->view->users = $users; + $this->view->actions = $this->action->getList('story', $storyID); + $this->view->modulePath = $modulePath; + $this->view->version = $version == 0 ? $story->version : $version; + $this->display(); + } + + /** + * Delete a story. + * + * @param int $storyID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($storyID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->story->confirmDelete, $this->createLink('story', 'delete', "story=$storyID&confirm=yes"), ''); + exit; + } + else + { + $this->story->delete(TABLE_STORY, $storyID); + die(js::locate($this->session->storyList, 'parent')); + } + } + + /** + * Review a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function review($storyID) + { + $this->loadModel('action'); + + if(!empty($_POST)) + { + $this->story->review($storyID); + if(dao::isError()) die(js::error(dao::getError())); + $result = $this->post->result; + if($this->post->closedReason != '' and strpos('done,postponed,subdivided', $this->post->closedReason) !== false) $result = 'pass'; + $actionID = $this->action->create('story', $storyID, 'Reviewed', $this->post->comment, ucfirst($result)); + $this->action->logHistory($actionID, array()); + $this->sendMail($storyID, $actionID); + if($this->post->result == 'reject') + { + $this->action->create('story', $storyID, 'Closed', '', ucfirst($this->post->closedReason)); + } + die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); + } + + /* Get story and product. */ + $story = $this->story->getById($storyID); + $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); + + /* Set menu. */ + $this->product->setMenu($this->product->getPairs(), $product->id); + + /* Set the review result options. */ + if($story->status == 'draft' and $story->version == 1) unset($this->lang->story->reviewResultList['revert']); + if($story->status == 'changed') unset($this->lang->story->reviewResultList['reject']); + + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->view . $this->lang->colon . $story->title; + $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); + $this->view->position[] = $this->lang->story->view; + + $this->view->product = $product; + $this->view->story = $story; + $this->view->actions = $this->action->getList('story', $storyID); + $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); + + /* Get the affcected things. */ + $this->story->getAffectedScope($this->view->story); + $this->app->loadLang('task'); + $this->app->loadLang('bug'); + $this->app->loadLang('testcase'); + $this->app->loadLang('project'); + + $this->display(); + } + + /** + * Close a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function close($storyID) + { + $this->loadModel('action'); + + if(!empty($_POST)) + { + $this->story->close($storyID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason)); + $this->action->logHistory($actionID); + $this->sendMail($storyID, $actionID); + die(js::locate(inlink('view', "storyID=$storyID"), 'parent')); + } + + /* Get story and product. */ + $story = $this->story->getById($storyID); + $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); + + /* Set menu. */ + $this->product->setMenu($this->product->getPairs(), $product->id); + + /* Set the closed reason options. */ + if($story->status == 'draft') unset($this->lang->story->reasonList['cancel']); + + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->close . $this->lang->colon . $story->title; + $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id"), $product->name); + $this->view->position[] = $this->lang->close; + + $this->view->product = $product; + $this->view->story = $story; + $this->view->actions = $this->action->getList('story', $storyID); + $this->view->users = $this->loadModel('user')->getPairs(); + $this->display(); + } + + /** + * Tasks of a story. + * + * @param int $storyID + * @param int $projectID + * @access public + * @return void + */ + public function tasks($storyID, $projectID = 0) + { + $this->loadModel('task'); + $this->view->tasks = $this->task->getStoryTaskPairs($storyID, $projectID); + $this->display(); + exit; + } + + /** + * AJAX: get stories of a project in html select. + * + * @param int $projectID + * @param int $productID + * @param int $storyID + * @access public + * @return void + */ + public function ajaxGetProjectStories($projectID, $productID = 0, $storyID = 0) + { + $stories = $this->story->getProjectStoryPairs($projectID, $productID); + die(html::select('story', $stories, $storyID)); + } + + /** + * AJAX: get stories of a product in html select. + * + * @param int $productID + * @param int $moduleID + * @param int $storyID + * @access public + * @return void + */ + public function ajaxGetProductStories($productID, $moduleID = 0, $storyID = 0) + { + $stories = $this->story->getProductStoryPairs($productID, $moduleID); + die(html::select('story', $stories, $storyID, "class=''")); + } + + /** + * Send email. + * + * @param int $storyID + * @param int $actionID + * @access private + * @return void + */ + private function sendmail($storyID, $actionID) + { + $story = $this->story->getById($storyID); + $productName = $this->product->getById($story->product)->name; + + /* Get actions. */ + $action = $this->loadModel('action')->getById($actionID); + $history = $this->action->getHistory($actionID); + $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); + if(strtolower($action->action) == 'opened') $action->comment = $story->spec; + + /* Set toList and ccList. */ + $toList = $story->assignedTo; + $ccList = str_replace(' ', '', trim($story->mailto, ',')); + + /* If the action is changed or reviewed, mail to the project team. */ + if(strtolower($action->action) == 'changed' or strtolower($action->action) == 'reviewed') + { + $prjMembers = $this->story->getProjectMembers($storyID); + if($prjMembers) + { + $ccList .= ',' . join(',', $prjMembers); + $ccList = ltrim(',', $ccList); + } + } + + if($toList == '') + { + if($ccList == '') return; + if(strpos($ccList, ',') === false) + { + $toList = $ccList; + $ccList = ''; + } + else + { + $commaPos = strpos($ccList, ','); + $toList = substr($ccList, 0, $commaPos); + $ccList = substr($ccList, $commaPos + 1); + } + } + elseif($toList == 'closed') + { + $toList = $story->openedBy; + } + + /* Get the mail content. */ + $this->view->story = $story; + $this->view->action = $action; + $this->view->users = $this->user->getPairs('noletter'); + $mailContent = $this->parse($this->moduleName, 'sendmail'); + + /* Send it. */ + $this->loadModel('mail')->send($toList, $productName . ':' . 'STORY #' . $story->id . $this->lang->colon . $story->title, $mailContent, $ccList); + if($this->mail->isError()) echo js::error($this->mail->getError()); + } + /** + * The report page. + * + * @param int $productID + * @param string $browseType + * @param int $moduleID + * @access public + * @return void + */ + public function report($productID, $browseType, $moduleID) + { + $this->loadModel('report'); + $this->view->charts = array(); + $this->view->renderJS = ''; + + if(!empty($_POST)) + { + foreach($this->post->charts as $chart) + { + $chartFunc = 'getDataOf' . $chart; + $chartData = $this->story->$chartFunc(); + $chartOption = $this->lang->story->report->$chart; + $this->story->mergeChartOption($chart); + + $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); + $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); + $this->view->datas[$chart] = $this->report->computePercent($chartData); + } + $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); + } + $this->products = $this->product->getPairs(); + $this->product->setMenu($this->products, $productID); + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->story->common; + $this->view->productID = $productID; + $this->view->browseType = $browseType; + $this->view->moduleID = $moduleID; + $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; + $this->display(); + } + + /** + * get data to export + * + * @param int $productID + * @param string $orderBy + * @access public + * @return void + */ + public function export($productID, $orderBy) + { + /* format the fields of every story in order to export data. */ + if($_POST) + { + $storyLang = $this->lang->story; + $storyConfig = $this->config->story; + + /* Create field lists. */ + $fields = explode(',', $storyConfig->list->exportFields); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($storyLang->$fieldName) ? $storyLang->$fieldName : $fieldName; + unset($fields[$key]); + } + + /* Get stories. */ + $stories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyReport)->orderBy($orderBy)->fetchAll('id'); + + /* Get users, products and projects. */ + $users = $this->loadModel('user')->getPairs('noletter'); + $products = $this->loadModel('product')->getPairs(); + + /* Get related objects id lists. */ + $relatedModuleIdList = array(); + $relatedStoryIdList = array(); + $relatedPlanIdList = array(); + + foreach($stories as $story) + { + $relatedModuleIdList[$story->module] = $story->module; + $relatedPlanIdList[$story->plan] = $story->plan; + + /* Process related stories. */ + $relatedStories = $story->childStories . ',' . $story->linkStories . ',' . $story->duplicateStory; + $relatedStories = explode(',', $relatedStories); + foreach($relatedStories as $storyID) + { + if($storyID) $relatedStoryIdList[$storyID] = trim($storyID); + } + } + + /* Get related objects title or names. */ + $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); + $relatedPlans = $this->dao->select('id, title')->from(TABLE_PRODUCTPLAN)->where('id')->in($relatedPlanIdList)->fetchPairs(); + $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); + $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->in(@array_keys($stories))->fetchGroup('objectID'); + $relatedSpecs = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('`story`')->in(@array_keys($stories))->orderBy('version desc')->fetchGroup('story'); + + foreach($stories as $story) + { + $story->spec = ''; + $story->verify = ''; + if(isset($relatedSpecs[$story->id])) + { + $storySpec = $relatedSpecs[$story->id][0]; + $story->title = $storySpec->title; + $story->spec = $storySpec->spec; + $story->verify = $storySpec->verify; + } + + if($this->post->fileType == 'csv') + { + $story->spec = htmlspecialchars_decode($story->spec); + $story->spec = str_replace("
          ", "\n", $story->spec); + $story->spec = str_replace('"', '""', $story->spec); + + $story->verify = htmlspecialchars_decode($story->verify); + $story->verify = str_replace("
          ", "\n", $story->verify); + $story->verify = str_replace('"', '""', $story->verify); + } + + /* fill some field with useful value. */ + if(isset($products[$story->product])) $story->product = $products[$story->product]; + if(isset($relatedModules[$story->module])) $story->module = $relatedModules[$story->module]; + if(isset($relatedPlans[$story->plan])) $story->plan = $relatedPlans[$story->plan]; + if(isset($relatedStories[$story->duplicateStory])) $story->duplicateStory = $relatedStories[$story->duplicateStory]; + + if(isset($storyLang->priList[$story->pri])) $story->pri = $storyLang->priList[$story->pri]; + if(isset($storyLang->statusList[$story->status])) $story->status = $storyLang->statusList[$story->status]; + if(isset($storyLang->stageList[$story->stage])) $story->stage = $storyLang->stageList[$story->stage]; + if(isset($storyLang->reasonList[$story->closedReason])) $story->closedReason = $storyLang->reasonList[$story->closedReason]; + + if(isset($users[$story->openedBy])) $story->openedBy = $users[$story->openedBy]; + if(isset($users[$story->assignedTo])) $story->assignedTo = $users[$story->assignedTo]; + if(isset($users[$story->lastEditedBy])) $story->lastEditedBy = $users[$story->lastEditedBy]; + if(isset($users[$story->closedBy])) $story->closedBy = $users[$story->closedBy]; + + $story->openedDate = substr($story->openedDate, 0, 10); + $story->assignedDate = substr($story->assignedDate, 0, 10); + $story->lastEditedDate = substr($story->lastEditedDate, 0, 10); + $story->closedDate = substr($story->closedDate, 0, 10); + + + if($story->linkStories) + { + $tmpLinkStories = array(); + $linkStoriesIdList = explode(',', $story->linkStories); + foreach($linkStoriesIdList as $linkStoryID) + { + $linkStoryID = trim($linkStoryID); + $tmpLinkStories[] = isset($relatedStories[$linkStoryID]) ? $relatedStories[$linkStoryID] : $linkStoryID; + } + $story->linkStories = join("; \n", $tmpLinkStories); + } + + if($story->childStories) + { + $tmpChildStories = array(); + $childStoriesIdList = explode(',', $story->childStories); + foreach($childStoriesIdList as $childStoryID) + { + $childStoryID = trim($childStoryID); + $tmpChildStories[] = isset($relatedStories[$childStoryID]) ? $relatedStories[$childStoryID] : $childStoryID; + } + $story->childStories = join("; \n", $tmpChildStories); + } + + /* Set related files. */ + if(isset($relatedFiles[$story->id])) + { + foreach($relatedFiles[$story->id] as $file) + { + $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$story->company/" . $file->pathname; + $story->files .= html::a($fileURL, $file->title, '_blank') . '
          '; + } + } + + $story->mailto = trim(trim($story->mailto), ','); + $mailtos = explode(',', $story->mailto); + $story->mailto = ''; + foreach($mailtos as $mailto) + { + $mailto = trim($mailto); + if(isset($users[$mailto])) $story->mailto .= $users[$mailto] . ','; + } + + $story->reviewedBy = trim(trim($story->reviewedBy), ','); + $reviewedBys = explode(',', $story->reviewedBy); + $story->reviewedBy = ''; + foreach($reviewedBys as $reviewedBy) + { + $reviewedBy = trim($reviewedBy); + if(isset($users[$reviewedBy])) $story->reviewedBy .= $users[$reviewedBy] . ','; + } + + } + + $this->post->set('fields', $fields); + $this->post->set('rows', $stories); + $this->fetch('file', 'export2' . $this->post->fileType, $_POST); + } + + $this->display(); + } +} diff --git a/module/story/lang/en.php b/module/story/lang/en.php index 0d2d219e0c..57c1f4c249 100644 --- a/module/story/lang/en.php +++ b/module/story/lang/en.php @@ -1,222 +1,222 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->story->browse = "Browse"; -$lang->story->create = "Create"; -$lang->story->createCase = "Create case"; -$lang->story->batchCreate = "Batch create"; -$lang->story->change = "Change"; -$lang->story->changed = 'Changed'; -$lang->story->review = 'Review'; -$lang->story->edit = "Edit"; -$lang->story->close = 'Close'; -$lang->story->activate = 'Activate'; -$lang->story->delete = "Delete"; -$lang->story->view = "Info"; -$lang->story->tasks = "Tasks"; -$lang->story->taskCount = 'Tasks count'; -$lang->story->bugs = "Bug"; -$lang->story->linkStory = 'Related story'; -$lang->story->export = "Export"; -$lang->story->reportChart = "Report"; - -$lang->story->common = 'Story'; -$lang->story->id = 'ID'; -$lang->story->product = 'Product'; -$lang->story->module = 'Module'; -$lang->story->source = 'Source'; -$lang->story->release = 'Release'; -$lang->story->bug = 'Related Bug'; -$lang->story->title = 'Title'; -$lang->story->spec = 'Spec'; -$lang->story->verify = 'Verify'; -$lang->story->type = 'Type '; -$lang->story->pri = 'Priority'; -$lang->story->estimate = 'Estimate'; -$lang->story->estimateAB = 'Estimate'; -$lang->story->status = 'Status'; -$lang->story->stage = 'Stage'; -$lang->story->stageAB = 'Stage'; -$lang->story->mailto = 'Mailto'; -$lang->story->openedBy = 'Opened by'; -$lang->story->openedDate = 'Opened date'; -$lang->story->assignedTo = 'Assigned to'; -$lang->story->assignedDate = 'Assigned date'; -$lang->story->lastEditedBy = 'Last edited by'; -$lang->story->lastEditedDate = 'Last edited date'; -$lang->story->lastEdited = 'Last edited'; -$lang->story->closedBy = 'Closed by'; -$lang->story->closedDate = 'Closed date'; -$lang->story->closedReason = 'Closed reason'; -$lang->story->rejectedReason = 'Reject reason'; -$lang->story->reviewedBy = 'Reviewed by'; -$lang->story->reviewedDate = 'Reviewed date'; -$lang->story->version = 'Version'; -$lang->story->project = 'Project'; -$lang->story->plan = 'Plan'; -$lang->story->planAB = 'Plan'; -$lang->story->comment = 'Comment'; -$lang->story->linkStories = 'Related story'; -$lang->story->childStories = 'Child story'; -$lang->story->duplicateStory = 'Duplicate story'; -$lang->story->reviewResult = 'Reviewed result'; -$lang->story->preVersion = 'Pre version'; -$lang->story->keywords = 'Keyword'; - -$lang->story->same = 'The same as above'; - -$lang->story->useList[0] = 'No use'; -$lang->story->useList[1] = 'Use'; - -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = 'Draft'; -$lang->story->statusList['active'] = 'Active'; -$lang->story->statusList['closed'] = 'Closed'; -$lang->story->statusList['changed'] = 'Changed'; - -$lang->story->stageList[''] = ''; -$lang->story->stageList['wait'] = 'Waitting'; -$lang->story->stageList['planned'] = 'Planned'; -$lang->story->stageList['projected'] = 'Projected'; -$lang->story->stageList['developing'] = 'Developing'; -$lang->story->stageList['developed'] = 'Developed'; -$lang->story->stageList['testing'] = 'Testing'; -$lang->story->stageList['tested'] = 'Tested'; -$lang->story->stageList['verified'] = 'Verified'; -$lang->story->stageList['released'] = 'Released'; - -$lang->story->reasonList[''] = ''; -$lang->story->reasonList['done'] = 'Done'; -$lang->story->reasonList['subdivided'] = 'Subdivided'; -$lang->story->reasonList['duplicate'] = 'Duplicate'; -$lang->story->reasonList['postponed'] = 'Postponed'; -$lang->story->reasonList['willnotdo'] = "Won't do"; -$lang->story->reasonList['cancel'] = 'Canceled'; -$lang->story->reasonList['bydesign'] = 'By design'; -//$lang->story->reasonList['isbug'] = '是个Bug'; - -$lang->story->reviewResultList[''] = ''; -$lang->story->reviewResultList['pass'] = 'Pass'; -$lang->story->reviewResultList['revert'] = 'Revert'; -$lang->story->reviewResultList['clarify'] = 'Clarify'; -$lang->story->reviewResultList['reject'] = 'Reject'; - -$lang->story->reviewList[0] = 'No'; -$lang->story->reviewList[1] = 'Yes'; - -$lang->story->sourceList[''] = ''; -$lang->story->sourceList['custom'] = 'Custom'; -$lang->story->sourceList['user'] = 'User'; -$lang->story->sourceList['po'] = 'PO'; -$lang->story->sourceList['market'] = 'Market'; -$lang->story->sourceList['service'] = 'Service'; -$lang->story->sourceList['competitor'] = 'Competitor'; -$lang->story->sourceList['partner'] = 'Partner'; -$lang->story->sourceList['dev'] = 'Developer'; -$lang->story->sourceList['tester'] = 'Tester'; -$lang->story->sourceList['bug'] = 'Bug'; -$lang->story->sourceList['other'] = 'Other'; - -$lang->story->priList[] = ''; -$lang->story->priList[3] = '3'; -$lang->story->priList[1] = '1'; -$lang->story->priList[2] = '2'; -$lang->story->priList[4] = '4'; - -$lang->story->legendBasicInfo = 'Basic info'; -$lang->story->legendLifeTime = 'Life time'; -$lang->story->legendRelated = 'Related info'; -$lang->story->legendMailto = 'Maitto'; -$lang->story->legendAttatch = 'Files'; -$lang->story->legendProjectAndTask = 'Project & task'; -$lang->story->legendBugs = 'Related Bug'; -$lang->story->legendFromBug = 'From Bug'; -$lang->story->legendCases = 'Related Case'; -$lang->story->legendLinkStories = 'Related story'; -$lang->story->legendChildStories = 'Child story'; -$lang->story->legendSpec = 'Spec'; -$lang->story->legendVerify = 'Verify standard'; -$lang->story->legendHistory = 'History'; -$lang->story->legendVersion = 'Versions'; -$lang->story->legendMisc = 'Misc'; - -$lang->story->lblChange = 'Change'; -$lang->story->lblReview = 'Review'; -$lang->story->lblActivate = 'Activate'; -$lang->story->lblClose = 'Close'; - -$lang->story->affectedProjects = 'Affected projects'; -$lang->story->affectedBugs = 'Affected bugs'; -$lang->story->affectedCases = 'Affected cases'; - -$lang->story->specTemplate = "Recommend template::As <a type of user>,I want <some goals>,so that <some reason>."; -$lang->story->notes = "(notes:if the title is empty, it is no use)"; -$lang->story->needNotReview = "needn't review"; -$lang->story->confirmDelete = "Are you sure to delete this story?"; -$lang->story->errorFormat = 'Error format'; -$lang->story->errorEmptyTitle = "Title can't be empty"; -$lang->story->mustChooseResult = 'Must choose s result'; -$lang->story->mustChoosePreVersion = 'Must select an version to revert'; -$lang->story->ajaxGetProjectStories = 'API:Project stories'; -$lang->story->ajaxGetProductStories = 'API:Product stories'; - -$lang->story->action->reviewed = array('main' => '$date, Reviewed by $actor, result is $extra.', 'extra' => $lang->story->reviewResultList); -$lang->story->action->closed = array('main' => '$date, Closed by $actor, reason is $extra.', 'extra' => $lang->story->reasonList); -$lang->story->action->linked2plan = array('main' => '$date, Linked to plan $extra by $actor.'); -$lang->story->action->unlinkedfromplan = array('main' => '$date, Removed from $extra> by $actor'); -$lang->story->action->linked2project = array('main' => '$date, Linked to project $extra by $actor.'); -$lang->story->action->unlinkedfromproject = array('main' => '$date, Removed from project $extra by $actor.'); - -/* Report*/ -$lang->story->report->common = 'Report'; -$lang->story->report->select = 'Select'; -$lang->story->report->create = 'Creat'; -$lang->story->report->selectAll = 'All'; -$lang->story->report->selectReverse = 'Reverse'; - -$lang->story->report->charts['storysPerProduct'] = 'Product storys'; -$lang->story->report->charts['storysPerModule'] = 'Module storys'; -$lang->story->report->charts['storysPerSource'] = 'Source storys'; -$lang->story->report->charts['storysPerPlan'] = 'Plan storys'; -$lang->story->report->charts['storysPerStatus'] = 'Sotrys of status'; -$lang->story->report->charts['storysPerStage'] = 'Storys of stage'; -$lang->story->report->charts['storysPerPri'] = 'Storys of priority'; -$lang->story->report->charts['storysPerEstimate'] = 'Storys of Estimate'; -$lang->story->report->charts['storysPerOpenedBy'] = 'Opened by user'; -$lang->story->report->charts['storysPerAssignedTo'] = 'Assigned to user'; -$lang->story->report->charts['storysPerClosedReason'] = 'Storys for reason'; -$lang->story->report->charts['storysPerChange'] = 'Story version'; - -$lang->story->report->options->swf = 'pie2d'; -$lang->story->report->options->width = 'auto'; -$lang->story->report->options->height = 300; -$lang->story->report->options->graph->baseFontSize = 12; -$lang->story->report->options->graph->showNames = 1; -$lang->story->report->options->graph->formatNumber = 1; -$lang->story->report->options->graph->decimalPrecision = 0; -$lang->story->report->options->graph->animation = 0; -$lang->story->report->options->graph->rotateNames = 0; -$lang->story->report->options->graph->yAxisName = 'COUNT'; -$lang->story->report->options->graph->pieRadius = 100; -$lang->story->report->options->graph->showColumnShadow = 0; - -$lang->story->report->storysPerProduct->graph->xAxisName = 'Product'; -$lang->story->report->storysPerModule->graph->xAxisName = 'Module'; -$lang->story->report->storysPerSource->graph->xAxisName = 'Source'; -$lang->story->report->storysPerPlan->graph->xAxisName = 'Plan'; -$lang->story->report->storysPerStatus->graph->xAxisName = 'Status'; -$lang->story->report->storysPerStage->graph->xAxisName = 'Stage'; -$lang->story->report->storysPerPri->graph->xAxisName = 'Priority'; -$lang->story->report->storysPerOpenedBy->graph->xAxisName = 'Opened by'; -$lang->story->report->storysPerAssignedTo->graph->xAxisName = 'Assigned to'; -$lang->story->report->storysPerClosedReason->graph->xAxisName = 'Closed reason'; -$lang->story->report->storysPerEstimate->graph->xAxisName = 'Estimate'; -$lang->story->report->storysPerChange->graph->xAxisName = 'Change'; + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->story->browse = "Browse"; +$lang->story->create = "Create"; +$lang->story->createCase = "Create case"; +$lang->story->batchCreate = "Batch create"; +$lang->story->change = "Change"; +$lang->story->changed = 'Changed'; +$lang->story->review = 'Review'; +$lang->story->edit = "Edit"; +$lang->story->close = 'Close'; +$lang->story->activate = 'Activate'; +$lang->story->delete = "Delete"; +$lang->story->view = "Info"; +$lang->story->tasks = "Tasks"; +$lang->story->taskCount = 'Tasks count'; +$lang->story->bugs = "Bug"; +$lang->story->linkStory = 'Related story'; +$lang->story->export = "Export"; +$lang->story->reportChart = "Report"; + +$lang->story->common = 'Story'; +$lang->story->id = 'ID'; +$lang->story->product = 'Product'; +$lang->story->module = 'Module'; +$lang->story->source = 'Source'; +$lang->story->release = 'Release'; +$lang->story->bug = 'Related Bug'; +$lang->story->title = 'Title'; +$lang->story->spec = 'Spec'; +$lang->story->verify = 'Verify'; +$lang->story->type = 'Type '; +$lang->story->pri = 'Priority'; +$lang->story->estimate = 'Estimate'; +$lang->story->estimateAB = 'Estimate'; +$lang->story->status = 'Status'; +$lang->story->stage = 'Stage'; +$lang->story->stageAB = 'Stage'; +$lang->story->mailto = 'Mailto'; +$lang->story->openedBy = 'Opened by'; +$lang->story->openedDate = 'Opened date'; +$lang->story->assignedTo = 'Assigned to'; +$lang->story->assignedDate = 'Assigned date'; +$lang->story->lastEditedBy = 'Last edited by'; +$lang->story->lastEditedDate = 'Last edited date'; +$lang->story->lastEdited = 'Last edited'; +$lang->story->closedBy = 'Closed by'; +$lang->story->closedDate = 'Closed date'; +$lang->story->closedReason = 'Closed reason'; +$lang->story->rejectedReason = 'Reject reason'; +$lang->story->reviewedBy = 'Reviewed by'; +$lang->story->reviewedDate = 'Reviewed date'; +$lang->story->version = 'Version'; +$lang->story->project = 'Project'; +$lang->story->plan = 'Plan'; +$lang->story->planAB = 'Plan'; +$lang->story->comment = 'Comment'; +$lang->story->linkStories = 'Related story'; +$lang->story->childStories = 'Child story'; +$lang->story->duplicateStory = 'Duplicate story'; +$lang->story->reviewResult = 'Reviewed result'; +$lang->story->preVersion = 'Pre version'; +$lang->story->keywords = 'Keyword'; + +$lang->story->same = 'The same as above'; + +$lang->story->useList[0] = 'No use'; +$lang->story->useList[1] = 'Use'; + +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = 'Draft'; +$lang->story->statusList['active'] = 'Active'; +$lang->story->statusList['closed'] = 'Closed'; +$lang->story->statusList['changed'] = 'Changed'; + +$lang->story->stageList[''] = ''; +$lang->story->stageList['wait'] = 'Waitting'; +$lang->story->stageList['planned'] = 'Planned'; +$lang->story->stageList['projected'] = 'Projected'; +$lang->story->stageList['developing'] = 'Developing'; +$lang->story->stageList['developed'] = 'Developed'; +$lang->story->stageList['testing'] = 'Testing'; +$lang->story->stageList['tested'] = 'Tested'; +$lang->story->stageList['verified'] = 'Verified'; +$lang->story->stageList['released'] = 'Released'; + +$lang->story->reasonList[''] = ''; +$lang->story->reasonList['done'] = 'Done'; +$lang->story->reasonList['subdivided'] = 'Subdivided'; +$lang->story->reasonList['duplicate'] = 'Duplicate'; +$lang->story->reasonList['postponed'] = 'Postponed'; +$lang->story->reasonList['willnotdo'] = "Won't do"; +$lang->story->reasonList['cancel'] = 'Canceled'; +$lang->story->reasonList['bydesign'] = 'By design'; +//$lang->story->reasonList['isbug'] = '是个Bug'; + +$lang->story->reviewResultList[''] = ''; +$lang->story->reviewResultList['pass'] = 'Pass'; +$lang->story->reviewResultList['revert'] = 'Revert'; +$lang->story->reviewResultList['clarify'] = 'Clarify'; +$lang->story->reviewResultList['reject'] = 'Reject'; + +$lang->story->reviewList[0] = 'No'; +$lang->story->reviewList[1] = 'Yes'; + +$lang->story->sourceList[''] = ''; +$lang->story->sourceList['custom'] = 'Custom'; +$lang->story->sourceList['user'] = 'User'; +$lang->story->sourceList['po'] = 'PO'; +$lang->story->sourceList['market'] = 'Market'; +$lang->story->sourceList['service'] = 'Service'; +$lang->story->sourceList['competitor'] = 'Competitor'; +$lang->story->sourceList['partner'] = 'Partner'; +$lang->story->sourceList['dev'] = 'Developer'; +$lang->story->sourceList['tester'] = 'Tester'; +$lang->story->sourceList['bug'] = 'Bug'; +$lang->story->sourceList['other'] = 'Other'; + +$lang->story->priList[] = ''; +$lang->story->priList[3] = '3'; +$lang->story->priList[1] = '1'; +$lang->story->priList[2] = '2'; +$lang->story->priList[4] = '4'; + +$lang->story->legendBasicInfo = 'Basic info'; +$lang->story->legendLifeTime = 'Life time'; +$lang->story->legendRelated = 'Related info'; +$lang->story->legendMailto = 'Maitto'; +$lang->story->legendAttatch = 'Files'; +$lang->story->legendProjectAndTask = 'Project & task'; +$lang->story->legendBugs = 'Related Bug'; +$lang->story->legendFromBug = 'From Bug'; +$lang->story->legendCases = 'Related Case'; +$lang->story->legendLinkStories = 'Related story'; +$lang->story->legendChildStories = 'Child story'; +$lang->story->legendSpec = 'Spec'; +$lang->story->legendVerify = 'Verify standard'; +$lang->story->legendHistory = 'History'; +$lang->story->legendVersion = 'Versions'; +$lang->story->legendMisc = 'Misc'; + +$lang->story->lblChange = 'Change'; +$lang->story->lblReview = 'Review'; +$lang->story->lblActivate = 'Activate'; +$lang->story->lblClose = 'Close'; + +$lang->story->affectedProjects = 'Affected projects'; +$lang->story->affectedBugs = 'Affected bugs'; +$lang->story->affectedCases = 'Affected cases'; + +$lang->story->specTemplate = "Recommend template::As <a type of user>,I want <some goals>,so that <some reason>."; +$lang->story->notes = "(notes:if the title is empty, it is no use)"; +$lang->story->needNotReview = "needn't review"; +$lang->story->confirmDelete = "Are you sure to delete this story?"; +$lang->story->errorFormat = 'Error format'; +$lang->story->errorEmptyTitle = "Title can't be empty"; +$lang->story->mustChooseResult = 'Must choose s result'; +$lang->story->mustChoosePreVersion = 'Must select an version to revert'; +$lang->story->ajaxGetProjectStories = 'API:Project stories'; +$lang->story->ajaxGetProductStories = 'API:Product stories'; + +$lang->story->action->reviewed = array('main' => '$date, Reviewed by $actor, result is $extra.', 'extra' => $lang->story->reviewResultList); +$lang->story->action->closed = array('main' => '$date, Closed by $actor, reason is $extra.', 'extra' => $lang->story->reasonList); +$lang->story->action->linked2plan = array('main' => '$date, Linked to plan $extra by $actor.'); +$lang->story->action->unlinkedfromplan = array('main' => '$date, Removed from $extra> by $actor'); +$lang->story->action->linked2project = array('main' => '$date, Linked to project $extra by $actor.'); +$lang->story->action->unlinkedfromproject = array('main' => '$date, Removed from project $extra by $actor.'); + +/* Report*/ +$lang->story->report->common = 'Report'; +$lang->story->report->select = 'Select'; +$lang->story->report->create = 'Creat'; +$lang->story->report->selectAll = 'All'; +$lang->story->report->selectReverse = 'Reverse'; + +$lang->story->report->charts['storysPerProduct'] = 'Product storys'; +$lang->story->report->charts['storysPerModule'] = 'Module storys'; +$lang->story->report->charts['storysPerSource'] = 'Source storys'; +$lang->story->report->charts['storysPerPlan'] = 'Plan storys'; +$lang->story->report->charts['storysPerStatus'] = 'Sotrys of status'; +$lang->story->report->charts['storysPerStage'] = 'Storys of stage'; +$lang->story->report->charts['storysPerPri'] = 'Storys of priority'; +$lang->story->report->charts['storysPerEstimate'] = 'Storys of Estimate'; +$lang->story->report->charts['storysPerOpenedBy'] = 'Opened by user'; +$lang->story->report->charts['storysPerAssignedTo'] = 'Assigned to user'; +$lang->story->report->charts['storysPerClosedReason'] = 'Storys for reason'; +$lang->story->report->charts['storysPerChange'] = 'Story version'; + +$lang->story->report->options->swf = 'pie2d'; +$lang->story->report->options->width = 'auto'; +$lang->story->report->options->height = 300; +$lang->story->report->options->graph->baseFontSize = 12; +$lang->story->report->options->graph->showNames = 1; +$lang->story->report->options->graph->formatNumber = 1; +$lang->story->report->options->graph->decimalPrecision = 0; +$lang->story->report->options->graph->animation = 0; +$lang->story->report->options->graph->rotateNames = 0; +$lang->story->report->options->graph->yAxisName = 'COUNT'; +$lang->story->report->options->graph->pieRadius = 100; +$lang->story->report->options->graph->showColumnShadow = 0; + +$lang->story->report->storysPerProduct->graph->xAxisName = 'Product'; +$lang->story->report->storysPerModule->graph->xAxisName = 'Module'; +$lang->story->report->storysPerSource->graph->xAxisName = 'Source'; +$lang->story->report->storysPerPlan->graph->xAxisName = 'Plan'; +$lang->story->report->storysPerStatus->graph->xAxisName = 'Status'; +$lang->story->report->storysPerStage->graph->xAxisName = 'Stage'; +$lang->story->report->storysPerPri->graph->xAxisName = 'Priority'; +$lang->story->report->storysPerOpenedBy->graph->xAxisName = 'Opened by'; +$lang->story->report->storysPerAssignedTo->graph->xAxisName = 'Assigned to'; +$lang->story->report->storysPerClosedReason->graph->xAxisName = 'Closed reason'; +$lang->story->report->storysPerEstimate->graph->xAxisName = 'Estimate'; +$lang->story->report->storysPerChange->graph->xAxisName = 'Change'; diff --git a/module/story/lang/zh-cn.php b/module/story/lang/zh-cn.php index 6677d55395..8047bdc3da 100644 --- a/module/story/lang/zh-cn.php +++ b/module/story/lang/zh-cn.php @@ -1,222 +1,222 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->story->browse = "需求列表"; -$lang->story->create = "新增需求"; -$lang->story->createCase = "建用例"; -$lang->story->batchCreate = "批量添加"; -$lang->story->change = "变更"; -$lang->story->changed = '需求变更'; -$lang->story->review = '评审'; -$lang->story->edit = "编辑需求"; -$lang->story->close = '关闭'; -$lang->story->activate = '激活'; -$lang->story->delete = "删除需求"; -$lang->story->view = "需求详情"; -$lang->story->tasks = "相关任务"; -$lang->story->taskCount = '任务数'; -$lang->story->bugs = "Bug"; -$lang->story->linkStory = '关联需求'; -$lang->story->export = "导出数据"; -$lang->story->reportChart = "统计报表"; - -$lang->story->common = '需求'; -$lang->story->id = '编号'; -$lang->story->product = '所属产品'; -$lang->story->module = '所属模块'; -$lang->story->source = '来源'; -$lang->story->release = '发布计划'; -$lang->story->bug = '相关bug'; -$lang->story->title = '需求名称'; -$lang->story->spec = '需求描述'; -$lang->story->verify = '验收标准'; -$lang->story->type = '需求类型 '; -$lang->story->pri = '优先级'; -$lang->story->estimate = '预计工时'; -$lang->story->estimateAB = '预计'; -$lang->story->status = '当前状态'; -$lang->story->stage = '所处阶段'; -$lang->story->stageAB = '阶段'; -$lang->story->mailto = '抄送给'; -$lang->story->openedBy = '由谁创建'; -$lang->story->openedDate = '创建日期'; -$lang->story->assignedTo = '指派给'; -$lang->story->assignedDate = '指派日期'; -$lang->story->lastEditedBy = '最后修改'; -$lang->story->lastEditedDate = '最后修改日期'; -$lang->story->lastEdited = '最后修改'; -$lang->story->closedBy = '由谁关闭'; -$lang->story->closedDate = '关闭日期'; -$lang->story->closedReason = '关闭原因'; -$lang->story->rejectedReason = '拒绝原因'; -$lang->story->reviewedBy = '由谁评审'; -$lang->story->reviewedDate = '评审时间'; -$lang->story->version = '版本号'; -$lang->story->project = '所属项目'; -$lang->story->plan = '所属计划'; -$lang->story->planAB = '计划'; -$lang->story->comment = '备注'; -$lang->story->linkStories = '相关需求'; -$lang->story->childStories = '细分需求'; -$lang->story->duplicateStory = '重复需求'; -$lang->story->reviewResult = '评审结果'; -$lang->story->preVersion = '之前版本'; -$lang->story->keywords = '关键词'; - -$lang->story->same = '同上'; - -$lang->story->useList[0] = '不使用'; -$lang->story->useList[1] = '使用'; - -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = '草稿'; -$lang->story->statusList['active'] = '激活'; -$lang->story->statusList['closed'] = '已关闭'; -$lang->story->statusList['changed'] = '已变更'; - -$lang->story->stageList[''] = ''; -$lang->story->stageList['wait'] = '未开始'; -$lang->story->stageList['planned'] = '已计划'; -$lang->story->stageList['projected'] = '已立项'; -$lang->story->stageList['developing'] = '研发中'; -$lang->story->stageList['developed'] = '研发完毕'; -$lang->story->stageList['testing'] = '测试中'; -$lang->story->stageList['tested'] = '测试完毕'; -$lang->story->stageList['verified'] = '已验收'; -$lang->story->stageList['released'] = '已发布'; - -$lang->story->reasonList[''] = ''; -$lang->story->reasonList['done'] = '已完成'; -$lang->story->reasonList['subdivided'] = '已细分'; -$lang->story->reasonList['duplicate'] = '重复'; -$lang->story->reasonList['postponed'] = '延期'; -$lang->story->reasonList['willnotdo'] = '不做'; -$lang->story->reasonList['cancel'] = '已取消'; -$lang->story->reasonList['bydesign'] = '设计如此'; -//$lang->story->reasonList['isbug'] = '是个Bug'; - -$lang->story->reviewResultList[''] = ''; -$lang->story->reviewResultList['pass'] = '确认通过'; -$lang->story->reviewResultList['revert'] = '撤销变更'; -$lang->story->reviewResultList['clarify'] = '有待明确'; -$lang->story->reviewResultList['reject'] = '拒绝'; - -$lang->story->reviewList[0] = '否'; -$lang->story->reviewList[1] = '是'; - -$lang->story->sourceList[''] = ''; -$lang->story->sourceList['custom'] = '客户'; -$lang->story->sourceList['user'] = '用户'; -$lang->story->sourceList['po'] = '产品经理'; -$lang->story->sourceList['market'] = '市场'; -$lang->story->sourceList['service'] = '客服'; -$lang->story->sourceList['competitor'] = '竞争对手'; -$lang->story->sourceList['partner'] = '合作伙伴'; -$lang->story->sourceList['dev'] = '开发人员'; -$lang->story->sourceList['tester'] = '测试人员'; -$lang->story->sourceList['bug'] = 'Bug'; -$lang->story->sourceList['other'] = '其他'; - -$lang->story->priList[] = ''; -$lang->story->priList[3] = '3'; -$lang->story->priList[1] = '1'; -$lang->story->priList[2] = '2'; -$lang->story->priList[4] = '4'; - -$lang->story->legendBasicInfo = '基本信息'; -$lang->story->legendLifeTime = '需求的一生'; -$lang->story->legendRelated = '相关信息'; -$lang->story->legendMailto = '抄送给'; -$lang->story->legendAttatch = '附件'; -$lang->story->legendProjectAndTask = '项目任务'; -$lang->story->legendBugs = '相关Bug'; -$lang->story->legendFromBug = '来源Bug'; -$lang->story->legendCases = '相关用例'; -$lang->story->legendLinkStories = '相关需求'; -$lang->story->legendChildStories = '细分需求'; -$lang->story->legendSpec = '需求描述'; -$lang->story->legendVerify = '验收标准'; -$lang->story->legendHistory = '历史记录'; -$lang->story->legendVersion = '历史版本'; -$lang->story->legendMisc = '其他相关'; - -$lang->story->lblChange = '变更需求'; -$lang->story->lblReview = '评审需求'; -$lang->story->lblActivate = '激活需求'; -$lang->story->lblClose = '关闭需求'; - -$lang->story->affectedProjects = '影响的项目'; -$lang->story->affectedBugs = '影响的Bug'; -$lang->story->affectedCases = '影响的用例'; - -$lang->story->specTemplate = "建议参考的模板:作为一名<某种类型的用户>,我希望<达成某些目的>,这样可以<开发的价值>。"; -$lang->story->notes = '(注:如果“需求标题”为空,则表示不使用此行)'; -$lang->story->needNotReview = '不需要评审'; -$lang->story->confirmDelete = "您确认删除该需求吗?"; -$lang->story->errorFormat = '需求数据有误'; -$lang->story->errorEmptyTitle = '标题不能为空'; -$lang->story->mustChooseResult = '必须选择评审结果'; -$lang->story->mustChoosePreVersion = '必须选择回溯的版本'; -$lang->story->ajaxGetProjectStories = '接口:获取项目需求列表'; -$lang->story->ajaxGetProductStories = '接口:获取产品需求列表'; - -$lang->story->action->reviewed = array('main' => '$date, 由 $actor 记录评审结果,结果为 $extra。', 'extra' => $lang->story->reviewResultList); -$lang->story->action->closed = array('main' => '$date, 由 $actor 关闭,原因为 $extra。', 'extra' => $lang->story->reasonList); -$lang->story->action->linked2plan = array('main' => '$date, 由 $actor 关联到计划 $extra。'); -$lang->story->action->unlinkedfromplan = array('main' => '$date, 由 $actor 从计划 $extra 移除。'); -$lang->story->action->linked2project = array('main' => '$date, 由 $actor 关联到项目 $extra。'); -$lang->story->action->unlinkedfromproject = array('main' => '$date, 由 $actor 从项目 $extra 移除。'); - -/* 统计报表。*/ -$lang->story->report->common = '统计报表'; -$lang->story->report->select = '请选择报表类型'; -$lang->story->report->create = '生成报表'; -$lang->story->report->selectAll = '全选'; -$lang->story->report->selectReverse = '反选'; - -$lang->story->report->charts['storysPerProduct'] = '产品需求数量'; -$lang->story->report->charts['storysPerModule'] = '模块需求数量'; -$lang->story->report->charts['storysPerSource'] = '需求来源统计'; -$lang->story->report->charts['storysPerPlan'] = '计划进行统计'; -$lang->story->report->charts['storysPerStatus'] = '状态进行统计'; -$lang->story->report->charts['storysPerStage'] = '所处阶段进行统计'; -$lang->story->report->charts['storysPerPri'] = '优先级进行统计'; -$lang->story->report->charts['storysPerEstimate'] = '预计工时进行统计'; -$lang->story->report->charts['storysPerOpenedBy'] = '由谁创建来进行统计'; -$lang->story->report->charts['storysPerAssignedTo'] = '当前指派来进行统计'; -$lang->story->report->charts['storysPerClosedReason'] = '关闭原因来进行统计'; -$lang->story->report->charts['storysPerChange'] = '变更次数来进行统计'; - -$lang->story->report->options->swf = 'pie2d'; -$lang->story->report->options->width = 'auto'; -$lang->story->report->options->height = 300; -$lang->story->report->options->graph->baseFontSize = 12; -$lang->story->report->options->graph->showNames = 1; -$lang->story->report->options->graph->formatNumber = 1; -$lang->story->report->options->graph->decimalPrecision = 0; -$lang->story->report->options->graph->animation = 0; -$lang->story->report->options->graph->rotateNames = 0; -$lang->story->report->options->graph->yAxisName = 'COUNT'; -$lang->story->report->options->graph->pieRadius = 100; // 饼图直径。 -$lang->story->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 - -$lang->story->report->storysPerProduct->graph->xAxisName = '产品'; -$lang->story->report->storysPerModule->graph->xAxisName = '模块'; -$lang->story->report->storysPerSource->graph->xAxisName = '来源'; -$lang->story->report->storysPerPlan->graph->xAxisName = '产品计划'; -$lang->story->report->storysPerStatus->graph->xAxisName = '状态'; -$lang->story->report->storysPerStage->graph->xAxisName = '所处阶段'; -$lang->story->report->storysPerPri->graph->xAxisName = '优先级'; -$lang->story->report->storysPerOpenedBy->graph->xAxisName = '由谁创建'; -$lang->story->report->storysPerAssignedTo->graph->xAxisName = '当前指派'; -$lang->story->report->storysPerClosedReason->graph->xAxisName = '关闭原因'; -$lang->story->report->storysPerEstimate->graph->xAxisName = '预计时间'; -$lang->story->report->storysPerChange->graph->xAxisName = '变更次数'; + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->story->browse = "需求列表"; +$lang->story->create = "新增需求"; +$lang->story->createCase = "建用例"; +$lang->story->batchCreate = "批量添加"; +$lang->story->change = "变更"; +$lang->story->changed = '需求变更'; +$lang->story->review = '评审'; +$lang->story->edit = "编辑需求"; +$lang->story->close = '关闭'; +$lang->story->activate = '激活'; +$lang->story->delete = "删除需求"; +$lang->story->view = "需求详情"; +$lang->story->tasks = "相关任务"; +$lang->story->taskCount = '任务数'; +$lang->story->bugs = "Bug"; +$lang->story->linkStory = '关联需求'; +$lang->story->export = "导出数据"; +$lang->story->reportChart = "统计报表"; + +$lang->story->common = '需求'; +$lang->story->id = '编号'; +$lang->story->product = '所属产品'; +$lang->story->module = '所属模块'; +$lang->story->source = '来源'; +$lang->story->release = '发布计划'; +$lang->story->bug = '相关bug'; +$lang->story->title = '需求名称'; +$lang->story->spec = '需求描述'; +$lang->story->verify = '验收标准'; +$lang->story->type = '需求类型 '; +$lang->story->pri = '优先级'; +$lang->story->estimate = '预计工时'; +$lang->story->estimateAB = '预计'; +$lang->story->status = '当前状态'; +$lang->story->stage = '所处阶段'; +$lang->story->stageAB = '阶段'; +$lang->story->mailto = '抄送给'; +$lang->story->openedBy = '由谁创建'; +$lang->story->openedDate = '创建日期'; +$lang->story->assignedTo = '指派给'; +$lang->story->assignedDate = '指派日期'; +$lang->story->lastEditedBy = '最后修改'; +$lang->story->lastEditedDate = '最后修改日期'; +$lang->story->lastEdited = '最后修改'; +$lang->story->closedBy = '由谁关闭'; +$lang->story->closedDate = '关闭日期'; +$lang->story->closedReason = '关闭原因'; +$lang->story->rejectedReason = '拒绝原因'; +$lang->story->reviewedBy = '由谁评审'; +$lang->story->reviewedDate = '评审时间'; +$lang->story->version = '版本号'; +$lang->story->project = '所属项目'; +$lang->story->plan = '所属计划'; +$lang->story->planAB = '计划'; +$lang->story->comment = '备注'; +$lang->story->linkStories = '相关需求'; +$lang->story->childStories = '细分需求'; +$lang->story->duplicateStory = '重复需求'; +$lang->story->reviewResult = '评审结果'; +$lang->story->preVersion = '之前版本'; +$lang->story->keywords = '关键词'; + +$lang->story->same = '同上'; + +$lang->story->useList[0] = '不使用'; +$lang->story->useList[1] = '使用'; + +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = '草稿'; +$lang->story->statusList['active'] = '激活'; +$lang->story->statusList['closed'] = '已关闭'; +$lang->story->statusList['changed'] = '已变更'; + +$lang->story->stageList[''] = ''; +$lang->story->stageList['wait'] = '未开始'; +$lang->story->stageList['planned'] = '已计划'; +$lang->story->stageList['projected'] = '已立项'; +$lang->story->stageList['developing'] = '研发中'; +$lang->story->stageList['developed'] = '研发完毕'; +$lang->story->stageList['testing'] = '测试中'; +$lang->story->stageList['tested'] = '测试完毕'; +$lang->story->stageList['verified'] = '已验收'; +$lang->story->stageList['released'] = '已发布'; + +$lang->story->reasonList[''] = ''; +$lang->story->reasonList['done'] = '已完成'; +$lang->story->reasonList['subdivided'] = '已细分'; +$lang->story->reasonList['duplicate'] = '重复'; +$lang->story->reasonList['postponed'] = '延期'; +$lang->story->reasonList['willnotdo'] = '不做'; +$lang->story->reasonList['cancel'] = '已取消'; +$lang->story->reasonList['bydesign'] = '设计如此'; +//$lang->story->reasonList['isbug'] = '是个Bug'; + +$lang->story->reviewResultList[''] = ''; +$lang->story->reviewResultList['pass'] = '确认通过'; +$lang->story->reviewResultList['revert'] = '撤销变更'; +$lang->story->reviewResultList['clarify'] = '有待明确'; +$lang->story->reviewResultList['reject'] = '拒绝'; + +$lang->story->reviewList[0] = '否'; +$lang->story->reviewList[1] = '是'; + +$lang->story->sourceList[''] = ''; +$lang->story->sourceList['custom'] = '客户'; +$lang->story->sourceList['user'] = '用户'; +$lang->story->sourceList['po'] = '产品经理'; +$lang->story->sourceList['market'] = '市场'; +$lang->story->sourceList['service'] = '客服'; +$lang->story->sourceList['competitor'] = '竞争对手'; +$lang->story->sourceList['partner'] = '合作伙伴'; +$lang->story->sourceList['dev'] = '开发人员'; +$lang->story->sourceList['tester'] = '测试人员'; +$lang->story->sourceList['bug'] = 'Bug'; +$lang->story->sourceList['other'] = '其他'; + +$lang->story->priList[] = ''; +$lang->story->priList[3] = '3'; +$lang->story->priList[1] = '1'; +$lang->story->priList[2] = '2'; +$lang->story->priList[4] = '4'; + +$lang->story->legendBasicInfo = '基本信息'; +$lang->story->legendLifeTime = '需求的一生'; +$lang->story->legendRelated = '相关信息'; +$lang->story->legendMailto = '抄送给'; +$lang->story->legendAttatch = '附件'; +$lang->story->legendProjectAndTask = '项目任务'; +$lang->story->legendBugs = '相关Bug'; +$lang->story->legendFromBug = '来源Bug'; +$lang->story->legendCases = '相关用例'; +$lang->story->legendLinkStories = '相关需求'; +$lang->story->legendChildStories = '细分需求'; +$lang->story->legendSpec = '需求描述'; +$lang->story->legendVerify = '验收标准'; +$lang->story->legendHistory = '历史记录'; +$lang->story->legendVersion = '历史版本'; +$lang->story->legendMisc = '其他相关'; + +$lang->story->lblChange = '变更需求'; +$lang->story->lblReview = '评审需求'; +$lang->story->lblActivate = '激活需求'; +$lang->story->lblClose = '关闭需求'; + +$lang->story->affectedProjects = '影响的项目'; +$lang->story->affectedBugs = '影响的Bug'; +$lang->story->affectedCases = '影响的用例'; + +$lang->story->specTemplate = "建议参考的模板:作为一名<某种类型的用户>,我希望<达成某些目的>,这样可以<开发的价值>。"; +$lang->story->notes = '(注:如果“需求标题”为空,则表示不使用此行)'; +$lang->story->needNotReview = '不需要评审'; +$lang->story->confirmDelete = "您确认删除该需求吗?"; +$lang->story->errorFormat = '需求数据有误'; +$lang->story->errorEmptyTitle = '标题不能为空'; +$lang->story->mustChooseResult = '必须选择评审结果'; +$lang->story->mustChoosePreVersion = '必须选择回溯的版本'; +$lang->story->ajaxGetProjectStories = '接口:获取项目需求列表'; +$lang->story->ajaxGetProductStories = '接口:获取产品需求列表'; + +$lang->story->action->reviewed = array('main' => '$date, 由 $actor 记录评审结果,结果为 $extra。', 'extra' => $lang->story->reviewResultList); +$lang->story->action->closed = array('main' => '$date, 由 $actor 关闭,原因为 $extra。', 'extra' => $lang->story->reasonList); +$lang->story->action->linked2plan = array('main' => '$date, 由 $actor 关联到计划 $extra。'); +$lang->story->action->unlinkedfromplan = array('main' => '$date, 由 $actor 从计划 $extra 移除。'); +$lang->story->action->linked2project = array('main' => '$date, 由 $actor 关联到项目 $extra。'); +$lang->story->action->unlinkedfromproject = array('main' => '$date, 由 $actor 从项目 $extra 移除。'); + +/* 统计报表。*/ +$lang->story->report->common = '统计报表'; +$lang->story->report->select = '请选择报表类型'; +$lang->story->report->create = '生成报表'; +$lang->story->report->selectAll = '全选'; +$lang->story->report->selectReverse = '反选'; + +$lang->story->report->charts['storysPerProduct'] = '产品需求数量'; +$lang->story->report->charts['storysPerModule'] = '模块需求数量'; +$lang->story->report->charts['storysPerSource'] = '需求来源统计'; +$lang->story->report->charts['storysPerPlan'] = '计划进行统计'; +$lang->story->report->charts['storysPerStatus'] = '状态进行统计'; +$lang->story->report->charts['storysPerStage'] = '所处阶段进行统计'; +$lang->story->report->charts['storysPerPri'] = '优先级进行统计'; +$lang->story->report->charts['storysPerEstimate'] = '预计工时进行统计'; +$lang->story->report->charts['storysPerOpenedBy'] = '由谁创建来进行统计'; +$lang->story->report->charts['storysPerAssignedTo'] = '当前指派来进行统计'; +$lang->story->report->charts['storysPerClosedReason'] = '关闭原因来进行统计'; +$lang->story->report->charts['storysPerChange'] = '变更次数来进行统计'; + +$lang->story->report->options->swf = 'pie2d'; +$lang->story->report->options->width = 'auto'; +$lang->story->report->options->height = 300; +$lang->story->report->options->graph->baseFontSize = 12; +$lang->story->report->options->graph->showNames = 1; +$lang->story->report->options->graph->formatNumber = 1; +$lang->story->report->options->graph->decimalPrecision = 0; +$lang->story->report->options->graph->animation = 0; +$lang->story->report->options->graph->rotateNames = 0; +$lang->story->report->options->graph->yAxisName = 'COUNT'; +$lang->story->report->options->graph->pieRadius = 100; // 饼图直径。 +$lang->story->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 + +$lang->story->report->storysPerProduct->graph->xAxisName = '产品'; +$lang->story->report->storysPerModule->graph->xAxisName = '模块'; +$lang->story->report->storysPerSource->graph->xAxisName = '来源'; +$lang->story->report->storysPerPlan->graph->xAxisName = '产品计划'; +$lang->story->report->storysPerStatus->graph->xAxisName = '状态'; +$lang->story->report->storysPerStage->graph->xAxisName = '所处阶段'; +$lang->story->report->storysPerPri->graph->xAxisName = '优先级'; +$lang->story->report->storysPerOpenedBy->graph->xAxisName = '由谁创建'; +$lang->story->report->storysPerAssignedTo->graph->xAxisName = '当前指派'; +$lang->story->report->storysPerClosedReason->graph->xAxisName = '关闭原因'; +$lang->story->report->storysPerEstimate->graph->xAxisName = '预计时间'; +$lang->story->report->storysPerChange->graph->xAxisName = '变更次数'; diff --git a/module/story/lang/zh-tw.php b/module/story/lang/zh-tw.php index c60012df8f..93384f1aac 100644 --- a/module/story/lang/zh-tw.php +++ b/module/story/lang/zh-tw.php @@ -1,222 +1,222 @@ - - * @package story - * @version $Id: zh-tw.php 2471 2011-12-24 01:40:31Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->story->browse = "需求列表"; -$lang->story->create = "新增需求"; -$lang->story->createCase = "建用例"; -$lang->story->batchCreate = "批量添加"; -$lang->story->change = "變更"; -$lang->story->changed = '需求變更'; -$lang->story->review = '評審'; -$lang->story->edit = "編輯需求"; -$lang->story->close = '關閉'; -$lang->story->activate = '激活'; -$lang->story->delete = "刪除需求"; -$lang->story->view = "需求詳情"; -$lang->story->tasks = "相關任務"; -$lang->story->taskCount = '任務數'; -$lang->story->bugs = "Bug"; -$lang->story->linkStory = '關聯需求'; -$lang->story->export = "導出數據"; -$lang->story->reportChart = "統計報表"; - -$lang->story->common = '需求'; -$lang->story->id = '編號'; -$lang->story->product = '所屬產品'; -$lang->story->module = '所屬模組'; -$lang->story->source = '來源'; -$lang->story->release = '發佈計劃'; -$lang->story->bug = '相關bug'; -$lang->story->title = '需求名稱'; -$lang->story->spec = '需求描述'; -$lang->story->verify = '驗收標準'; -$lang->story->type = '需求類型 '; -$lang->story->pri = '優先順序'; -$lang->story->estimate = '預計工時'; -$lang->story->estimateAB = '預計'; -$lang->story->status = '當前狀態'; -$lang->story->stage = '所處階段'; -$lang->story->stageAB = '階段'; -$lang->story->mailto = '抄送給'; -$lang->story->openedBy = '由誰創建'; -$lang->story->openedDate = '創建日期'; -$lang->story->assignedTo = '指派給'; -$lang->story->assignedDate = '指派日期'; -$lang->story->lastEditedBy = '最後修改'; -$lang->story->lastEditedDate = '最後修改日期'; -$lang->story->lastEdited = '最後修改'; -$lang->story->closedBy = '由誰關閉'; -$lang->story->closedDate = '關閉日期'; -$lang->story->closedReason = '關閉原因'; -$lang->story->rejectedReason = '拒絶原因'; -$lang->story->reviewedBy = '由誰評審'; -$lang->story->reviewedDate = '評審時間'; -$lang->story->version = '版本號'; -$lang->story->project = '所屬項目'; -$lang->story->plan = '所屬計劃'; -$lang->story->planAB = '計劃'; -$lang->story->comment = '備註'; -$lang->story->linkStories = '相關需求'; -$lang->story->childStories = '細分需求'; -$lang->story->duplicateStory = '重複需求'; -$lang->story->reviewResult = '評審結果'; -$lang->story->preVersion = '之前版本'; -$lang->story->keywords = '關鍵詞'; - -$lang->story->same = '同上'; - -$lang->story->useList[0] = '不使用'; -$lang->story->useList[1] = '使用'; - -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = '草稿'; -$lang->story->statusList['active'] = '激活'; -$lang->story->statusList['closed'] = '已關閉'; -$lang->story->statusList['changed'] = '已變更'; - -$lang->story->stageList[''] = ''; -$lang->story->stageList['wait'] = '未開始'; -$lang->story->stageList['planned'] = '已計劃'; -$lang->story->stageList['projected'] = '已立項'; -$lang->story->stageList['developing'] = '研發中'; -$lang->story->stageList['developed'] = '研發完畢'; -$lang->story->stageList['testing'] = '測試中'; -$lang->story->stageList['tested'] = '測試完畢'; -$lang->story->stageList['verified'] = '已驗收'; -$lang->story->stageList['released'] = '已發佈'; - -$lang->story->reasonList[''] = ''; -$lang->story->reasonList['done'] = '已完成'; -$lang->story->reasonList['subdivided'] = '已細分'; -$lang->story->reasonList['duplicate'] = '重複'; -$lang->story->reasonList['postponed'] = '延期'; -$lang->story->reasonList['willnotdo'] = '不做'; -$lang->story->reasonList['cancel'] = '已取消'; -$lang->story->reasonList['bydesign'] = '設計如此'; -//$lang->story->reasonList['isbug'] = '是個Bug'; - -$lang->story->reviewResultList[''] = ''; -$lang->story->reviewResultList['pass'] = '確認通過'; -$lang->story->reviewResultList['revert'] = '撤銷變更'; -$lang->story->reviewResultList['clarify'] = '有待明確'; -$lang->story->reviewResultList['reject'] = '拒絶'; - -$lang->story->reviewList[0] = '否'; -$lang->story->reviewList[1] = '是'; - -$lang->story->sourceList[''] = ''; -$lang->story->sourceList['custom'] = '客戶'; -$lang->story->sourceList['user'] = '用戶'; -$lang->story->sourceList['po'] = '產品經理'; -$lang->story->sourceList['market'] = '市場'; -$lang->story->sourceList['service'] = '客服'; -$lang->story->sourceList['competitor'] = '競爭對手'; -$lang->story->sourceList['partner'] = '合作夥伴'; -$lang->story->sourceList['dev'] = '開發人員'; -$lang->story->sourceList['tester'] = '測試人員'; -$lang->story->sourceList['bug'] = 'Bug'; -$lang->story->sourceList['other'] = '其他'; - -$lang->story->priList[] = ''; -$lang->story->priList[3] = '3'; -$lang->story->priList[1] = '1'; -$lang->story->priList[2] = '2'; -$lang->story->priList[4] = '4'; - -$lang->story->legendBasicInfo = '基本信息'; -$lang->story->legendLifeTime = '需求的一生'; -$lang->story->legendRelated = '相關信息'; -$lang->story->legendMailto = '抄送給'; -$lang->story->legendAttatch = '附件'; -$lang->story->legendProjectAndTask = '項目任務'; -$lang->story->legendBugs = '相關Bug'; -$lang->story->legendFromBug = '來源Bug'; -$lang->story->legendCases = '相關用例'; -$lang->story->legendLinkStories = '相關需求'; -$lang->story->legendChildStories = '細分需求'; -$lang->story->legendSpec = '需求描述'; -$lang->story->legendVerify = '驗收標準'; -$lang->story->legendHistory = '歷史記錄'; -$lang->story->legendVersion = '歷史版本'; -$lang->story->legendMisc = '其他相關'; - -$lang->story->lblChange = '變更需求'; -$lang->story->lblReview = '評審需求'; -$lang->story->lblActivate = '激活需求'; -$lang->story->lblClose = '關閉需求'; - -$lang->story->affectedProjects = '影響的項目'; -$lang->story->affectedBugs = '影響的Bug'; -$lang->story->affectedCases = '影響的用例'; - -$lang->story->specTemplate = "建議參考的模板:作為一名<某種類型的用戶>,我希望<達成某些目的>,這樣可以<開發的價值>。"; -$lang->story->notes = '(註:如果“需求標題”為空,則表示不使用此行)'; -$lang->story->needNotReview = '不需要評審'; -$lang->story->confirmDelete = "您確認刪除該需求嗎?"; -$lang->story->errorFormat = '需求數據有誤'; -$lang->story->errorEmptyTitle = '標題不能為空'; -$lang->story->mustChooseResult = '必須選擇評審結果'; -$lang->story->mustChoosePreVersion = '必須選擇回溯的版本'; -$lang->story->ajaxGetProjectStories = '介面:獲取項目需求列表'; -$lang->story->ajaxGetProductStories = '介面:獲取產品需求列表'; - -$lang->story->action->reviewed = array('main' => '$date, 由 $actor 記錄評審結果,結果為 $extra。', 'extra' => $lang->story->reviewResultList); -$lang->story->action->closed = array('main' => '$date, 由 $actor 關閉,原因為 $extra。', 'extra' => $lang->story->reasonList); -$lang->story->action->linked2plan = array('main' => '$date, 由 $actor 關聯到計劃 $extra。'); -$lang->story->action->unlinkedfromplan = array('main' => '$date, 由 $actor 從計劃 $extra 移除。'); -$lang->story->action->linked2project = array('main' => '$date, 由 $actor 關聯到項目 $extra。'); -$lang->story->action->unlinkedfromproject = array('main' => '$date, 由 $actor 從項目 $extra 移除。'); - -/* 統計報表。*/ -$lang->story->report->common = '統計報表'; -$lang->story->report->select = '請選擇報表類型'; -$lang->story->report->create = '生成報表'; -$lang->story->report->selectAll = '全選'; -$lang->story->report->selectReverse = '反選'; - -$lang->story->report->charts['storysPerProduct'] = '產品需求數量'; -$lang->story->report->charts['storysPerModule'] = '模組需求數量'; -$lang->story->report->charts['storysPerSource'] = '需求來源統計'; -$lang->story->report->charts['storysPerPlan'] = '計划進行統計'; -$lang->story->report->charts['storysPerStatus'] = '狀態進行統計'; -$lang->story->report->charts['storysPerStage'] = '所處階段進行統計'; -$lang->story->report->charts['storysPerPri'] = '優先順序進行統計'; -$lang->story->report->charts['storysPerEstimate'] = '預計工時進行統計'; -$lang->story->report->charts['storysPerOpenedBy'] = '由誰創建來進行統計'; -$lang->story->report->charts['storysPerAssignedTo'] = '當前指派來進行統計'; -$lang->story->report->charts['storysPerClosedReason'] = '關閉原因來進行統計'; -$lang->story->report->charts['storysPerChange'] = '變更次數來進行統計'; - -$lang->story->report->options->swf = 'pie2d'; -$lang->story->report->options->width = 'auto'; -$lang->story->report->options->height = 300; -$lang->story->report->options->graph->baseFontSize = 12; -$lang->story->report->options->graph->showNames = 1; -$lang->story->report->options->graph->formatNumber = 1; -$lang->story->report->options->graph->decimalPrecision = 0; -$lang->story->report->options->graph->animation = 0; -$lang->story->report->options->graph->rotateNames = 0; -$lang->story->report->options->graph->yAxisName = 'COUNT'; -$lang->story->report->options->graph->pieRadius = 100; // 餅圖直徑。 -$lang->story->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 - -$lang->story->report->storysPerProduct->graph->xAxisName = '產品'; -$lang->story->report->storysPerModule->graph->xAxisName = '模組'; -$lang->story->report->storysPerSource->graph->xAxisName = '來源'; -$lang->story->report->storysPerPlan->graph->xAxisName = '產品計劃'; -$lang->story->report->storysPerStatus->graph->xAxisName = '狀態'; -$lang->story->report->storysPerStage->graph->xAxisName = '所處階段'; -$lang->story->report->storysPerPri->graph->xAxisName = '優先順序'; -$lang->story->report->storysPerOpenedBy->graph->xAxisName = '由誰創建'; -$lang->story->report->storysPerAssignedTo->graph->xAxisName = '當前指派'; -$lang->story->report->storysPerClosedReason->graph->xAxisName = '關閉原因'; -$lang->story->report->storysPerEstimate->graph->xAxisName = '預計時間'; -$lang->story->report->storysPerChange->graph->xAxisName = '變更次數'; + + * @package story + * @version $Id: zh-tw.php 2471 2011-12-24 01:40:31Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->story->browse = "需求列表"; +$lang->story->create = "新增需求"; +$lang->story->createCase = "建用例"; +$lang->story->batchCreate = "批量添加"; +$lang->story->change = "變更"; +$lang->story->changed = '需求變更'; +$lang->story->review = '評審'; +$lang->story->edit = "編輯需求"; +$lang->story->close = '關閉'; +$lang->story->activate = '激活'; +$lang->story->delete = "刪除需求"; +$lang->story->view = "需求詳情"; +$lang->story->tasks = "相關任務"; +$lang->story->taskCount = '任務數'; +$lang->story->bugs = "Bug"; +$lang->story->linkStory = '關聯需求'; +$lang->story->export = "導出數據"; +$lang->story->reportChart = "統計報表"; + +$lang->story->common = '需求'; +$lang->story->id = '編號'; +$lang->story->product = '所屬產品'; +$lang->story->module = '所屬模組'; +$lang->story->source = '來源'; +$lang->story->release = '發佈計劃'; +$lang->story->bug = '相關bug'; +$lang->story->title = '需求名稱'; +$lang->story->spec = '需求描述'; +$lang->story->verify = '驗收標準'; +$lang->story->type = '需求類型 '; +$lang->story->pri = '優先順序'; +$lang->story->estimate = '預計工時'; +$lang->story->estimateAB = '預計'; +$lang->story->status = '當前狀態'; +$lang->story->stage = '所處階段'; +$lang->story->stageAB = '階段'; +$lang->story->mailto = '抄送給'; +$lang->story->openedBy = '由誰創建'; +$lang->story->openedDate = '創建日期'; +$lang->story->assignedTo = '指派給'; +$lang->story->assignedDate = '指派日期'; +$lang->story->lastEditedBy = '最後修改'; +$lang->story->lastEditedDate = '最後修改日期'; +$lang->story->lastEdited = '最後修改'; +$lang->story->closedBy = '由誰關閉'; +$lang->story->closedDate = '關閉日期'; +$lang->story->closedReason = '關閉原因'; +$lang->story->rejectedReason = '拒絶原因'; +$lang->story->reviewedBy = '由誰評審'; +$lang->story->reviewedDate = '評審時間'; +$lang->story->version = '版本號'; +$lang->story->project = '所屬項目'; +$lang->story->plan = '所屬計劃'; +$lang->story->planAB = '計劃'; +$lang->story->comment = '備註'; +$lang->story->linkStories = '相關需求'; +$lang->story->childStories = '細分需求'; +$lang->story->duplicateStory = '重複需求'; +$lang->story->reviewResult = '評審結果'; +$lang->story->preVersion = '之前版本'; +$lang->story->keywords = '關鍵詞'; + +$lang->story->same = '同上'; + +$lang->story->useList[0] = '不使用'; +$lang->story->useList[1] = '使用'; + +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = '草稿'; +$lang->story->statusList['active'] = '激活'; +$lang->story->statusList['closed'] = '已關閉'; +$lang->story->statusList['changed'] = '已變更'; + +$lang->story->stageList[''] = ''; +$lang->story->stageList['wait'] = '未開始'; +$lang->story->stageList['planned'] = '已計劃'; +$lang->story->stageList['projected'] = '已立項'; +$lang->story->stageList['developing'] = '研發中'; +$lang->story->stageList['developed'] = '研發完畢'; +$lang->story->stageList['testing'] = '測試中'; +$lang->story->stageList['tested'] = '測試完畢'; +$lang->story->stageList['verified'] = '已驗收'; +$lang->story->stageList['released'] = '已發佈'; + +$lang->story->reasonList[''] = ''; +$lang->story->reasonList['done'] = '已完成'; +$lang->story->reasonList['subdivided'] = '已細分'; +$lang->story->reasonList['duplicate'] = '重複'; +$lang->story->reasonList['postponed'] = '延期'; +$lang->story->reasonList['willnotdo'] = '不做'; +$lang->story->reasonList['cancel'] = '已取消'; +$lang->story->reasonList['bydesign'] = '設計如此'; +//$lang->story->reasonList['isbug'] = '是個Bug'; + +$lang->story->reviewResultList[''] = ''; +$lang->story->reviewResultList['pass'] = '確認通過'; +$lang->story->reviewResultList['revert'] = '撤銷變更'; +$lang->story->reviewResultList['clarify'] = '有待明確'; +$lang->story->reviewResultList['reject'] = '拒絶'; + +$lang->story->reviewList[0] = '否'; +$lang->story->reviewList[1] = '是'; + +$lang->story->sourceList[''] = ''; +$lang->story->sourceList['custom'] = '客戶'; +$lang->story->sourceList['user'] = '用戶'; +$lang->story->sourceList['po'] = '產品經理'; +$lang->story->sourceList['market'] = '市場'; +$lang->story->sourceList['service'] = '客服'; +$lang->story->sourceList['competitor'] = '競爭對手'; +$lang->story->sourceList['partner'] = '合作夥伴'; +$lang->story->sourceList['dev'] = '開發人員'; +$lang->story->sourceList['tester'] = '測試人員'; +$lang->story->sourceList['bug'] = 'Bug'; +$lang->story->sourceList['other'] = '其他'; + +$lang->story->priList[] = ''; +$lang->story->priList[3] = '3'; +$lang->story->priList[1] = '1'; +$lang->story->priList[2] = '2'; +$lang->story->priList[4] = '4'; + +$lang->story->legendBasicInfo = '基本信息'; +$lang->story->legendLifeTime = '需求的一生'; +$lang->story->legendRelated = '相關信息'; +$lang->story->legendMailto = '抄送給'; +$lang->story->legendAttatch = '附件'; +$lang->story->legendProjectAndTask = '項目任務'; +$lang->story->legendBugs = '相關Bug'; +$lang->story->legendFromBug = '來源Bug'; +$lang->story->legendCases = '相關用例'; +$lang->story->legendLinkStories = '相關需求'; +$lang->story->legendChildStories = '細分需求'; +$lang->story->legendSpec = '需求描述'; +$lang->story->legendVerify = '驗收標準'; +$lang->story->legendHistory = '歷史記錄'; +$lang->story->legendVersion = '歷史版本'; +$lang->story->legendMisc = '其他相關'; + +$lang->story->lblChange = '變更需求'; +$lang->story->lblReview = '評審需求'; +$lang->story->lblActivate = '激活需求'; +$lang->story->lblClose = '關閉需求'; + +$lang->story->affectedProjects = '影響的項目'; +$lang->story->affectedBugs = '影響的Bug'; +$lang->story->affectedCases = '影響的用例'; + +$lang->story->specTemplate = "建議參考的模板:作為一名<某種類型的用戶>,我希望<達成某些目的>,這樣可以<開發的價值>。"; +$lang->story->notes = '(註:如果“需求標題”為空,則表示不使用此行)'; +$lang->story->needNotReview = '不需要評審'; +$lang->story->confirmDelete = "您確認刪除該需求嗎?"; +$lang->story->errorFormat = '需求數據有誤'; +$lang->story->errorEmptyTitle = '標題不能為空'; +$lang->story->mustChooseResult = '必須選擇評審結果'; +$lang->story->mustChoosePreVersion = '必須選擇回溯的版本'; +$lang->story->ajaxGetProjectStories = '介面:獲取項目需求列表'; +$lang->story->ajaxGetProductStories = '介面:獲取產品需求列表'; + +$lang->story->action->reviewed = array('main' => '$date, 由 $actor 記錄評審結果,結果為 $extra。', 'extra' => $lang->story->reviewResultList); +$lang->story->action->closed = array('main' => '$date, 由 $actor 關閉,原因為 $extra。', 'extra' => $lang->story->reasonList); +$lang->story->action->linked2plan = array('main' => '$date, 由 $actor 關聯到計劃 $extra。'); +$lang->story->action->unlinkedfromplan = array('main' => '$date, 由 $actor 從計劃 $extra 移除。'); +$lang->story->action->linked2project = array('main' => '$date, 由 $actor 關聯到項目 $extra。'); +$lang->story->action->unlinkedfromproject = array('main' => '$date, 由 $actor 從項目 $extra 移除。'); + +/* 統計報表。*/ +$lang->story->report->common = '統計報表'; +$lang->story->report->select = '請選擇報表類型'; +$lang->story->report->create = '生成報表'; +$lang->story->report->selectAll = '全選'; +$lang->story->report->selectReverse = '反選'; + +$lang->story->report->charts['storysPerProduct'] = '產品需求數量'; +$lang->story->report->charts['storysPerModule'] = '模組需求數量'; +$lang->story->report->charts['storysPerSource'] = '需求來源統計'; +$lang->story->report->charts['storysPerPlan'] = '計划進行統計'; +$lang->story->report->charts['storysPerStatus'] = '狀態進行統計'; +$lang->story->report->charts['storysPerStage'] = '所處階段進行統計'; +$lang->story->report->charts['storysPerPri'] = '優先順序進行統計'; +$lang->story->report->charts['storysPerEstimate'] = '預計工時進行統計'; +$lang->story->report->charts['storysPerOpenedBy'] = '由誰創建來進行統計'; +$lang->story->report->charts['storysPerAssignedTo'] = '當前指派來進行統計'; +$lang->story->report->charts['storysPerClosedReason'] = '關閉原因來進行統計'; +$lang->story->report->charts['storysPerChange'] = '變更次數來進行統計'; + +$lang->story->report->options->swf = 'pie2d'; +$lang->story->report->options->width = 'auto'; +$lang->story->report->options->height = 300; +$lang->story->report->options->graph->baseFontSize = 12; +$lang->story->report->options->graph->showNames = 1; +$lang->story->report->options->graph->formatNumber = 1; +$lang->story->report->options->graph->decimalPrecision = 0; +$lang->story->report->options->graph->animation = 0; +$lang->story->report->options->graph->rotateNames = 0; +$lang->story->report->options->graph->yAxisName = 'COUNT'; +$lang->story->report->options->graph->pieRadius = 100; // 餅圖直徑。 +$lang->story->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 + +$lang->story->report->storysPerProduct->graph->xAxisName = '產品'; +$lang->story->report->storysPerModule->graph->xAxisName = '模組'; +$lang->story->report->storysPerSource->graph->xAxisName = '來源'; +$lang->story->report->storysPerPlan->graph->xAxisName = '產品計劃'; +$lang->story->report->storysPerStatus->graph->xAxisName = '狀態'; +$lang->story->report->storysPerStage->graph->xAxisName = '所處階段'; +$lang->story->report->storysPerPri->graph->xAxisName = '優先順序'; +$lang->story->report->storysPerOpenedBy->graph->xAxisName = '由誰創建'; +$lang->story->report->storysPerAssignedTo->graph->xAxisName = '當前指派'; +$lang->story->report->storysPerClosedReason->graph->xAxisName = '關閉原因'; +$lang->story->report->storysPerEstimate->graph->xAxisName = '預計時間'; +$lang->story->report->storysPerChange->graph->xAxisName = '變更次數'; diff --git a/module/story/model.php b/module/story/model.php index ee93d505c6..dfff6be45e 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -1,1212 +1,1212 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findById((int)$storyID)->from(TABLE_STORY)->fetch(); - if(!$story) return false; - if(substr($story->closedDate, 0, 4) == '0000') $story->closedDate = ''; - if($version == 0) $version = $story->version; - $spec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWhere('version')->eq($version)->fetch(); - $story->title = isset($spec->title) ? $spec->title : ''; - $story->spec = isset($spec->spec) ? $this->loadModel('file')->setImgSize($spec->spec) : ''; - $story->verify = isset($spec->verify) ? $spec->verify : ''; - $story->projects = $this->dao->select('t1.project, t2.name, t2.status') - ->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.story')->eq($storyID) - ->orderBy('t1.project DESC') - ->fetchAll('project'); - $story->tasks = $this->dao->select('id, name, assignedTo, project, status, consumed, `left`')->from(TABLE_TASK)->where('story')->eq($storyID)->orderBy('id DESC')->fetchGroup('project'); - //$story->bugCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_BUG)->where('story')->eq($storyID)->fetch('count'); - //$story->caseCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_CASE)->where('story')->eq($storyID)->fetch('count'); - if($story->toBug) $story->toBugTitle = $this->dao->findById($story->toBug)->from(TABLE_BUG)->fetch('title'); - if($story->plan) $story->planTitle = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title'); - $extraStories = array(); - if($story->duplicateStory) $extraStories = array($story->duplicateStory); - if($story->linkStories) $extraStories = explode(',', $story->linkStories); - if($story->childStories) $extraStories = array_merge($extraStories, explode(',', $story->childStories)); - $extraStories = array_unique($extraStories); - if(!empty($extraStories)) $story->extraStories = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($extraStories)->fetchPairs(); - return $story; - } - - /** - * Get affected things. - * - * @param object $story - * @access public - * @return object - */ - public function getAffectedScope($story) - { - /* Remove closed projects. */ - if($story->projects) - { - foreach($story->projects as $projectID => $project) - { - if($project->status != 'doing') unset($story->projects[$projectID]); - } - } - - /* Get team members. */ - if($story->projects) - { - $story->teams = $this->dao->select('account, project') - ->from(TABLE_TEAM) - ->where('project')->in(array_keys($story->projects)) - ->fetchGroup('project'); - } - - /* Get affected bugs. */ - $story->bugs = $this->dao->findByStory($story->id)->from(TABLE_BUG) - ->andWhere('status')->ne('closed') - ->andWhere('deleted')->eq(0) - ->orderBy('id desc')->fetchAll(); - - /* Get affected cases. */ - $story->cases = $this->dao->findByStory($story->id)->from(TABLE_CASE)->andWhere('deleted')->eq(0)->fetchAll(); - - return $story; - } - - /** - * Create a story. - * - * @access public - * @return int|bool the id of the created story or false when error. - */ - public function create($projectID = 0, $bugID = 0) - { - $now = helper::now(); - $story = fixer::input('post') - ->cleanInt('product,module,pri,plan') - ->cleanFloat('estimate') - ->stripTags('title') - ->callFunc('title', 'trim') - ->setDefault('plan', 0) - ->add('openedBy', $this->app->user->account) - ->add('openedDate', $now) - ->add('assignedDate', 0) - ->add('version', 1) - ->add('status', 'draft') - ->setIF($this->post->assignedTo != '', 'assignedDate', $now) - ->setIF($this->post->needNotReview, 'status', 'active') - ->setIF($this->post->plan > 0, 'stage', 'planned') - ->setIF($projectID > 0, 'stage', 'projected') - ->setIF($bugID > 0, 'fromBug', $bugID) - ->remove('files,labels,spec,verify,needNotReview') - ->get(); - - $this->dao->insert(TABLE_STORY)->data($story)->autoCheck()->batchCheck($this->config->story->create->requiredFields, 'notempty')->exec(); - if(!dao::isError()) - { - $storyID = $this->dao->lastInsertID(); - $this->loadModel('file')->saveUpload('story', $storyID, $extra = 1); - - $data->story = $storyID; - $data->version = 1; - $data->title = $story->title; - $data->spec = $this->post->spec; - $data->verify = $this->post->verify; - $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); - - if($projectID != 0) - { - $this->dao->insert(TABLE_PROJECTSTORY) - ->set('company')->eq(1) - ->set('project')->eq($projectID) - ->set('product')->eq($this->post->product) - ->set('story')->eq($storyID) - ->set('version')->eq(1) - ->exec(); - } - - if($bugID > 0) - { - $bug->toStory = $storyID; - $bug->status = 'closed'; - $bug->resolution = 'tostory'; - $bug->resolvedBy = $this->app->user->account; - $bug->resolvedDate = $now; - $bug->closedBy = $this->app->user->account; - $bug->closedDate = $now; - $bug->assignedTo = 'closed'; - $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); - - $this->loadModel('action')->create('bug', $bugID, 'ToStory', '', $storyID); - $this->action->create('bug', $bugID, 'Closed'); - - /* add files to story from bug. */ - $files = $this->dao->select('*')->from(TABLE_FILE) - ->where('objectType')->eq('bug') - ->andWhere('objectID')->eq($bugID) - ->fetchAll(); - if(!empty($files)) - { - foreach($files as $file) - { - $file->objectType = 'story'; - $file->objectID = $storyID; - unset($file->id); - $this->dao->insert(TABLE_FILE)->data($file)->exec(); - } - } - } - return $storyID; - } - return false; - } - - /** - * Create a batch stories. - * - * @access public - * @return int|bool the id of the created story or false when error. - */ - public function batchCreate($productID = 0) - { - $now = helper::now(); - $stories = fixer::input('post')->get(); - for($i = 0; $i < $this->config->story->batchCreate; $i++) - { - if($stories->title[$i] != '') - { - $data[$i]->module = $stories->module[$i] != 'same' ? $stories->module[$i] : ($i == 0 ? 0 : $data[$i-1]->module); - $data[$i]->plan = $stories->plan[$i] == 'same' ? ($i != 0 ? $data[$i-1]->plan : 0) : ($stories->plan[$i] != '' ? $stories->plan[$i] : 0); - $data[$i]->title = $stories->title[$i]; - $data[$i]->pri = $stories->pri[$i] != '' ? $stories->pri[$i] : 0; - $data[$i]->estimate = $stories->estimate[$i] != '' ? $stories->estimate[$i] : 0; - $data[$i]->status = $stories->needReview[$i] == 0 ? 'active' : 'draft'; - $data[$i]->product = $productID; - $data[$i]->openedBy = $this->app->user->account; - $data[$i]->openedDate = $now; - $data[$i]->version = 1; - - $this->dao->insert(TABLE_STORY) - ->data($data[$i]) - ->autoCheck() - ->batchCheck($this->config->story->create->requiredFields, 'notempty') - ->exec(); - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - - $storyID = $this->dao->lastInsertID(); - - $specData[$i]->story = $storyID; - $specData[$i]->version = 1; - $specData[$i]->title = $stories->title[$i]; - if($stories->spec[$i] != '') $specData[$i]->spec = $stories->spec[$i]; - $this->dao->insert(TABLE_STORYSPEC)->data($specData[$i])->exec(); - - $this->loadModel('action'); - $actionID = $this->action->create('story', $storyID, 'Opened', ''); - $mails[$i]->storyID = $storyID; - $mails[$i]->actionID = $actionID; - } - else - { - unset($stories->use[$i]); - unset($stories->module[$i]); - unset($stories->plan[$i]); - unset($stories->title[$i]); - unset($stories->spec[$i]); - unset($stories->pri[$i]); - unset($stories->estimate[$i]); - unset($stories->needReview[$i]); - } - } - return $mails; - } - - /** - * Change a story. - * - * @param int $storyID - * @access public - * @return array the change of the story. - */ - public function change($storyID) - { - $now = helper::now(); - $oldStory = $this->getById($storyID); - $specChanged = false; - if($this->post->spec != $oldStory->spec or $this->post->verify != $oldStory->verify or $this->post->title != $oldStory->title or $this->loadModel('file')->getCount()) $specChanged = true; - - $story = fixer::input('post') - ->stripTags('title') - ->callFunc('title', 'trim') - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->setIF($this->post->assignedTo != $oldStory->assignedTo, 'assignedDate', $now) - ->setIF($specChanged, 'version', $oldStory->version + 1) - ->setIF($specChanged and $oldStory->status == 'active' and $this->post->needNotReview == false, 'status', 'changed') - ->setIF($specChanged and $oldStory->status == 'draft' and $this->post->needNotReview, 'status', 'active') - ->setIF($specChanged, 'reviewedBy', '') - ->setIF($specChanged, 'closedBy', '') - ->setIF($specChanged, 'closedReason', '') - ->setIF($specChanged and $oldStory->reviewedBy, 'reviewedDate', '0000-00-00') - ->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00') - ->remove('files,labels,spec,verify,comment,needNotReview') - ->get(); - $this->dao->update(TABLE_STORY) - ->data($story) - ->autoCheck() - ->batchCheck($this->config->story->change->requiredFields, 'notempty') - ->where('id')->eq((int)$storyID)->exec(); - if(!dao::isError()) - { - if($specChanged) - { - $data->story = $storyID; - $data->version = $oldStory->version + 1; - $data->title = $story->title; - $data->spec = $this->post->spec; - $data->verify = $this->post->verify; - $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); - $story->spec = $this->post->spec; - $story->verify = $this->post->verify; - } - else - { - unset($oldStory->spec); - } - return common::createChanges($oldStory, $story); - } - } - - /** - * Update a story. - * - * @param int $storyID - * @access public - * @return array the changes of the story. - */ - public function update($storyID) - { - $now = helper::now(); - $oldStory = $this->getById($storyID); - - $story = fixer::input('post') - ->cleanInt('product,module,pri,plan') - ->stripTags('title') - ->add('assignedDate', $oldStory->assignedDate) - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->setDefault('plan', 0) - ->setDefault('status', $oldStory->status) - ->setIF($this->post->assignedTo != $oldStory->assignedTo, 'assignedDate', $now) - ->setIF($this->post->closedBy != false and $oldStory->closedDate == '', 'closedDate', $now) - ->setIF($this->post->closedReason != false and $oldStory->closedDate == '', 'closedDate', $now) - ->setIF($this->post->closedBy != false or $this->post->closedReason != false, 'status', 'closed') - ->setIF($this->post->closedReason != false and $this->post->closedBy == false, 'closedBy', $this->app->user->account) - ->remove('files,labels,comment') - ->get(); - - $this->dao->update(TABLE_STORY) - ->data($story) - ->autoCheck() - ->batchCheck($this->config->story->edit->requiredFields, 'notempty') - ->checkIF(isset($story->closedBy), 'closedReason', 'notempty') - ->checkIF(isset($story->closedReason) and $story->closedReason == 'done', 'stage', 'notempty') - ->checkIF(isset($story->closedReason) and $story->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF(isset($story->closedReason) and $story->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq((int)$storyID)->exec(); - - $this->setStage($storyID); - if(!dao::isError()) return common::createChanges($oldStory, $story); - } - - /** - * Review a story. - * - * @param int $storyID - * @access public - * @return bool - */ - public function review($storyID) - { - if($this->post->result == false) die(js::alert($this->lang->story->mustChooseResult)); - if($this->post->result == 'revert' and $this->post->preVersion == false) die(js::alert($this->lang->story->mustChoosePreVersion)); - - $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); - $now = helper::now(); - $date = helper::today(); - $story = fixer::input('post') - ->remove('result,preVersion,comment') - ->setDefault('reviewedDate', $date) - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->setIF($this->post->result == 'pass' and $oldStory->status == 'draft', 'status', 'active') - ->setIF($this->post->result == 'pass' and $oldStory->status == 'changed', 'status', 'active') - ->setIF($this->post->result == 'reject', 'closedBy', $this->app->user->account) - ->setIF($this->post->result == 'reject', 'closedDate', $now) - ->setIF($this->post->result == 'reject', 'assignedTo', 'closed') - ->setIF($this->post->result == 'reject', 'status', 'closed') - ->setIF($this->post->result == 'revert', 'version', $this->post->preVersion) - ->setIF($this->post->result == 'revert', 'status', 'active') - ->setIF($this->post->closedReason == 'done', 'stage', 'released') - ->removeIF($this->post->result != 'reject', 'closedReason, duplicateStory, childStories') - ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'duplicate', 'duplicateStory') - ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'subdivided', 'childStories') - ->get(); - $this->dao->update(TABLE_STORY)->data($story) - ->autoCheck() - ->batchCheck($this->config->story->review->requiredFields, 'notempty') - ->checkIF($this->post->result == 'reject', 'closedReason', 'notempty') - ->checkIF($this->post->result == 'reject' and $this->post->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF($this->post->result == 'reject' and $this->post->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq($storyID)->exec(); - if($this->post->result == 'revert') - { - $preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($this->post->preVersion)->fetch('title'); - $this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->where('id')->eq($storyID)->exec(); - $this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($oldStory->version)->exec(); - $this->dao->delete()->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->eq($storyID)->andWhere('extra')->eq($oldStory->version)->exec(); - } - $this->setStage($storyID); - return true; - } - - /** - * Close a story. - * - * @param int $storyID - * @access public - * @return bool - */ - public function close($storyID) - { - $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); - $now = helper::now(); - $story = fixer::input('post') - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->add('closedDate', $now) - ->add('closedBy', $this->app->user->account) - ->add('assignedTo', 'closed') - ->add('assignedDate', $now) - ->add('status', 'closed') - ->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory') - ->removeIF($this->post->closedReason != 'subdivided', 'childStories') - ->setIF($this->post->closedReason == 'done', 'stage', 'released') - ->setIF($this->post->closedReason != 'done', 'plan', 0) - ->remove('comment') - ->get(); - $this->dao->update(TABLE_STORY)->data($story) - ->autoCheck() - ->batchCheck($this->config->story->close->requiredFields, 'notempty') - ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq($storyID)->exec(); - return true; - } - - /** - * Activate a story. - * - * @param int $storyID - * @access public - * @return bool - */ - public function activate($storyID) - { - $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); - $now = helper::now(); - $story = fixer::input('post') - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->add('assignedDate', $now) - ->add('status', 'active') - ->add('closedBy', '') - ->add('closedReason', '') - ->add('closedDate', '0000-00-00') - ->add('reviewedBy', '') - ->add('reviewedDate', '0000-00-00') - ->remove('comment') - ->get(); - $this->dao->update(TABLE_STORY)->data($story)->autoCheck()->where('id')->eq($storyID)->exec(); - return true; - } - - /** - * Set stage of a story. - * - * @param int $storyID - * @param string $customStage - * @access public - * @return bool - */ - public function setStage($storyID, $customStage = '') - { - /* Custom stage defined, use it. */ - if($customStage) - { - $this->dao->update(TABLE_STORY)->set('stage')->eq($customStage)->where('id')->eq((int)$storyID)->exec(); - return true; - } - - /* Get projects which status is doing. */ - $projects = $this->dao->select('project') - ->from(TABLE_PROJECTSTORY)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.story')->eq((int)$storyID) - ->andWhere('t2.status')->ne('done') - ->andWhere('t2.deleted')->eq(0) - ->fetchPairs(); - - /* If no projects, in plan, stage is planned. No plan, wait. */ - if(!$projects) - { - $this->dao->update(TABLE_STORY)->set('stage')->eq('planned')->where('id')->eq((int)$storyID)->andWhere('plan')->gt(0)->exec(); - $this->dao->update(TABLE_STORY)->set('stage')->eq('wait')->where('id')->eq((int)$storyID)->andWhere('plan')->eq(0)->andWhere('status')->eq('active')->exec(); - return true; - } - - /* Search related tasks. */ - $tasks = $this->dao->select('type,status')->from(TABLE_TASK) - ->where('project')->in($projects) - ->andWhere('story')->eq($storyID) - ->andWhere('status')->ne('cancel') - ->andWhere('status')->ne('closed') - ->andWhere('deleted')->eq(0) - ->fetchGroup('type'); - - /* No tasks, then the stage is projected. */ - if(!$tasks) - { - $this->dao->update(TABLE_STORY)->set('stage')->eq('projected')->where('id')->eq((int)$storyID)->exec(); - return true; - } - - /* If have test task, the stage is tested, testing or developing. */ - if(isset($tasks['test'])) - { - $stage = 'tested'; - foreach($tasks['test'] as $task) - { - if($task->status != 'done') - { - $stage = 'testing'; - break; - } - } - if($stage != 'testing') - { - unset($tasks['test']); - foreach($tasks as $type => $typeTasks) - { - foreach($typeTasks as $task) - { - if($task->status != 'done') - { - $stage = 'developing'; - break; - } - } - } - } - } - /* No test taske, stage is done or developing. */ - else - { - $stage = 'developed'; - foreach($tasks as $type => $typeTasks) - { - foreach($typeTasks as $task) - { - if($task->status != 'done') - { - $stage = 'developing'; - break; - } - } - } - } - $this->dao->update(TABLE_STORY)->set('stage')->eq($stage)->where('id')->eq((int)$storyID)->exec(); - return; - } - - /** - * Get stories list of a product. - * - * @param int $productID - * @param array|string $moduleIds - * @param string $status - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getProductStories($productID = 0, $moduleIds = 0, $status = 'all', $orderBy = 'id_desc', $pager = null) - { - $stories = $this->dao->select('t1.*, t2.title as planTitle') - ->from(TABLE_STORY)->alias('t1') - ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') - ->where('t1.product')->in($productID) - ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() - ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() - ->andWhere('t1.deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - - $this->saveReportQuery($this->dao->get()); - - return $stories; - } - - /** - * Get stories pairs of a product. - * - * @param int $productID - * @param array|string $moduleIds - * @param string $status - * @param string $order - * @access public - * @return array - */ - public function getProductStoryPairs($productID = 0, $moduleIds = 0, $status = 'all', $order = 'id_desc') - { - $stories = $this->dao->select('t1.id, t1.title, t1.module, t1.pri, t1.estimate, t2.name AS product') - ->from(TABLE_STORY)->alias('t1')->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') - ->where('1=1') - ->beginIF($productID)->andWhere('t1.product')->in($productID)->fi() - ->beginIF($moduleIds)->andWhere('t1.module')->in($moduleIds)->fi() - ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() - ->andWhere('t1.deleted')->eq(0) - ->orderBy($order) - ->fetchAll(); - if(!$stories) return array(); - return $this->formatStories($stories); - } - - /** - * Get stories by assignedTo. - * - * @param int $productID - * @param string $account - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByAssignedTo($productID, $account, $orderBy, $pager) - { - return $this->getByField($productID, 'assignedTo', $account, $orderBy, $pager); - } - - /** - * Get stories by openedBy. - * - * @param int $productID - * @param string $account - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByOpenedBy($productID, $account, $orderBy, $pager) - { - return $this->getByField($productID, 'openedBy', $account, $orderBy, $pager); - } - - /** - * Get stories by reviewedBy. - * - * @param int $productID - * @param string $account - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getByReviewedBy($productID, $account, $orderBy, $pager) - { - return $this->getByField($productID, 'reviewedBy', $account, $orderBy, $pager, 'include'); - } - - /** - * Get stories by closedBy. - * - * @param int $productID - * @param string $account - * @param string $orderBy - * @param object $pager - * @return array - */ - public function getByClosedBy($productID, $account, $orderBy, $pager) - { - return $this->getByField($productID, 'closedBy', $account, $orderBy, $pager); - } - - /** - * Get stories by status. - * - * @param int $productID - * @param string $orderBy - * @param object $pager - * @param string $status - * @access public - * @return array - */ - public function getByStatus($productID, $status, $orderBy, $pager) - { - return $this->getByField($productID, 'status', $status, $orderBy, $pager); - } - - /** - * Get stories by a field. - * - * @param int $productID - * @param string $fieldName - * @param mixed $fieldValue - * @param string $orderBy - * @param object $pager - * @param string $operator equal|include - * @access public - * @return array - */ - public function getByField($productID, $fieldName, $fieldValue, $orderBy, $pager, $operator = 'equal') - { - $stories = $this->dao->select('t1.*, t2.title as planTitle') - ->from(TABLE_STORY)->alias('t1') - ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') - ->where('t1.product')->in($productID) - ->andWhere('t1.deleted')->eq(0) - ->beginIF($operator == 'equal')->andWhere($fieldName)->eq($fieldValue)->fi() - ->beginIF($operator == 'include')->andWhere($fieldName)->like("%$fieldValue%")->fi() - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - $this->saveReportQuery($this->dao->get()); - - return $stories; - } - - /** - * Get stories through search. - * - * @access public - * @param int $productID - * @param int $queryID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getBySearch($productID, $queryID, $orderBy, $pager) - { - $products = $this->loadModel('product')->getPairs(); - $query = $queryID ? $this->loadModel('search')->getQuery($queryID) : ''; - - /* Get the sql and form status from the query. */ - if($query) - { - $this->session->set('storyQuery', $query->sql); - $this->session->set('storyForm', $query->form); - } - if($this->session->storyQuery == false) $this->session->set('storyQuery', ' 1 = 1'); - - $allProduct = "`product` = 'all'"; - $storyQuery = $this->session->storyQuery; - $queryProductID = $productID; - if(strpos($this->session->storyQuery, $allProduct) !== false) - { - $storyQuery = str_replace($allProduct, '1', $this->session->storyQuery); - $queryProductID = 'all'; - } - $storyQuery = $storyQuery . 'AND `product`' . helper::dbIN(array_keys($products)); - - return $this->getBySQL($queryProductID, $storyQuery, $orderBy, $pager); - } - - /** - * Get stories by a sql. - * - * @param int $productID - * @param string $sql - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getBySQL($productID, $sql, $orderBy, $pager = null) - { - $tmpStories = $this->dao->select('*')->from(TABLE_STORY)->where($sql) - ->beginIF($productID != 'all')->andWhere('product')->eq((int)$productID)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - $this->saveReportQuery($this->dao->get()); - - if(!$tmpStories) return array(); - - /* Get plans. */ - $plans = array(); - foreach($tmpStories as $story) $plans[$story->plan] = $story->plan; - $plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)->where('id')->in(array_keys($plans))->fetchPairs(); - - /* Process plans. */ - $stories = array(); - foreach($tmpStories as $story) - { - $story->planTitle = isset($plans[$story->plan]) ? $plans[$story->plan] : ''; - $stories[] = $story; - } - return $stories; - } - - /** - * Save one executed query as report query, thus when create report chart to make use the condition is the same. - * - * @param string $sql - * @access public - * @return void - */ - public function saveReportQuery($sql) - { - $sql = explode('WHERE', $sql); - $sql = explode('ORDER', $sql[1]); - $sql = str_replace('t1.', '', $sql[0]); - $this->session->set('storyReport', $sql); - } - - /** - * Get stories list of a project. - * - * @param int $projectID - * @param string $orderBy - * @access public - * @return array - */ - public function getProjectStories($projectID = 0, $orderBy = 'pri_asc,id_desc') - { - return $this->dao->select('t1.*, t2.*')->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t2.deleted')->eq(0) - ->orderBy($orderBy) - ->fetchAll('id'); - } - - /** - * Get stories pairs of a project. - * - * @param int $projectID - * @param int $productID - * @access public - * @return array - */ - public function getProjectStoryPairs($projectID = 0, $productID = 0) - { - $stories = $this->dao->select('t2.id, t2.title, t2.module, t2.pri, t2.estimate, t3.name AS product') - ->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2') - ->on('t1.story = t2.id') - ->leftJoin(TABLE_PRODUCT)->alias('t3') - ->on('t1.product = t3.id') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t2.deleted')->eq(0) - ->beginIF($productID)->andWhere('t1.product')->eq((int)$productID)->fi() - ->fetchAll(); - if(!$stories) return array(); - return $this->formatStories($stories); - } - - /** - * Get stories list of a plan. - * - * @param int $planID - * @param string $status - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getPlanStories($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('*')->from(TABLE_STORY) - ->where('plan')->eq((int)$planID) - ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll('id'); - } - - /** - * Get stories pairs of a plan. - * - * @param int $planID - * @param string $status - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getPlanStoryPairs($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('*')->from(TABLE_STORY) - ->where('plan')->eq($planID) - ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() - ->andWhere('deleted')->eq(0) - ->fetchAll(); - } - - /** - * Get stories of a user. - * - * @param string $account - * @param string $type the query type - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getUserStories($account, $type = 'assignedto', $orderBy = 'id_desc', $pager = null) - { - $type = strtolower($type); - return $this->dao->select('t1.*, t2.title as planTitle, t3.name as productTitle') - ->from(TABLE_STORY)->alias('t1') - ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') - ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') - ->where('t1.deleted')->eq(0) - ->beginIF($type == 'assignedto')->andWhere('assignedTo')->eq($this->app->user->account)->fi() - ->beginIF($type == 'openedby')->andWhere('openedby')->eq($this->app->user->account)->fi() - ->beginIF($type == 'reviewedby')->andWhere('reviewedby')->like('%' . $this->app->user->account . '%')->fi() - ->beginIF($type == 'closedby')->andWhere('closedby')->eq($this->app->user->account)->fi() - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get doing projects' members of a story. - * - * @param int $storyID - * @access public - * @return array - */ - public function getProjectMembers($storyID) - { - $projects = $this->dao->select('project') - ->from(TABLE_PROJECTSTORY)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.story')->eq((int)$storyID) - ->andWhere('t2.status')->eq('doing') - ->andWhere('t2.deleted')->eq(0) - ->fetchPairs(); - if($projects) return($this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs('account')); - } - - /** - * Get version of a story. - * - * @param int $storyID - * @access public - * @return int - */ - public function getVersion($storyID) - { - return $this->dao->select('version')->from(TABLE_STORY)->where('id')->eq((int)$storyID)->fetch('version'); - } - - /** - * Get versions of some stories. - * - * @param array|string story id list - * @access public - * @return array - */ - public function getVersions($storyID) - { - return $this->dao->select('id, version')->from(TABLE_STORY)->where('id')->in($storyID)->fetchPairs(); - } - - /** - * Format stories - * - * @param array $stories - * @access private - * @return void - */ - private function formatStories($stories) - { - /* Get module names of stories. */ - /*$modules = array(); - foreach($stories as $story) $modules[] = $story->module; - $moduleNames = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($modules)->fetchPairs();*/ - - /* Format these stories. */ - $storyPairs = array('' => ''); - foreach($stories as $story) $storyPairs[$story->id] = $story->id . ':' . $story->title . "({$this->lang->story->pri}:$story->pri, {$this->lang->story->estimate}: $story->estimate)"; - return $storyPairs; - } - - /** - * Extract accounts from some stories. - * - * @param array $stories - * @access public - * @return array - */ - public function extractAccountsFromList($stories) - { - $accounts = array(); - foreach($stories as $story) - { - if(!empty($story->openedBy)) $accounts[] = $story->openedBy; - if(!empty($story->assignedTo)) $accounts[] = $story->assignedTo; - if(!empty($story->closedBy)) $accounts[] = $story->closedBy; - if(!empty($story->lastEditedBy)) $accounts[] = $story->lastEditedBy; - } - return array_unique($accounts); - } - - /** - * Extract accounts from a story. - * - * @param object $story - * @access public - * @return array - */ - public function extractAccountsFromSingle($story) - { - $accounts = array(); - if(!empty($story->openedBy)) $accounts[] = $story->openedBy; - if(!empty($story->assignedTo)) $accounts[] = $story->assignedTo; - if(!empty($story->closedBy)) $accounts[] = $story->closedBy; - if(!empty($story->lastEditedBy)) $accounts[] = $story->lastEditedBy; - return array_unique($accounts); - } - - /** - * Merge the default chart settings and the settings of current chart. - * - * @param string $chartType - * @access public - * @return void - */ - public function mergeChartOption($chartType) - { - $chartOption = $this->lang->story->report->$chartType; - $commonOption = $this->lang->story->report->options; - - $chartOption->graph->caption = $this->lang->story->report->charts[$chartType]; - if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; - if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; - if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; - - foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; - } - - /** - * Get report data of storys per product - * - * @access public - * @return array - */ - public function getDataOfStorysPerProduct() - { - $datas = $this->dao->select('product as name, count(product) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('product')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $products = $this->loadModel('product')->getPairs(); - foreach($datas as $productID => $data) $data->name = isset($products[$productID]) ? $products[$productID] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per module - * - * @access public - * @return array - */ - public function getDataOfStorysPerModule() - { - $datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('module')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs(); - foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/'; - return $datas; - } - - /** - * Get report data of storys per source - * - * @access public - * @return array - */ - public function getDataOfStorysPerSource() - { - $datas = $this->dao->select('source as name, count(source) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('source')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $this->lang->story->sourceList[''] = $this->lang->report->undefined; - foreach($datas as $key => $data) $data->name = isset($this->lang->story->sourceList[$key]) ? $this->lang->story->sourceList[$key] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per plan - * - * @access public - * @return array - */ - public function getDataOfStorysPerPlan() - { - $datas = $this->dao->select('plan as name, count(plan) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('plan')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $plans = $this->dao->select('id, title')->from(TABLE_PRODUCTPLAN)->where('id')->in(array_keys($datas))->fetchPairs(); - foreach($datas as $planID => $data) $data->name = isset($plans[$planID]) ? $plans[$planID] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per status - * - * @access public - * @return array - */ - public function getDataOfStorysPerStatus() - { - $datas = $this->dao->select('status as name, count(status) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('status')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $status => $data) if(isset($this->lang->story->statusList[$status])) $data->name = $this->lang->story->statusList[$status]; - return $datas; - } - - /** - * Get report data of storys per stage - * - * @access public - * @return array - */ - public function getDataOfStorysPerStage() - { - $datas = $this->dao->select('stage as name, count(stage) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('stage')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $stage => $data) $data->name = $this->lang->story->stageList[$stage] != '' ? $this->lang->story->stageList[$stage] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per pri - * - * @access public - * @return array - */ - public function getDataOfStorysPerPri() - { - $datas = $this->dao->select('pri as name, count(pri) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('pri')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $pri => $data) $data->name = $this->lang->story->priList[$pri] != '' ? $this->lang->story->priList[$pri] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per estimate - * - * @access public - * @return array - */ - public function getDataOfStorysPerEstimate() - { - return $this->dao->select('estimate as name, count(estimate) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('estimate')->orderBy('value')->fetchAll(); - } - - /** - * Get report data of storys per openedBy - * - * @access public - * @return array - */ - public function getDataOfStorysPerOpenedBy() - { - $datas = $this->dao->select('openedBy as name, count(openedBy) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('openedBy')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) $data->name = isset($this->users[$account]) ? $this->users[$account] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per assignedTo - * - * @access public - * @return array - */ - public function getDataOfStorysPerAssignedTo() - { - $datas = $this->dao->select('assignedTo as name, count(assignedTo) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('assignedTo')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) $data->name = (isset($this->users[$account]) and $this->users[$account] != '') ? $this->users[$account] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per closedReason - * - * @access public - * @return array - */ - public function getDataOfStorysPerClosedReason() - { - $datas = $this->dao->select('closedReason as name, count(closedReason) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('closedReason')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $reason => $data) $data->name = $this->lang->story->reasonList[$reason] != '' ? $this->lang->story->reasonList[$reason] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of storys per change - * - * @access public - * @return array - */ - public function getDataOfStorysPerChange() - { - return $this->dao->select('(version-1) as name, count(*) as value')->from(TABLE_STORY) - ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() - ->groupBy('version')->orderBy('value')->fetchAll(); - } -} + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->findById((int)$storyID)->from(TABLE_STORY)->fetch(); + if(!$story) return false; + if(substr($story->closedDate, 0, 4) == '0000') $story->closedDate = ''; + if($version == 0) $version = $story->version; + $spec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWhere('version')->eq($version)->fetch(); + $story->title = isset($spec->title) ? $spec->title : ''; + $story->spec = isset($spec->spec) ? $this->loadModel('file')->setImgSize($spec->spec) : ''; + $story->verify = isset($spec->verify) ? $spec->verify : ''; + $story->projects = $this->dao->select('t1.project, t2.name, t2.status') + ->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.story')->eq($storyID) + ->orderBy('t1.project DESC') + ->fetchAll('project'); + $story->tasks = $this->dao->select('id, name, assignedTo, project, status, consumed, `left`')->from(TABLE_TASK)->where('story')->eq($storyID)->orderBy('id DESC')->fetchGroup('project'); + //$story->bugCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_BUG)->where('story')->eq($storyID)->fetch('count'); + //$story->caseCount = $this->dao->select('COUNT(*)')->alias('count')->from(TABLE_CASE)->where('story')->eq($storyID)->fetch('count'); + if($story->toBug) $story->toBugTitle = $this->dao->findById($story->toBug)->from(TABLE_BUG)->fetch('title'); + if($story->plan) $story->planTitle = $this->dao->findById($story->plan)->from(TABLE_PRODUCTPLAN)->fetch('title'); + $extraStories = array(); + if($story->duplicateStory) $extraStories = array($story->duplicateStory); + if($story->linkStories) $extraStories = explode(',', $story->linkStories); + if($story->childStories) $extraStories = array_merge($extraStories, explode(',', $story->childStories)); + $extraStories = array_unique($extraStories); + if(!empty($extraStories)) $story->extraStories = $this->dao->select('id,title')->from(TABLE_STORY)->where('id')->in($extraStories)->fetchPairs(); + return $story; + } + + /** + * Get affected things. + * + * @param object $story + * @access public + * @return object + */ + public function getAffectedScope($story) + { + /* Remove closed projects. */ + if($story->projects) + { + foreach($story->projects as $projectID => $project) + { + if($project->status != 'doing') unset($story->projects[$projectID]); + } + } + + /* Get team members. */ + if($story->projects) + { + $story->teams = $this->dao->select('account, project') + ->from(TABLE_TEAM) + ->where('project')->in(array_keys($story->projects)) + ->fetchGroup('project'); + } + + /* Get affected bugs. */ + $story->bugs = $this->dao->findByStory($story->id)->from(TABLE_BUG) + ->andWhere('status')->ne('closed') + ->andWhere('deleted')->eq(0) + ->orderBy('id desc')->fetchAll(); + + /* Get affected cases. */ + $story->cases = $this->dao->findByStory($story->id)->from(TABLE_CASE)->andWhere('deleted')->eq(0)->fetchAll(); + + return $story; + } + + /** + * Create a story. + * + * @access public + * @return int|bool the id of the created story or false when error. + */ + public function create($projectID = 0, $bugID = 0) + { + $now = helper::now(); + $story = fixer::input('post') + ->cleanInt('product,module,pri,plan') + ->cleanFloat('estimate') + ->stripTags('title') + ->callFunc('title', 'trim') + ->setDefault('plan', 0) + ->add('openedBy', $this->app->user->account) + ->add('openedDate', $now) + ->add('assignedDate', 0) + ->add('version', 1) + ->add('status', 'draft') + ->setIF($this->post->assignedTo != '', 'assignedDate', $now) + ->setIF($this->post->needNotReview, 'status', 'active') + ->setIF($this->post->plan > 0, 'stage', 'planned') + ->setIF($projectID > 0, 'stage', 'projected') + ->setIF($bugID > 0, 'fromBug', $bugID) + ->remove('files,labels,spec,verify,needNotReview') + ->get(); + + $this->dao->insert(TABLE_STORY)->data($story)->autoCheck()->batchCheck($this->config->story->create->requiredFields, 'notempty')->exec(); + if(!dao::isError()) + { + $storyID = $this->dao->lastInsertID(); + $this->loadModel('file')->saveUpload('story', $storyID, $extra = 1); + + $data->story = $storyID; + $data->version = 1; + $data->title = $story->title; + $data->spec = $this->post->spec; + $data->verify = $this->post->verify; + $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); + + if($projectID != 0) + { + $this->dao->insert(TABLE_PROJECTSTORY) + ->set('company')->eq(1) + ->set('project')->eq($projectID) + ->set('product')->eq($this->post->product) + ->set('story')->eq($storyID) + ->set('version')->eq(1) + ->exec(); + } + + if($bugID > 0) + { + $bug->toStory = $storyID; + $bug->status = 'closed'; + $bug->resolution = 'tostory'; + $bug->resolvedBy = $this->app->user->account; + $bug->resolvedDate = $now; + $bug->closedBy = $this->app->user->account; + $bug->closedDate = $now; + $bug->assignedTo = 'closed'; + $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bugID)->exec(); + + $this->loadModel('action')->create('bug', $bugID, 'ToStory', '', $storyID); + $this->action->create('bug', $bugID, 'Closed'); + + /* add files to story from bug. */ + $files = $this->dao->select('*')->from(TABLE_FILE) + ->where('objectType')->eq('bug') + ->andWhere('objectID')->eq($bugID) + ->fetchAll(); + if(!empty($files)) + { + foreach($files as $file) + { + $file->objectType = 'story'; + $file->objectID = $storyID; + unset($file->id); + $this->dao->insert(TABLE_FILE)->data($file)->exec(); + } + } + } + return $storyID; + } + return false; + } + + /** + * Create a batch stories. + * + * @access public + * @return int|bool the id of the created story or false when error. + */ + public function batchCreate($productID = 0) + { + $now = helper::now(); + $stories = fixer::input('post')->get(); + for($i = 0; $i < $this->config->story->batchCreate; $i++) + { + if($stories->title[$i] != '') + { + $data[$i]->module = $stories->module[$i] != 'same' ? $stories->module[$i] : ($i == 0 ? 0 : $data[$i-1]->module); + $data[$i]->plan = $stories->plan[$i] == 'same' ? ($i != 0 ? $data[$i-1]->plan : 0) : ($stories->plan[$i] != '' ? $stories->plan[$i] : 0); + $data[$i]->title = $stories->title[$i]; + $data[$i]->pri = $stories->pri[$i] != '' ? $stories->pri[$i] : 0; + $data[$i]->estimate = $stories->estimate[$i] != '' ? $stories->estimate[$i] : 0; + $data[$i]->status = $stories->needReview[$i] == 0 ? 'active' : 'draft'; + $data[$i]->product = $productID; + $data[$i]->openedBy = $this->app->user->account; + $data[$i]->openedDate = $now; + $data[$i]->version = 1; + + $this->dao->insert(TABLE_STORY) + ->data($data[$i]) + ->autoCheck() + ->batchCheck($this->config->story->create->requiredFields, 'notempty') + ->exec(); + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + + $storyID = $this->dao->lastInsertID(); + + $specData[$i]->story = $storyID; + $specData[$i]->version = 1; + $specData[$i]->title = $stories->title[$i]; + if($stories->spec[$i] != '') $specData[$i]->spec = $stories->spec[$i]; + $this->dao->insert(TABLE_STORYSPEC)->data($specData[$i])->exec(); + + $this->loadModel('action'); + $actionID = $this->action->create('story', $storyID, 'Opened', ''); + $mails[$i]->storyID = $storyID; + $mails[$i]->actionID = $actionID; + } + else + { + unset($stories->use[$i]); + unset($stories->module[$i]); + unset($stories->plan[$i]); + unset($stories->title[$i]); + unset($stories->spec[$i]); + unset($stories->pri[$i]); + unset($stories->estimate[$i]); + unset($stories->needReview[$i]); + } + } + return $mails; + } + + /** + * Change a story. + * + * @param int $storyID + * @access public + * @return array the change of the story. + */ + public function change($storyID) + { + $now = helper::now(); + $oldStory = $this->getById($storyID); + $specChanged = false; + if($this->post->spec != $oldStory->spec or $this->post->verify != $oldStory->verify or $this->post->title != $oldStory->title or $this->loadModel('file')->getCount()) $specChanged = true; + + $story = fixer::input('post') + ->stripTags('title') + ->callFunc('title', 'trim') + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->setIF($this->post->assignedTo != $oldStory->assignedTo, 'assignedDate', $now) + ->setIF($specChanged, 'version', $oldStory->version + 1) + ->setIF($specChanged and $oldStory->status == 'active' and $this->post->needNotReview == false, 'status', 'changed') + ->setIF($specChanged and $oldStory->status == 'draft' and $this->post->needNotReview, 'status', 'active') + ->setIF($specChanged, 'reviewedBy', '') + ->setIF($specChanged, 'closedBy', '') + ->setIF($specChanged, 'closedReason', '') + ->setIF($specChanged and $oldStory->reviewedBy, 'reviewedDate', '0000-00-00') + ->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00') + ->remove('files,labels,spec,verify,comment,needNotReview') + ->get(); + $this->dao->update(TABLE_STORY) + ->data($story) + ->autoCheck() + ->batchCheck($this->config->story->change->requiredFields, 'notempty') + ->where('id')->eq((int)$storyID)->exec(); + if(!dao::isError()) + { + if($specChanged) + { + $data->story = $storyID; + $data->version = $oldStory->version + 1; + $data->title = $story->title; + $data->spec = $this->post->spec; + $data->verify = $this->post->verify; + $this->dao->insert(TABLE_STORYSPEC)->data($data)->exec(); + $story->spec = $this->post->spec; + $story->verify = $this->post->verify; + } + else + { + unset($oldStory->spec); + } + return common::createChanges($oldStory, $story); + } + } + + /** + * Update a story. + * + * @param int $storyID + * @access public + * @return array the changes of the story. + */ + public function update($storyID) + { + $now = helper::now(); + $oldStory = $this->getById($storyID); + + $story = fixer::input('post') + ->cleanInt('product,module,pri,plan') + ->stripTags('title') + ->add('assignedDate', $oldStory->assignedDate) + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->setDefault('plan', 0) + ->setDefault('status', $oldStory->status) + ->setIF($this->post->assignedTo != $oldStory->assignedTo, 'assignedDate', $now) + ->setIF($this->post->closedBy != false and $oldStory->closedDate == '', 'closedDate', $now) + ->setIF($this->post->closedReason != false and $oldStory->closedDate == '', 'closedDate', $now) + ->setIF($this->post->closedBy != false or $this->post->closedReason != false, 'status', 'closed') + ->setIF($this->post->closedReason != false and $this->post->closedBy == false, 'closedBy', $this->app->user->account) + ->remove('files,labels,comment') + ->get(); + + $this->dao->update(TABLE_STORY) + ->data($story) + ->autoCheck() + ->batchCheck($this->config->story->edit->requiredFields, 'notempty') + ->checkIF(isset($story->closedBy), 'closedReason', 'notempty') + ->checkIF(isset($story->closedReason) and $story->closedReason == 'done', 'stage', 'notempty') + ->checkIF(isset($story->closedReason) and $story->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF(isset($story->closedReason) and $story->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq((int)$storyID)->exec(); + + $this->setStage($storyID); + if(!dao::isError()) return common::createChanges($oldStory, $story); + } + + /** + * Review a story. + * + * @param int $storyID + * @access public + * @return bool + */ + public function review($storyID) + { + if($this->post->result == false) die(js::alert($this->lang->story->mustChooseResult)); + if($this->post->result == 'revert' and $this->post->preVersion == false) die(js::alert($this->lang->story->mustChoosePreVersion)); + + $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); + $now = helper::now(); + $date = helper::today(); + $story = fixer::input('post') + ->remove('result,preVersion,comment') + ->setDefault('reviewedDate', $date) + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->setIF($this->post->result == 'pass' and $oldStory->status == 'draft', 'status', 'active') + ->setIF($this->post->result == 'pass' and $oldStory->status == 'changed', 'status', 'active') + ->setIF($this->post->result == 'reject', 'closedBy', $this->app->user->account) + ->setIF($this->post->result == 'reject', 'closedDate', $now) + ->setIF($this->post->result == 'reject', 'assignedTo', 'closed') + ->setIF($this->post->result == 'reject', 'status', 'closed') + ->setIF($this->post->result == 'revert', 'version', $this->post->preVersion) + ->setIF($this->post->result == 'revert', 'status', 'active') + ->setIF($this->post->closedReason == 'done', 'stage', 'released') + ->removeIF($this->post->result != 'reject', 'closedReason, duplicateStory, childStories') + ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'duplicate', 'duplicateStory') + ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'subdivided', 'childStories') + ->get(); + $this->dao->update(TABLE_STORY)->data($story) + ->autoCheck() + ->batchCheck($this->config->story->review->requiredFields, 'notempty') + ->checkIF($this->post->result == 'reject', 'closedReason', 'notempty') + ->checkIF($this->post->result == 'reject' and $this->post->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF($this->post->result == 'reject' and $this->post->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq($storyID)->exec(); + if($this->post->result == 'revert') + { + $preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($this->post->preVersion)->fetch('title'); + $this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->where('id')->eq($storyID)->exec(); + $this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($oldStory->version)->exec(); + $this->dao->delete()->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->eq($storyID)->andWhere('extra')->eq($oldStory->version)->exec(); + } + $this->setStage($storyID); + return true; + } + + /** + * Close a story. + * + * @param int $storyID + * @access public + * @return bool + */ + public function close($storyID) + { + $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); + $now = helper::now(); + $story = fixer::input('post') + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->add('closedDate', $now) + ->add('closedBy', $this->app->user->account) + ->add('assignedTo', 'closed') + ->add('assignedDate', $now) + ->add('status', 'closed') + ->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory') + ->removeIF($this->post->closedReason != 'subdivided', 'childStories') + ->setIF($this->post->closedReason == 'done', 'stage', 'released') + ->setIF($this->post->closedReason != 'done', 'plan', 0) + ->remove('comment') + ->get(); + $this->dao->update(TABLE_STORY)->data($story) + ->autoCheck() + ->batchCheck($this->config->story->close->requiredFields, 'notempty') + ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq($storyID)->exec(); + return true; + } + + /** + * Activate a story. + * + * @param int $storyID + * @access public + * @return bool + */ + public function activate($storyID) + { + $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); + $now = helper::now(); + $story = fixer::input('post') + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->add('assignedDate', $now) + ->add('status', 'active') + ->add('closedBy', '') + ->add('closedReason', '') + ->add('closedDate', '0000-00-00') + ->add('reviewedBy', '') + ->add('reviewedDate', '0000-00-00') + ->remove('comment') + ->get(); + $this->dao->update(TABLE_STORY)->data($story)->autoCheck()->where('id')->eq($storyID)->exec(); + return true; + } + + /** + * Set stage of a story. + * + * @param int $storyID + * @param string $customStage + * @access public + * @return bool + */ + public function setStage($storyID, $customStage = '') + { + /* Custom stage defined, use it. */ + if($customStage) + { + $this->dao->update(TABLE_STORY)->set('stage')->eq($customStage)->where('id')->eq((int)$storyID)->exec(); + return true; + } + + /* Get projects which status is doing. */ + $projects = $this->dao->select('project') + ->from(TABLE_PROJECTSTORY)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.story')->eq((int)$storyID) + ->andWhere('t2.status')->ne('done') + ->andWhere('t2.deleted')->eq(0) + ->fetchPairs(); + + /* If no projects, in plan, stage is planned. No plan, wait. */ + if(!$projects) + { + $this->dao->update(TABLE_STORY)->set('stage')->eq('planned')->where('id')->eq((int)$storyID)->andWhere('plan')->gt(0)->exec(); + $this->dao->update(TABLE_STORY)->set('stage')->eq('wait')->where('id')->eq((int)$storyID)->andWhere('plan')->eq(0)->andWhere('status')->eq('active')->exec(); + return true; + } + + /* Search related tasks. */ + $tasks = $this->dao->select('type,status')->from(TABLE_TASK) + ->where('project')->in($projects) + ->andWhere('story')->eq($storyID) + ->andWhere('status')->ne('cancel') + ->andWhere('status')->ne('closed') + ->andWhere('deleted')->eq(0) + ->fetchGroup('type'); + + /* No tasks, then the stage is projected. */ + if(!$tasks) + { + $this->dao->update(TABLE_STORY)->set('stage')->eq('projected')->where('id')->eq((int)$storyID)->exec(); + return true; + } + + /* If have test task, the stage is tested, testing or developing. */ + if(isset($tasks['test'])) + { + $stage = 'tested'; + foreach($tasks['test'] as $task) + { + if($task->status != 'done') + { + $stage = 'testing'; + break; + } + } + if($stage != 'testing') + { + unset($tasks['test']); + foreach($tasks as $type => $typeTasks) + { + foreach($typeTasks as $task) + { + if($task->status != 'done') + { + $stage = 'developing'; + break; + } + } + } + } + } + /* No test taske, stage is done or developing. */ + else + { + $stage = 'developed'; + foreach($tasks as $type => $typeTasks) + { + foreach($typeTasks as $task) + { + if($task->status != 'done') + { + $stage = 'developing'; + break; + } + } + } + } + $this->dao->update(TABLE_STORY)->set('stage')->eq($stage)->where('id')->eq((int)$storyID)->exec(); + return; + } + + /** + * Get stories list of a product. + * + * @param int $productID + * @param array|string $moduleIds + * @param string $status + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getProductStories($productID = 0, $moduleIds = 0, $status = 'all', $orderBy = 'id_desc', $pager = null) + { + $stories = $this->dao->select('t1.*, t2.title as planTitle') + ->from(TABLE_STORY)->alias('t1') + ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') + ->where('t1.product')->in($productID) + ->beginIF(!empty($moduleIds))->andWhere('module')->in($moduleIds)->fi() + ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() + ->andWhere('t1.deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + + $this->saveReportQuery($this->dao->get()); + + return $stories; + } + + /** + * Get stories pairs of a product. + * + * @param int $productID + * @param array|string $moduleIds + * @param string $status + * @param string $order + * @access public + * @return array + */ + public function getProductStoryPairs($productID = 0, $moduleIds = 0, $status = 'all', $order = 'id_desc') + { + $stories = $this->dao->select('t1.id, t1.title, t1.module, t1.pri, t1.estimate, t2.name AS product') + ->from(TABLE_STORY)->alias('t1')->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->where('1=1') + ->beginIF($productID)->andWhere('t1.product')->in($productID)->fi() + ->beginIF($moduleIds)->andWhere('t1.module')->in($moduleIds)->fi() + ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() + ->andWhere('t1.deleted')->eq(0) + ->orderBy($order) + ->fetchAll(); + if(!$stories) return array(); + return $this->formatStories($stories); + } + + /** + * Get stories by assignedTo. + * + * @param int $productID + * @param string $account + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByAssignedTo($productID, $account, $orderBy, $pager) + { + return $this->getByField($productID, 'assignedTo', $account, $orderBy, $pager); + } + + /** + * Get stories by openedBy. + * + * @param int $productID + * @param string $account + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByOpenedBy($productID, $account, $orderBy, $pager) + { + return $this->getByField($productID, 'openedBy', $account, $orderBy, $pager); + } + + /** + * Get stories by reviewedBy. + * + * @param int $productID + * @param string $account + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getByReviewedBy($productID, $account, $orderBy, $pager) + { + return $this->getByField($productID, 'reviewedBy', $account, $orderBy, $pager, 'include'); + } + + /** + * Get stories by closedBy. + * + * @param int $productID + * @param string $account + * @param string $orderBy + * @param object $pager + * @return array + */ + public function getByClosedBy($productID, $account, $orderBy, $pager) + { + return $this->getByField($productID, 'closedBy', $account, $orderBy, $pager); + } + + /** + * Get stories by status. + * + * @param int $productID + * @param string $orderBy + * @param object $pager + * @param string $status + * @access public + * @return array + */ + public function getByStatus($productID, $status, $orderBy, $pager) + { + return $this->getByField($productID, 'status', $status, $orderBy, $pager); + } + + /** + * Get stories by a field. + * + * @param int $productID + * @param string $fieldName + * @param mixed $fieldValue + * @param string $orderBy + * @param object $pager + * @param string $operator equal|include + * @access public + * @return array + */ + public function getByField($productID, $fieldName, $fieldValue, $orderBy, $pager, $operator = 'equal') + { + $stories = $this->dao->select('t1.*, t2.title as planTitle') + ->from(TABLE_STORY)->alias('t1') + ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') + ->where('t1.product')->in($productID) + ->andWhere('t1.deleted')->eq(0) + ->beginIF($operator == 'equal')->andWhere($fieldName)->eq($fieldValue)->fi() + ->beginIF($operator == 'include')->andWhere($fieldName)->like("%$fieldValue%")->fi() + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + $this->saveReportQuery($this->dao->get()); + + return $stories; + } + + /** + * Get stories through search. + * + * @access public + * @param int $productID + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getBySearch($productID, $queryID, $orderBy, $pager) + { + $products = $this->loadModel('product')->getPairs(); + $query = $queryID ? $this->loadModel('search')->getQuery($queryID) : ''; + + /* Get the sql and form status from the query. */ + if($query) + { + $this->session->set('storyQuery', $query->sql); + $this->session->set('storyForm', $query->form); + } + if($this->session->storyQuery == false) $this->session->set('storyQuery', ' 1 = 1'); + + $allProduct = "`product` = 'all'"; + $storyQuery = $this->session->storyQuery; + $queryProductID = $productID; + if(strpos($this->session->storyQuery, $allProduct) !== false) + { + $storyQuery = str_replace($allProduct, '1', $this->session->storyQuery); + $queryProductID = 'all'; + } + $storyQuery = $storyQuery . 'AND `product`' . helper::dbIN(array_keys($products)); + + return $this->getBySQL($queryProductID, $storyQuery, $orderBy, $pager); + } + + /** + * Get stories by a sql. + * + * @param int $productID + * @param string $sql + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getBySQL($productID, $sql, $orderBy, $pager = null) + { + $tmpStories = $this->dao->select('*')->from(TABLE_STORY)->where($sql) + ->beginIF($productID != 'all')->andWhere('product')->eq((int)$productID)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + $this->saveReportQuery($this->dao->get()); + + if(!$tmpStories) return array(); + + /* Get plans. */ + $plans = array(); + foreach($tmpStories as $story) $plans[$story->plan] = $story->plan; + $plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN)->where('id')->in(array_keys($plans))->fetchPairs(); + + /* Process plans. */ + $stories = array(); + foreach($tmpStories as $story) + { + $story->planTitle = isset($plans[$story->plan]) ? $plans[$story->plan] : ''; + $stories[] = $story; + } + return $stories; + } + + /** + * Save one executed query as report query, thus when create report chart to make use the condition is the same. + * + * @param string $sql + * @access public + * @return void + */ + public function saveReportQuery($sql) + { + $sql = explode('WHERE', $sql); + $sql = explode('ORDER', $sql[1]); + $sql = str_replace('t1.', '', $sql[0]); + $this->session->set('storyReport', $sql); + } + + /** + * Get stories list of a project. + * + * @param int $projectID + * @param string $orderBy + * @access public + * @return array + */ + public function getProjectStories($projectID = 0, $orderBy = 'pri_asc,id_desc') + { + return $this->dao->select('t1.*, t2.*')->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t2.deleted')->eq(0) + ->orderBy($orderBy) + ->fetchAll('id'); + } + + /** + * Get stories pairs of a project. + * + * @param int $projectID + * @param int $productID + * @access public + * @return array + */ + public function getProjectStoryPairs($projectID = 0, $productID = 0) + { + $stories = $this->dao->select('t2.id, t2.title, t2.module, t2.pri, t2.estimate, t3.name AS product') + ->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2') + ->on('t1.story = t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3') + ->on('t1.product = t3.id') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t2.deleted')->eq(0) + ->beginIF($productID)->andWhere('t1.product')->eq((int)$productID)->fi() + ->fetchAll(); + if(!$stories) return array(); + return $this->formatStories($stories); + } + + /** + * Get stories list of a plan. + * + * @param int $planID + * @param string $status + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getPlanStories($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('*')->from(TABLE_STORY) + ->where('plan')->eq((int)$planID) + ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll('id'); + } + + /** + * Get stories pairs of a plan. + * + * @param int $planID + * @param string $status + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getPlanStoryPairs($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('*')->from(TABLE_STORY) + ->where('plan')->eq($planID) + ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() + ->andWhere('deleted')->eq(0) + ->fetchAll(); + } + + /** + * Get stories of a user. + * + * @param string $account + * @param string $type the query type + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getUserStories($account, $type = 'assignedto', $orderBy = 'id_desc', $pager = null) + { + $type = strtolower($type); + return $this->dao->select('t1.*, t2.title as planTitle, t3.name as productTitle') + ->from(TABLE_STORY)->alias('t1') + ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') + ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product = t3.id') + ->where('t1.deleted')->eq(0) + ->beginIF($type == 'assignedto')->andWhere('assignedTo')->eq($this->app->user->account)->fi() + ->beginIF($type == 'openedby')->andWhere('openedby')->eq($this->app->user->account)->fi() + ->beginIF($type == 'reviewedby')->andWhere('reviewedby')->like('%' . $this->app->user->account . '%')->fi() + ->beginIF($type == 'closedby')->andWhere('closedby')->eq($this->app->user->account)->fi() + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get doing projects' members of a story. + * + * @param int $storyID + * @access public + * @return array + */ + public function getProjectMembers($storyID) + { + $projects = $this->dao->select('project') + ->from(TABLE_PROJECTSTORY)->alias('t1')->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.story')->eq((int)$storyID) + ->andWhere('t2.status')->eq('doing') + ->andWhere('t2.deleted')->eq(0) + ->fetchPairs(); + if($projects) return($this->dao->select('account')->from(TABLE_TEAM)->where('project')->in($projects)->fetchPairs('account')); + } + + /** + * Get version of a story. + * + * @param int $storyID + * @access public + * @return int + */ + public function getVersion($storyID) + { + return $this->dao->select('version')->from(TABLE_STORY)->where('id')->eq((int)$storyID)->fetch('version'); + } + + /** + * Get versions of some stories. + * + * @param array|string story id list + * @access public + * @return array + */ + public function getVersions($storyID) + { + return $this->dao->select('id, version')->from(TABLE_STORY)->where('id')->in($storyID)->fetchPairs(); + } + + /** + * Format stories + * + * @param array $stories + * @access private + * @return void + */ + private function formatStories($stories) + { + /* Get module names of stories. */ + /*$modules = array(); + foreach($stories as $story) $modules[] = $story->module; + $moduleNames = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($modules)->fetchPairs();*/ + + /* Format these stories. */ + $storyPairs = array('' => ''); + foreach($stories as $story) $storyPairs[$story->id] = $story->id . ':' . $story->title . "({$this->lang->story->pri}:$story->pri, {$this->lang->story->estimate}: $story->estimate)"; + return $storyPairs; + } + + /** + * Extract accounts from some stories. + * + * @param array $stories + * @access public + * @return array + */ + public function extractAccountsFromList($stories) + { + $accounts = array(); + foreach($stories as $story) + { + if(!empty($story->openedBy)) $accounts[] = $story->openedBy; + if(!empty($story->assignedTo)) $accounts[] = $story->assignedTo; + if(!empty($story->closedBy)) $accounts[] = $story->closedBy; + if(!empty($story->lastEditedBy)) $accounts[] = $story->lastEditedBy; + } + return array_unique($accounts); + } + + /** + * Extract accounts from a story. + * + * @param object $story + * @access public + * @return array + */ + public function extractAccountsFromSingle($story) + { + $accounts = array(); + if(!empty($story->openedBy)) $accounts[] = $story->openedBy; + if(!empty($story->assignedTo)) $accounts[] = $story->assignedTo; + if(!empty($story->closedBy)) $accounts[] = $story->closedBy; + if(!empty($story->lastEditedBy)) $accounts[] = $story->lastEditedBy; + return array_unique($accounts); + } + + /** + * Merge the default chart settings and the settings of current chart. + * + * @param string $chartType + * @access public + * @return void + */ + public function mergeChartOption($chartType) + { + $chartOption = $this->lang->story->report->$chartType; + $commonOption = $this->lang->story->report->options; + + $chartOption->graph->caption = $this->lang->story->report->charts[$chartType]; + if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; + if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; + if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; + + foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; + } + + /** + * Get report data of storys per product + * + * @access public + * @return array + */ + public function getDataOfStorysPerProduct() + { + $datas = $this->dao->select('product as name, count(product) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('product')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $products = $this->loadModel('product')->getPairs(); + foreach($datas as $productID => $data) $data->name = isset($products[$productID]) ? $products[$productID] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per module + * + * @access public + * @return array + */ + public function getDataOfStorysPerModule() + { + $datas = $this->dao->select('module as name, count(module) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('module')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $modules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in(array_keys($datas))->fetchPairs(); + foreach($datas as $moduleID => $data) $data->name = isset($modules[$moduleID]) ? $modules[$moduleID] : '/'; + return $datas; + } + + /** + * Get report data of storys per source + * + * @access public + * @return array + */ + public function getDataOfStorysPerSource() + { + $datas = $this->dao->select('source as name, count(source) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('source')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $this->lang->story->sourceList[''] = $this->lang->report->undefined; + foreach($datas as $key => $data) $data->name = isset($this->lang->story->sourceList[$key]) ? $this->lang->story->sourceList[$key] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per plan + * + * @access public + * @return array + */ + public function getDataOfStorysPerPlan() + { + $datas = $this->dao->select('plan as name, count(plan) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('plan')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $plans = $this->dao->select('id, title')->from(TABLE_PRODUCTPLAN)->where('id')->in(array_keys($datas))->fetchPairs(); + foreach($datas as $planID => $data) $data->name = isset($plans[$planID]) ? $plans[$planID] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per status + * + * @access public + * @return array + */ + public function getDataOfStorysPerStatus() + { + $datas = $this->dao->select('status as name, count(status) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('status')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $status => $data) if(isset($this->lang->story->statusList[$status])) $data->name = $this->lang->story->statusList[$status]; + return $datas; + } + + /** + * Get report data of storys per stage + * + * @access public + * @return array + */ + public function getDataOfStorysPerStage() + { + $datas = $this->dao->select('stage as name, count(stage) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('stage')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $stage => $data) $data->name = $this->lang->story->stageList[$stage] != '' ? $this->lang->story->stageList[$stage] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per pri + * + * @access public + * @return array + */ + public function getDataOfStorysPerPri() + { + $datas = $this->dao->select('pri as name, count(pri) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('pri')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $pri => $data) $data->name = $this->lang->story->priList[$pri] != '' ? $this->lang->story->priList[$pri] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per estimate + * + * @access public + * @return array + */ + public function getDataOfStorysPerEstimate() + { + return $this->dao->select('estimate as name, count(estimate) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('estimate')->orderBy('value')->fetchAll(); + } + + /** + * Get report data of storys per openedBy + * + * @access public + * @return array + */ + public function getDataOfStorysPerOpenedBy() + { + $datas = $this->dao->select('openedBy as name, count(openedBy) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('openedBy')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) $data->name = isset($this->users[$account]) ? $this->users[$account] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per assignedTo + * + * @access public + * @return array + */ + public function getDataOfStorysPerAssignedTo() + { + $datas = $this->dao->select('assignedTo as name, count(assignedTo) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('assignedTo')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) $data->name = (isset($this->users[$account]) and $this->users[$account] != '') ? $this->users[$account] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per closedReason + * + * @access public + * @return array + */ + public function getDataOfStorysPerClosedReason() + { + $datas = $this->dao->select('closedReason as name, count(closedReason) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('closedReason')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $reason => $data) $data->name = $this->lang->story->reasonList[$reason] != '' ? $this->lang->story->reasonList[$reason] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of storys per change + * + * @access public + * @return array + */ + public function getDataOfStorysPerChange() + { + return $this->dao->select('(version-1) as name, count(*) as value')->from(TABLE_STORY) + ->beginIF($this->session->storyReport != false)->where($this->session->storyReport)->fi() + ->groupBy('version')->orderBy('value')->fetchAll(); + } +} diff --git a/module/story/view/activate.html.php b/module/story/view/activate.html.php index 6e98032310..f88efd333e 100644 --- a/module/story/view/activate.html.php +++ b/module/story/view/activate.html.php @@ -1,36 +1,36 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - -
          story->activate;?>
          story->assignedTo;?>closedBy, 'class="select-3"');?>
          story->comment;?>
          - goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); - ?> -
          - -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + +
          story->activate;?>
          story->assignedTo;?>closedBy, 'class="select-3"');?>
          story->comment;?>
          + goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); + ?> +
          + +
          + diff --git a/module/story/view/batchcreate.html.php b/module/story/view/batchcreate.html.php index 435adb5126..d7d63392af 100644 --- a/module/story/view/batchcreate.html.php +++ b/module/story/view/batchcreate.html.php @@ -1,49 +1,49 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - story->batchCreate; $i++):?> - - - - - - - - - - - - - - - - -
          story->product . $lang->colon . $lang->story->batchCreate;?>
          idAB;?>story->module;?>story->plan;?>story->title;?>story->spec;?>story->pri;?>story->estimate;?>story->review;?>
          *";?>story->priList, $pri, 'class=select-1');?>story->reviewList, 0, "class='text-1'");?>
          -
          story->notes;?>
          -
          -
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + story->batchCreate; $i++):?> + + + + + + + + + + + + + + + + +
          story->product . $lang->colon . $lang->story->batchCreate;?>
          idAB;?>story->module;?>story->plan;?>story->title;?>story->spec;?>story->pri;?>story->estimate;?>story->review;?>
          *";?>story->priList, $pri, 'class=select-1');?>story->reviewList, 0, "class='text-1'");?>
          +
          story->notes;?>
          +
          +
          +
          + diff --git a/module/story/view/change.html.php b/module/story/view/change.html.php index 0362ac0886..a001e8d8cb 100644 --- a/module/story/view/change.html.php +++ b/module/story/view/change.html.php @@ -1,52 +1,52 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - -
          story->change;?>
          story->reviewedBy;?>assignedTo, 'class="select-3"') . html::checkbox('needNotReview', $lang->story->needNotReview, '', "id='needNotReview'");?>
          story->title;?>title, 'class="text-1"');?>
          story->spec;?>spec), 'rows=8 class="area-1"');?>
          story->specTemplate;?>
          story->verify;?>verify), 'rows=6 class="area-1"');?>
          story->comment;?>
          attatch;?>fetch('file', 'buildform', 'filecount=2');?>
          - -
          - goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); - ?> -
          - -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + +
          story->change;?>
          story->reviewedBy;?>assignedTo, 'class="select-3"') . html::checkbox('needNotReview', $lang->story->needNotReview, '', "id='needNotReview'");?>
          story->title;?>title, 'class="text-1"');?>
          story->spec;?>spec), 'rows=8 class="area-1"');?>
          story->specTemplate;?>
          story->verify;?>verify), 'rows=6 class="area-1"');?>
          story->comment;?>
          attatch;?>fetch('file', 'buildform', 'filecount=2');?>
          + +
          + goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); + ?> +
          + +
          + diff --git a/module/story/view/close.html.php b/module/story/view/close.html.php index 51c261d70b..d5e0d39b3e 100644 --- a/module/story/view/close.html.php +++ b/module/story/view/close.html.php @@ -1,42 +1,42 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - - - - - - - -
          title;?>
          story->closedReason;?>story->reasonList, '', 'class=select-3 onchange="setStory(this.value)"');?>
          story->comment;?>
          - - goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"));?> -
          - -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + + + + + + + +
          title;?>
          story->closedReason;?>story->reasonList, '', 'class=select-3 onchange="setStory(this.value)"');?>
          story->comment;?>
          + + goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"));?> +
          + +
          + diff --git a/module/story/view/create.html.php b/module/story/view/create.html.php index 88671db3e1..7f1bee3fd5 100644 --- a/module/story/view/create.html.php +++ b/module/story/view/create.html.php @@ -1,73 +1,73 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          story->create;?>
          story->product;?> - - -
          story->plan;?>
          story->source;?>story->sourceList, $source, 'class=select-3');?>
          story->title;?>
          story->spec;?>
          story->specTemplate;?>
          story->verify;?>
          story->pri;?>story->priList, $pri, 'class=select-3');?>
          story->estimate;?>
          story->reviewedBy;?>story->needNotReview, '', "id='needNotReview'");?>
          story->mailto;?>
          story->keywords;?>
          story->legendAttatch;?>fetch('file', 'buildform');?>
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          story->create;?>
          story->product;?> + + +
          story->plan;?>
          story->source;?>story->sourceList, $source, 'class=select-3');?>
          story->title;?>
          story->spec;?>
          story->specTemplate;?>
          story->verify;?>
          story->pri;?>story->priList, $pri, 'class=select-3');?>
          story->estimate;?>
          story->reviewedBy;?>story->needNotReview, '', "id='needNotReview'");?>
          story->mailto;?>
          story->keywords;?>
          story->legendAttatch;?>fetch('file', 'buildform');?>
          +
          + diff --git a/module/story/view/edit.html.php b/module/story/view/edit.html.php index 5dc32896d2..fbe2563a95 100644 --- a/module/story/view/edit.html.php +++ b/module/story/view/edit.html.php @@ -1,139 +1,139 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          -
          STORY #id . $lang->colon . $story->title;?>
          -
          -
          - - - - - - - -
          -
          - story->legendSpec;?> -
          spec;?>
          -
          -
          - story->comment;?> - -
          -
          - goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); - ?> -
          - -
          -
          - story->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - status != 'draft'):?> - - - - - - - - - - - - - - - - - -
          story->product;?>product, 'class="select-1" onchange="loadProduct(this.value)";');?>
          story->module;?>module, 'class="select-1"');?>
          story->plan;?>plan, 'class=select-1');?>
          story->source;?>story->sourceList, $story->source, 'class=select-1');?>
          story->status;?>story->statusList[$story->status];?>
          story->stage;?>story->stageList, $story->stage, 'class=select-1');?>
          story->pri;?>story->priList, $story->pri, 'class=select-1');?>
          story->estimate;?>estimate, 'class=text-1');?>
          story->keywords;?>keywords, 'class=text-1');?>
          -
          -
          - story->legendLifeTime;?> - - - - - - - - - - reviewedBy):?> - - - - - - closedBy):?> - - - - - - - - - -
          story->openedBy;?>openedBy];?>
          story->assignedTo;?>assignedTo, 'class="select-1"');?>
          story->reviewedBy;?>reviewedBy, 'class="area-1"');?>
          story->closedBy;?>closedBy, 'class="select-1"');?>
          story->closedReason;?>story->reasonList, $story->closedReason, 'class="select-1"');?>
          -
          - -
          - story->legendMisc;?> - - - - - - - - - - - - - - - - - -
          story->duplicateStory;?>duplicateStory, "class='text-1'");?>
          story->linkStories;?>linkStories, "class='text-1'");?>
          story->childStories;?>childStories, "class='text-1'");?>
          story->mailto;?>mailto, "class='area-1'");?>
          -
          -
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          +
          STORY #id . $lang->colon . $story->title;?>
          +
          +
          + + + + + + + +
          +
          + story->legendSpec;?> +
          spec;?>
          +
          +
          + story->comment;?> + +
          +
          + goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id")); + ?> +
          + +
          +
          + story->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + status != 'draft'):?> + + + + + + + + + + + + + + + + + +
          story->product;?>product, 'class="select-1" onchange="loadProduct(this.value)";');?>
          story->module;?>module, 'class="select-1"');?>
          story->plan;?>plan, 'class=select-1');?>
          story->source;?>story->sourceList, $story->source, 'class=select-1');?>
          story->status;?>story->statusList[$story->status];?>
          story->stage;?>story->stageList, $story->stage, 'class=select-1');?>
          story->pri;?>story->priList, $story->pri, 'class=select-1');?>
          story->estimate;?>estimate, 'class=text-1');?>
          story->keywords;?>keywords, 'class=text-1');?>
          +
          +
          + story->legendLifeTime;?> + + + + + + + + + + reviewedBy):?> + + + + + + closedBy):?> + + + + + + + + + +
          story->openedBy;?>openedBy];?>
          story->assignedTo;?>assignedTo, 'class="select-1"');?>
          story->reviewedBy;?>reviewedBy, 'class="area-1"');?>
          story->closedBy;?>closedBy, 'class="select-1"');?>
          story->closedReason;?>story->reasonList, $story->closedReason, 'class="select-1"');?>
          +
          + +
          + story->legendMisc;?> + + + + + + + + + + + + + + + + + +
          story->duplicateStory;?>duplicateStory, "class='text-1'");?>
          story->linkStories;?>linkStories, "class='text-1'");?>
          story->childStories;?>childStories, "class='text-1'");?>
          story->mailto;?>mailto, "class='area-1'");?>
          +
          +
          +
          + diff --git a/module/story/view/export.html.php b/module/story/view/export.html.php index 1b87db5645..e832c5cd50 100644 --- a/module/story/view/export.html.php +++ b/module/story/view/export.html.php @@ -1,13 +1,13 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + diff --git a/module/story/view/report.html.php b/module/story/view/report.html.php index 1b3b6b9466..24e8d7a59f 100644 --- a/module/story/view/report.html.php +++ b/module/story/view/report.html.php @@ -1,62 +1,62 @@ - - * @package product - * @version $Id: report.html.php 1594 2011-03-13 07:27:55Z wwccss $ - * @link http://www.zentao.net - */ -?> - -
          -
          story->report->common;?>
          -
          goback); ?>
          -
          - - - - - - - -
          -
          story->report->select;?>
          -
          -
          - story->report->charts, $checkedCharts);?> - - -

          - story->report->create);?> -
          -
          - - - $chartContent):?> - - - - - -
          story->report->common;?>
          - - - - - - - $data):?> - - - - - - -
          report->item;?>report->value;?>report->percent;?>
          name;?>value;?>percent * 100) . '%';?>
          -
          -
          - - + + * @package product + * @version $Id: report.html.php 1594 2011-03-13 07:27:55Z wwccss $ + * @link http://www.zentao.net + */ +?> + +
          +
          story->report->common;?>
          +
          goback); ?>
          +
          + + + + + + + +
          +
          story->report->select;?>
          +
          + + story->report->charts, $checkedCharts);?> + + +

          + story->report->create);?> +
          +
          + + + $chartContent):?> + + + + + +
          story->report->common;?>
          + + + + + + + $data):?> + + + + + + +
          report->item;?>report->value;?>report->percent;?>
          name;?>value;?>percent * 100) . '%';?>
          +
          +
          + + diff --git a/module/story/view/review.html.php b/module/story/view/review.html.php index d14e46cf67..d6fe8888df 100644 --- a/module/story/view/review.html.php +++ b/module/story/view/review.html.php @@ -1,68 +1,68 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - status == 'changed' or ($story->status == 'draft' and $story->version > 1)):?> - - - - - - - - - - - - - - - - - - - - -
          title;?>
          story->reviewedDate;?>
          story->reviewResult;?>story->reviewResultList, '', 'class=select-3 onchange="switchShow(this.value)"');?>
          story->assignedTo;?>lastEditedBy ? $story->lastEditedBy : $story->openedBy, 'class=select-3');?>
          story->reviewedBy;?>user->account . ', ', 'class=text-1');?>
          story->comment;?>
          - - goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"));?> -
          - - - - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + status == 'changed' or ($story->status == 'draft' and $story->version > 1)):?> + + + + + + + + + + + + + + + + + + + + +
          title;?>
          story->reviewedDate;?>
          story->reviewResult;?>story->reviewResultList, '', 'class=select-3 onchange="switchShow(this.value)"');?>
          story->assignedTo;?>lastEditedBy ? $story->lastEditedBy : $story->openedBy, 'class=select-3');?>
          story->reviewedBy;?>user->account . ', ', 'class=text-1');?>
          story->comment;?>
          + + goback, $app->session->storyList ? $app->session->storyList : inlink('view', "storyID=$story->id"));?> +
          +
          + + + diff --git a/module/story/view/sendmail.html.php b/module/story/view/sendmail.html.php index e487d7c894..249a603dca 100644 --- a/module/story/view/sendmail.html.php +++ b/module/story/view/sendmail.html.php @@ -1,22 +1,22 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          - STORY #id . "=>$story->assignedTo " . html::a(common::getSysURL() . $this->createLink('story', 'view', "storyID=$story->id"), $story->title);?> -
          + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          + STORY #id . "=>$story->assignedTo " . html::a(common::getSysURL() . $this->createLink('story', 'view', "storyID=$story->id"), $story->title);?> +
          diff --git a/module/story/view/view.html.php b/module/story/view/view.html.php index a751b4f8a0..9b9695d83c 100644 --- a/module/story/view/view.html.php +++ b/module/story/view/view.html.php @@ -1,273 +1,273 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          deleted) echo "class='deleted'";?>>STORY #id . $lang->colon . $story->title;?>
          -
          - session->storyList != false ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product&moduleID=$story->module"); - if(!$story->deleted) - { - if(!($story->status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; - if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; - if(common::hasPriv('story', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; - if(!($story->status == 'closed' and $story->closedReason == 'postponed' and common::printLink('story', 'activate', "storyID=$story->id", $lang->story->activate))) echo $lang->story->activate . ' '; - if(!common::printLink('story', 'edit', "storyID=$story->id", $lang->edit)) echo $lang->edit . ' '; - if(!common::printLink('testcase', 'create', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", $lang->story->createCase)) echo $lang->story->createCase . ' '; - common::printLink('story', 'create', "productID=$story->product&moduleID=$story->module&storyID=$story->id", $lang->copy); - common::printLink('story', 'delete', "storyID=$story->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          -
          - - - - - - -
          -
          - story->legendSpec;?> -
          spec;?>
          -
          -
          - story->legendVerify;?> -
          verify;?>
          -
          - fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true'));?> - -
          - deleted) - { - if(!($story->status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; - if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; - if(common::hasPriv('story', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; - if(!($story->status == 'closed' and $story->closedReason == 'postponed' and common::printLink('story', 'activate', "storyID=$story->id", $lang->story->activate))) echo $lang->story->activate . ' '; - if(!common::printLink('testcase', 'create', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", $lang->story->createCase)) echo $lang->story->createCase . ' '; - if(!common::printLink('story', 'edit', "storyID=$story->id", $lang->edit)) echo $lang->edit . ' '; - common::printLink('story', 'delete', "storyID=$story->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - -
          - -
          - story->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          story->product;?>product", $product->name);?> -
          story->module;?> - $module) - { - if(!common::printLink('product', 'browse', "productID=$story->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; - if(isset($modulePath[$key + 1])) echo $lang->arrow; - } - } - ?> -
          story->plan;?>planTitle)) if(!common::printLink('productplan', 'view', "planID=$story->plan", $story->planTitle)) echo $story->planTitle;?> -
          story->source;?>story->sourceList[$story->source];?>
          story->status;?>story->statusList[$story->status];?>
          story->stage;?>story->stageList[$story->stage];?>
          story->pri;?>story->priList[$story->pri];?>
          story->estimate;?>estimate;?>
          story->keywords;?>keywords;?>
          -
          -
          - story->legendLifeTime;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          story->openedBy;?>openedBy] . $lang->at . $story->openedDate;?>
          story->assignedTo;?>assignedTo) echo $users[$story->assignedTo] . $lang->at . $story->assignedDate;?>
          story->reviewedBy;?>reviewedBy); foreach($reviewedBy as $account) echo ' ' . $users[trim($account)]; ?>
          story->reviewedDate;?>reviewedBy) echo $story->reviewedDate;?>
          story->closedBy;?>closedBy) echo $users[$story->closedBy] . $lang->at . $story->closedDate;?>
          story->closedReason;?> - closedReason) echo $lang->story->reasonList[$story->closedReason]; - if(isset($story->extraStories[$story->duplicateStory])) - { - echo html::a(inlink('view', "storyID=$story->duplicateStory"), '#' . $story->duplicateStory . ' ' . $story->extraStories[$story->duplicateStory]); - } - ?> -
          story->lastEditedBy;?>lastEditedBy) echo $users[$story->lastEditedBy] . $lang->at . $story->lastEditedDate;?>
          -
          - -
          - story->legendProjectAndTask;?> - - - - -
          - tasks as $projectTasks) - { - foreach($projectTasks as $task) - { - @$projectName = $story->projects[$task->project]->name; - echo html::a($this->createLink('project', 'browse', "projectID=$task->project"), $projectName); - echo '' . html::a($this->createLink('task', 'view', "taskID=$task->id"), "#$task->id $task->name") . '
          '; - } - } - ?> -
          -
          - -
          - story->legendBugs;?> - - - - -
          - ' . html::a($this->createLink('bug', 'view', "bugID=$bug->id"), "#$bug->id $bug->title") . '
          '; - } - ?> -
          -
          - -
          - story->legendCases;?> - - - - -
          - ' . html::a($this->createLink('testcase', 'view', "caseID=$case->id"), "#$case->id $case->title") . '
          '; - } - ?> -
          -
          - -
          - story->legendLinkStories;?> -
          - linkStories) ; - foreach($linkStories as $linkStoryID) - { - if(isset($story->extraStories[$linkStoryID])) echo html::a(inlink('view', "storyID=$linkStoryID"), "#$linkStoryID " . $story->extraStories[$linkStoryID]) . '
          '; - } - ?> -
          -
          -
          - story->legendChildStories;?> -
          - childStories) ; - foreach($childStories as $childStoryID) - { - if(isset($story->extraStories[$childStoryID])) echo html::a(inlink('view', "storyID=$childStoryID"), "#$childStoryID " . $story->extraStories[$childStoryID]) . '
          '; - } - ?> -
          -
          -
          - story->legendFromBug;?> -
          - ' . html::a($this->createLink('bug', 'view', "bugID=$fromBug->id"), "#$fromBug->id $fromBug->title") . '
          '; - ?> -
          -
          -
          - story->legendMailto;?> -
          mailto); foreach($mailto as $account) echo ' ' . $users[trim($account)]; ?>
          -
          -
          - story->legendVersion;?> -
          version; $i >= 1; $i --) echo html::a(inlink('view', "storyID=$story->id&version=$i"), "#$i");?>
          -
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          deleted) echo "class='deleted'";?>>STORY #id . $lang->colon . $story->title;?>
          +
          + session->storyList != false ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product&moduleID=$story->module"); + if(!$story->deleted) + { + if(!($story->status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; + if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; + if(common::hasPriv('story', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; + if(!($story->status == 'closed' and $story->closedReason == 'postponed' and common::printLink('story', 'activate', "storyID=$story->id", $lang->story->activate))) echo $lang->story->activate . ' '; + if(!common::printLink('story', 'edit', "storyID=$story->id", $lang->edit)) echo $lang->edit . ' '; + if(!common::printLink('testcase', 'create', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", $lang->story->createCase)) echo $lang->story->createCase . ' '; + common::printLink('story', 'create', "productID=$story->product&moduleID=$story->module&storyID=$story->id", $lang->copy); + common::printLink('story', 'delete', "storyID=$story->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          +
          + + + + + + +
          +
          + story->legendSpec;?> +
          spec;?>
          +
          +
          + story->legendVerify;?> +
          verify;?>
          +
          + fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true'));?> + +
          + deleted) + { + if(!($story->status != 'closed' and common::printLink('story', 'change', "storyID=$story->id", $lang->story->change))) echo $lang->story->change . ' '; + if(!(($story->status == 'draft' or $story->status == 'changed') and common::printLink('story', 'review', "storyID=$story->id", $lang->story->review))) echo $lang->story->review . ' '; + if(common::hasPriv('story', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!($story->status != 'closed' and common::printLink('story', 'close', "storyID=$story->id", $lang->story->close))) echo $lang->story->close . ' '; + if(!($story->status == 'closed' and $story->closedReason == 'postponed' and common::printLink('story', 'activate', "storyID=$story->id", $lang->story->activate))) echo $lang->story->activate . ' '; + if(!common::printLink('testcase', 'create', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", $lang->story->createCase)) echo $lang->story->createCase . ' '; + if(!common::printLink('story', 'edit', "storyID=$story->id", $lang->edit)) echo $lang->edit . ' '; + common::printLink('story', 'delete', "storyID=$story->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + +
          + +
          + story->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          story->product;?>product", $product->name);?> +
          story->module;?> + $module) + { + if(!common::printLink('product', 'browse', "productID=$story->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; + if(isset($modulePath[$key + 1])) echo $lang->arrow; + } + } + ?> +
          story->plan;?>planTitle)) if(!common::printLink('productplan', 'view', "planID=$story->plan", $story->planTitle)) echo $story->planTitle;?> +
          story->source;?>story->sourceList[$story->source];?>
          story->status;?>story->statusList[$story->status];?>
          story->stage;?>story->stageList[$story->stage];?>
          story->pri;?>story->priList[$story->pri];?>
          story->estimate;?>estimate;?>
          story->keywords;?>keywords;?>
          +
          +
          + story->legendLifeTime;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          story->openedBy;?>openedBy] . $lang->at . $story->openedDate;?>
          story->assignedTo;?>assignedTo) echo $users[$story->assignedTo] . $lang->at . $story->assignedDate;?>
          story->reviewedBy;?>reviewedBy); foreach($reviewedBy as $account) echo ' ' . $users[trim($account)]; ?>
          story->reviewedDate;?>reviewedBy) echo $story->reviewedDate;?>
          story->closedBy;?>closedBy) echo $users[$story->closedBy] . $lang->at . $story->closedDate;?>
          story->closedReason;?> + closedReason) echo $lang->story->reasonList[$story->closedReason]; + if(isset($story->extraStories[$story->duplicateStory])) + { + echo html::a(inlink('view', "storyID=$story->duplicateStory"), '#' . $story->duplicateStory . ' ' . $story->extraStories[$story->duplicateStory]); + } + ?> +
          story->lastEditedBy;?>lastEditedBy) echo $users[$story->lastEditedBy] . $lang->at . $story->lastEditedDate;?>
          +
          + +
          + story->legendProjectAndTask;?> + + + + +
          + tasks as $projectTasks) + { + foreach($projectTasks as $task) + { + @$projectName = $story->projects[$task->project]->name; + echo html::a($this->createLink('project', 'browse', "projectID=$task->project"), $projectName); + echo '' . html::a($this->createLink('task', 'view', "taskID=$task->id"), "#$task->id $task->name") . '
          '; + } + } + ?> +
          +
          + +
          + story->legendBugs;?> + + + + +
          + ' . html::a($this->createLink('bug', 'view', "bugID=$bug->id"), "#$bug->id $bug->title") . '
          '; + } + ?> +
          +
          + +
          + story->legendCases;?> + + + + +
          + ' . html::a($this->createLink('testcase', 'view', "caseID=$case->id"), "#$case->id $case->title") . '
          '; + } + ?> +
          +
          + +
          + story->legendLinkStories;?> +
          + linkStories) ; + foreach($linkStories as $linkStoryID) + { + if(isset($story->extraStories[$linkStoryID])) echo html::a(inlink('view', "storyID=$linkStoryID"), "#$linkStoryID " . $story->extraStories[$linkStoryID]) . '
          '; + } + ?> +
          +
          +
          + story->legendChildStories;?> +
          + childStories) ; + foreach($childStories as $childStoryID) + { + if(isset($story->extraStories[$childStoryID])) echo html::a(inlink('view', "storyID=$childStoryID"), "#$childStoryID " . $story->extraStories[$childStoryID]) . '
          '; + } + ?> +
          +
          +
          + story->legendFromBug;?> +
          + ' . html::a($this->createLink('bug', 'view', "bugID=$fromBug->id"), "#$fromBug->id $fromBug->title") . '
          '; + ?> +
          +
          +
          + story->legendMailto;?> +
          mailto); foreach($mailto as $account) echo ' ' . $users[trim($account)]; ?>
          +
          +
          + story->legendVersion;?> +
          version; $i >= 1; $i --) echo html::a(inlink('view', "storyID=$story->id&version=$i"), "#$i");?>
          +
          +
          + diff --git a/module/svn/control.php b/module/svn/control.php index c443dcbc98..a960b7aea3 100644 --- a/module/svn/control.php +++ b/module/svn/control.php @@ -1,98 +1,98 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -class svn extends control -{ - /** - * Sync svn. - * - * @access public - * @return void - */ - public function run() - { - $this->svn->run(); - } - - /** - * Diff a file. - * - * @param string $url - * @param int $revision - * @access public - * @return void - */ - public function diff($url, $revision) - { - $url = helper::safe64Decode($url); - $this->view->url = $url; - $this->view->revision = $revision; - $this->view->diff = $this->svn->diff($url, $revision); - - $this->display(); - } - - /** - * Cat a file. - * - * @param string $url - * @param int $revision - * @access public - * @return void - */ - public function cat($url, $revision) - { - $url = helper::safe64Decode($url); - $this->view->url = $url; - $this->view->revision = $revision; - $this->view->code = $this->svn->cat($url, $revision); - - $this->display(); - } - - /** - * Sync from the syncer by api. - * - * @access public - * @return void - */ - public function apiSync() - { - if($this->post->logs) - { - $repoRoot = $this->post->repoRoot; - $logs = stripslashes($this->post->logs); - $logs = simplexml_load_string($logs); - foreach($logs->logentry as $entry) - { - $parsedLogs[] = $this->svn->convertLog($entry); - } - $parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array()); - foreach($parsedLogs as $log) - { - $objects = $this->svn->parseComment($log->msg); - if($objects) - { - $this->svn->saveAction2PMS($objects, $log, $repoRoot); - if($objects['stories']) $parsedObjects['stories'] = array_merge($parsedObjects['stories'], $objects['stories']); - if($objects['tasks']) $parsedObjects['tasks' ] = array_merge($parsedObjects['tasks'], $objects['tasks']); - if($objects['bugs']) $parsedObjects['bugs'] = array_merge($parsedObjects['bugs'], $objects['bugs']); - } - } - $parsedObjects['stories'] = array_unique($parsedObjects['stories']); - $parsedObjects['tasks'] = array_unique($parsedObjects['tasks']); - $parsedObjects['bugs'] = array_unique($parsedObjects['bugs']); - $this->view->parsedObjects = $parsedObjects; - $this->display(); - exit; - } - } -} + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +class svn extends control +{ + /** + * Sync svn. + * + * @access public + * @return void + */ + public function run() + { + $this->svn->run(); + } + + /** + * Diff a file. + * + * @param string $url + * @param int $revision + * @access public + * @return void + */ + public function diff($url, $revision) + { + $url = helper::safe64Decode($url); + $this->view->url = $url; + $this->view->revision = $revision; + $this->view->diff = $this->svn->diff($url, $revision); + + $this->display(); + } + + /** + * Cat a file. + * + * @param string $url + * @param int $revision + * @access public + * @return void + */ + public function cat($url, $revision) + { + $url = helper::safe64Decode($url); + $this->view->url = $url; + $this->view->revision = $revision; + $this->view->code = $this->svn->cat($url, $revision); + + $this->display(); + } + + /** + * Sync from the syncer by api. + * + * @access public + * @return void + */ + public function apiSync() + { + if($this->post->logs) + { + $repoRoot = $this->post->repoRoot; + $logs = stripslashes($this->post->logs); + $logs = simplexml_load_string($logs); + foreach($logs->logentry as $entry) + { + $parsedLogs[] = $this->svn->convertLog($entry); + } + $parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array()); + foreach($parsedLogs as $log) + { + $objects = $this->svn->parseComment($log->msg); + if($objects) + { + $this->svn->saveAction2PMS($objects, $log, $repoRoot); + if($objects['stories']) $parsedObjects['stories'] = array_merge($parsedObjects['stories'], $objects['stories']); + if($objects['tasks']) $parsedObjects['tasks' ] = array_merge($parsedObjects['tasks'], $objects['tasks']); + if($objects['bugs']) $parsedObjects['bugs'] = array_merge($parsedObjects['bugs'], $objects['bugs']); + } + } + $parsedObjects['stories'] = array_unique($parsedObjects['stories']); + $parsedObjects['tasks'] = array_unique($parsedObjects['tasks']); + $parsedObjects['bugs'] = array_unique($parsedObjects['bugs']); + $this->view->parsedObjects = $parsedObjects; + $this->display(); + exit; + } + } +} diff --git a/module/svn/lang/en.php b/module/svn/lang/en.php index 514fe2749b..2071994f8d 100644 --- a/module/svn/lang/en.php +++ b/module/svn/lang/en.php @@ -1,16 +1,16 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -/* Methods. */ -$lang->svn->common = 'Subversion'; -$lang->svn->cat = 'View code'; -$lang->svn->diff = 'Diff code'; -$lang->svn->apiSync = 'API: sync svn log'; + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +/* Methods. */ +$lang->svn->common = 'Subversion'; +$lang->svn->cat = 'View code'; +$lang->svn->diff = 'Diff code'; +$lang->svn->apiSync = 'API: sync svn log'; diff --git a/module/svn/lang/zh-cn.php b/module/svn/lang/zh-cn.php index f25a1ce23c..5d265fb190 100644 --- a/module/svn/lang/zh-cn.php +++ b/module/svn/lang/zh-cn.php @@ -1,16 +1,16 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -/* 方法列表。*/ -$lang->svn->common = 'Subversion'; -$lang->svn->cat = '查看源代码'; -$lang->svn->diff = '比较源代码'; -$lang->svn->apiSync = '接口:同步svn日志'; + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +/* 方法列表。*/ +$lang->svn->common = 'Subversion'; +$lang->svn->cat = '查看源代码'; +$lang->svn->diff = '比较源代码'; +$lang->svn->apiSync = '接口:同步svn日志'; diff --git a/module/svn/lang/zh-tw.php b/module/svn/lang/zh-tw.php index b10275a7a2..980d0a55ba 100644 --- a/module/svn/lang/zh-tw.php +++ b/module/svn/lang/zh-tw.php @@ -1,16 +1,16 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -/* 方法列表。*/ -$lang->svn->common = 'Subversion'; -$lang->svn->cat = '查看原始碼'; -$lang->svn->diff = '比較原始碼'; -$lang->svn->apiSync = '介面:同步svn日誌'; + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +/* 方法列表。*/ +$lang->svn->common = 'Subversion'; +$lang->svn->cat = '查看原始碼'; +$lang->svn->diff = '比較原始碼'; +$lang->svn->apiSync = '介面:同步svn日誌'; diff --git a/module/svn/model.php b/module/svn/model.php index 9cb2c1122a..aafc5d56ed 100644 --- a/module/svn/model.php +++ b/module/svn/model.php @@ -1,634 +1,634 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -?> -loadModel('action'); - } - - /** - * Run. - * - * @access public - * @return void - */ - public function run() - { - $this->setRepos(); - $this->setLogRoot(); - $this->setRestartFile(); - - foreach($this->repos as $name => $repo) - { - $this->printLog("begin repo $name"); - $repo = (object)$repo; - $repo->name = $name; - $this->setRepo($repo); - - $savedRevision = $this->getSavedRevision(); - $this->printLog("start from revision $savedRevision"); - $logs = $this->getRepoLogs($repo, $savedRevision); - $this->printLog("get " . count($logs) . " logs"); - - $this->printLog('begin parsing logs'); - foreach($logs as $log) - { - $this->printLog("parsing log {$log->revision}"); - if($log->revision == $savedRevision) - { - $this->printLog("{$log->revision} alread parsed, ommit it"); - continue; - } - - $this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------"); - $objects = $this->parseComment($log->msg); - if($objects) - { - $this->printLog('extract' . - 'story:' . join(' ', $objects['stories']) . - ' task:' . join(' ', $objects['tasks']) . - ' bug:' . join(',', $objects['bugs'])); - - $this->saveAction2PMS($objects, $log); - } - else - { - $this->printLog('no objects found' . "\n"); - } - if($log->revision > $savedRevision) $savedRevision = $log->revision; - } - $this->saveLastRevision($savedRevision); - $this->printLog("save revision $savedRevision"); - $this->deleteRestartFile(); - $this->printLog("\n\nrepo $name finished"); - } - } - - /** - * Set the log root. - * - * @access public - * @return void - */ - public function setLogRoot() - { - $this->logRoot = $this->app->getTmpRoot() . 'svn/'; - if(!is_dir($this->logRoot)) mkdir($this->logRoot); - } - - /** - * Set the restart file. - * - * @access public - * @return void - */ - public function setRestartFile() - { - $this->restartFile = dirname(__FILE__) . '/restart'; - } - - /** - * Delete the restart file. - * - * @access public - * @return void - */ - public function deleteRestartFile() - { - if(is_file($this->restartFile)) unlink($this->restartFile); - } - - /** - * Set the repos. - * - * @access public - * @return void - */ - public function setRepos() - { - if(!$this->config->svn->repos) die("You must set one svn repo.\n"); - $this->repos = $this->config->svn->repos; - } - - /** - * Set repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setRepo($repo) - { - $this->setClient($repo); - $this->setLogFile($repo->name); - $this->setRepoRoot($repo); - } - - /** - * Set the svn binary client of a repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setClient($repo) - { - if($this->config->svn->client == '') die("You must set the svn client file.\n"); - $this->client = $this->config->svn->client . " --non-interactive"; - if(isset($repo->username)) $this->client .= " --username $repo->username --password $repo->password --no-auth-cache"; - } - - /** - * Set the log file of a repo. - * - * @param string $repoName - * @access public - * @return void - */ - public function setLogFile($repoName) - { - $this->logFile = $this->logRoot . $repoName; - } - - /** - * set the root path of a repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setRepoRoot($repo) - { - $cmd = $this->client . " info --xml $repo->path"; - $info = `$cmd`; - $info = simplexml_load_string($info); - $repoRoot = $info->entry->repository->root; - $this->repoRoot = $repoRoot; - } - - /** - * Get repo logs. - * - * @param object $repo - * @param int $fromRevision - * @access public - * @return array - */ - public function getRepoLogs($repo, $fromRevision) - { - $parsedLogs = array(); - - /* The svn log command. */ - $cmd = $this->client . " log -r $fromRevision:HEAD -v --xml $repo->path"; - $rawLogs = `$cmd`; - $logs = @simplexml_load_string($rawLogs); // Convert it to object. - if(!$logs) die("Some error occers: \nThe command is $cmd\n the svn logs is $rawLogs\n"); - - /* Process logs. */ - foreach($logs->logentry as $entry) $parsedLogs[] = $this->convertLog($entry); - return $parsedLogs; - } - - /** - * Convert log from xml format to object. - * - * @param object $log - * @access public - * @return ojbect - */ - public function convertLog($log) - { - /* Get author, revision, msg, date attributes. */ - $parsedLog = new stdClass(); - $parsedLog->author = (string)$log->author; - $parsedLog->revision = (int)$log['revision']; - $parsedLog->msg = trim((string)$log->msg); - $parsedLog->date = date('Y-m-d H:i:s', strtotime($log->date)); - - /* Process files. */ - $parsedLog->files = array(); - foreach ($log->paths as $key => $paths) - { - $parsedFiles = array(); - foreach($paths as $path) - { - $action = (string)$path['action']; - $parsedFiles[$action][] = (string)$path; - } - } - $parsedLog->files = $parsedFiles; - - return $parsedLog; - } - - /** - * Parse the comment of svn, extract object id list from it. - * - * @param string $comment - * @access public - * @return array - */ - public function parseComment($comment) - { - $stories = array(); - $tasks = array(); - $bugs = array(); - - // bug|story|task(case insensitive) + some space + #|:|:(Chinese) + id lists(maybe join with space or ,) - // $comment = "bug # 1,2,3,4 Bug:1 2 3 4 5 story:9999,1234566 story:456,1234566"; - $commonReg = "(?:\s){0,}(?:#|:|:){0,}([0-9, ]{1,})"; - $taskReg = '/task' . $commonReg . '/i'; - $storyReg = '/story' . $commonReg . '/i'; - $bugReg = '/bug' . $commonReg . '/i'; - - if(preg_match_all($storyReg, $comment, $result)) $stories = join(' ', $result[1]); - if(preg_match_all($taskReg, $comment, $result)) $tasks = join(' ', $result[1]); - if(preg_match_all($bugReg, $comment, $result)) $bugs = join(' ', $result[1]); - - if($stories) $stories = array_unique(explode(' ', str_replace(',', ' ', $stories))); - if($tasks) $tasks = array_unique(explode(' ', str_replace(',', ' ', $tasks))); - if($bugs) $bugs = array_unique(explode(' ', str_replace(',', ' ', $bugs))); - - if(!$stories and !$tasks and !$bugs) return array(); - return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs); - } - - /** - * Convert the comment to uft-8. - * - * @param string $comment - * @access public - * @return string - */ - public function iconvComment($comment) - { - /* Get encodings. */ - $encodings = str_replace(' ', '', trim($comment)); - if($encodings == '') return $comment; - $encodings = explode(',', $encodings); - - /* Try convert. */ - foreach($encodings as $encoding) - { - $result = @iconv($encoding, 'utf-8', $comment); - if($result) return $result; - } - - return $comment; - } - - /** - * Diff a url. - * - * @param string $url - * @param int $revision - * @access public - * @return string|bool - */ - public function diff($url, $revision) - { - $repo = $this->getRepoByURL($url); - if(!$repo) return false; - - $this->setClient($repo); - - $oldRevision = $revision - 1; - $cmd = $this->client . " diff --old=$url@$oldRevision --new=$url@$revision"; - $diff = `$cmd`; - return $diff; - } - - /** - * Cat a url. - * - * @param string $url - * @param int $revision - * @access public - * @return string|bool - */ - public function cat($url, $revision) - { - $repo = $this->getRepoByURL($url); - if(!$repo) return false; - - $this->setClient($repo); - - $cmd = $this->client . " cat $url@$revision"; - $code = `$cmd`; - return $code; - } - - /** - * Get repo by url. - * - * @param string $url - * @access public - * @return object|bool - */ - public function getRepoByURL($url) - { - foreach($this->config->svn->repos as $repo) if(strpos($url, $repo['path']) !== false) return (object)$repo; - return false; - } - - /** - * Save action to pms. - * - * @param array $objects - * @param object $log - * @param string $repoRoot - * @access public - * @return void - */ - public function saveAction2PMS($objects, $log, $repoRoot = '') - { - $action->actor = $log->author; - $action->action = 'svncommited'; - $action->date = $log->date; - $action->comment = $this->iconvComment($log->msg); - $action->extra = $log->revision; - - $changes = $this->createActionChanges($log, $repoRoot); - - if($objects['stories']) - { - $products = $this->getStoryProducts($objects['stories']); - foreach($objects['stories'] as $storyID) - { - $storyID = (int)$storyID; - if(!isset($products[$storyID])) continue; - - $action->objectType = 'story'; - $action->objectID = $storyID; - $action->product = $products[$storyID]; - $action->project = 0; - - $this->saveRecord($action, $changes); - } - } - - if($objects['tasks']) - { - $productsAndProjects = $this->getTaskProductsAndProjects($objects['tasks']); - foreach($objects['tasks'] as $taskID) - { - $taskID = (int)$taskID; - if(!isset($productsAndProjects[$taskID])) continue; - - $action->objectType = 'task'; - $action->objectID = $taskID; - $action->product = $productsAndProjects[$taskID]['product']; - $action->project = $productsAndProjects[$taskID]['project']; - - $this->saveRecord($action, $changes); - } - } - - if($objects['bugs']) - { - $productsAndProjects = $this->getBugProductsAndProjects($objects['bugs']); - - foreach($objects['bugs'] as $bugID) - { - $bugID = (int)$bugID; - if(!isset($productsAndProjects[$bugID])) continue; - - $action->objectType = 'bug'; - $action->objectID = $bugID; - $action->product = $productsAndProjects[$bugID]->product; - $action->project = $productsAndProjects[$bugID]->project; - - $this->saveRecord($action, $changes); - } - } - } - - /** - * Save an action to pms. - * - * @param object $action - * @param object $log - * @access public - * @return bool - */ - public function saveRecord($action, $changes) - { - $record = $this->dao->select('*')->from(TABLE_ACTION) - ->where('objectType')->eq($action->objectType) - ->andWhere('objectID')->eq($action->objectID) - ->andWhere('extra')->eq($action->extra) - ->andWhere('action')->eq('svncommited') - ->fetch(); - if($record) - { - $this->dao->update(TABLE_ACTION)->data($action)->where('id')->eq($record->id)->exec(); - if($changes) - { - $historyID = $this->dao->findByAction($record->id)->from(TABLE_HISTORY)->fetch('id'); - $this->dao->update(TABLE_HISTORY)->data($changes)->where('id')->eq($historyID)->exec(); - } - } - else - { - $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); - if($changes) - { - $actionID = $this->dao->lastInsertID(); - $this->action->logHistory($actionID, array($changes)); - } - } - } - - /** - * Create changes for action from a log. - * - * @param object $log - * @param string $repoRoot - * @access public - * @return array - */ - public function createActionChanges($log, $repoRoot) - { - if(!$log->files) return array(); - $diff = ''; - - $oldSelf = $this->server->PHP_SELF; - $this->server->set('PHP_SELF', $this->config->webRoot); - - if(!$repoRoot) $repoRoot = $this->repoRoot; - - foreach($log->files as $action => $actionFiles) - { - foreach($actionFiles as $file) - { - $param = array('url' => helper::safe64Encode($repoRoot . $file), 'revision' => $log->revision); - $catLink = trim(html::a(helper::createLink('svn', 'cat', $param, 'html'), 'view', '', "class='svnlink'")); - $diffLink = trim(html::a(helper::createLink('svn', 'diff', $param, 'html'), 'diff', '', "class='svnlink'")); - $diff .= $action . " " . $file . " $catLink "; - $diff .= $action == 'M' ? "$diffLink\n" : "\n" ; - } - } - $changes->field = 'subversion'; - $changes->old = ''; - $changes->new = ''; - $changes->diff = trim($diff); - - $this->server->set('PHP_SELF', $oldSelf); - return (array)$changes; - } - - /** - * Get products of stories. - * - * @param array $stories - * @access public - * @return array - */ - public function getStoryProducts($stories) - { - return $this->dao->select('id, product')->from(TABLE_STORY)->where('id')->in($stories)->fetchPairs(); - } - - /** - * Get products and projects of tasks. - * - * @param array $tasks - * @access public - * @return array - */ - public function getTaskProductsAndProjects($tasks) - { - $records = array(); - $products = $this->dao->select('t1.id, t2.product') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->where('t1.id')->in($tasks)->fetchPairs(); - - $projects = $this->dao->select('id, project')->from(TABLE_TASK)->where('id')->in($tasks)->fetchPairs(); - - foreach($projects as $taskID => $projectID) - { - $record = array(); - $record['project'] = $projectID; - $record['product'] = isset($products[$taskID]) ? $products[$taskID] : 0; - $records[$taskID] = $record; - } - return $records; - } - - /** - * Get products and projects of bugs. - * - * @param array $bugs - * @access public - * @return array - */ - public function getBugProductsAndProjects($bugs) - { - return $this->dao->select('id, project, product')->from(TABLE_BUG)->where('id')->in($bugs)->fetchAll('id'); - } - - /** - * Get the saved revision. - * - * @access public - * @return int - */ - public function getSavedRevision() - { - if(!file_exists($this->logFile)) return 0; - if(file_exists($this->restartFile)) return 0; - return (int)trim(file_get_contents($this->logFile)); - } - - /** - * Save the last revision. - * - * @param int $revision - * @access public - * @return void - */ - public function saveLastRevision($revision) - { - file_put_contents($this->logFile, $revision); - } - - /** - * Pring log. - * - * @param sting $log - * @access public - * @return void - */ - public function printLog($log) - { - echo helper::now() . " $log\n"; - } -} + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('action'); + } + + /** + * Run. + * + * @access public + * @return void + */ + public function run() + { + $this->setRepos(); + $this->setLogRoot(); + $this->setRestartFile(); + + foreach($this->repos as $name => $repo) + { + $this->printLog("begin repo $name"); + $repo = (object)$repo; + $repo->name = $name; + $this->setRepo($repo); + + $savedRevision = $this->getSavedRevision(); + $this->printLog("start from revision $savedRevision"); + $logs = $this->getRepoLogs($repo, $savedRevision); + $this->printLog("get " . count($logs) . " logs"); + + $this->printLog('begin parsing logs'); + foreach($logs as $log) + { + $this->printLog("parsing log {$log->revision}"); + if($log->revision == $savedRevision) + { + $this->printLog("{$log->revision} alread parsed, ommit it"); + continue; + } + + $this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------"); + $objects = $this->parseComment($log->msg); + if($objects) + { + $this->printLog('extract' . + 'story:' . join(' ', $objects['stories']) . + ' task:' . join(' ', $objects['tasks']) . + ' bug:' . join(',', $objects['bugs'])); + + $this->saveAction2PMS($objects, $log); + } + else + { + $this->printLog('no objects found' . "\n"); + } + if($log->revision > $savedRevision) $savedRevision = $log->revision; + } + $this->saveLastRevision($savedRevision); + $this->printLog("save revision $savedRevision"); + $this->deleteRestartFile(); + $this->printLog("\n\nrepo $name finished"); + } + } + + /** + * Set the log root. + * + * @access public + * @return void + */ + public function setLogRoot() + { + $this->logRoot = $this->app->getTmpRoot() . 'svn/'; + if(!is_dir($this->logRoot)) mkdir($this->logRoot); + } + + /** + * Set the restart file. + * + * @access public + * @return void + */ + public function setRestartFile() + { + $this->restartFile = dirname(__FILE__) . '/restart'; + } + + /** + * Delete the restart file. + * + * @access public + * @return void + */ + public function deleteRestartFile() + { + if(is_file($this->restartFile)) unlink($this->restartFile); + } + + /** + * Set the repos. + * + * @access public + * @return void + */ + public function setRepos() + { + if(!$this->config->svn->repos) die("You must set one svn repo.\n"); + $this->repos = $this->config->svn->repos; + } + + /** + * Set repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepo($repo) + { + $this->setClient($repo); + $this->setLogFile($repo->name); + $this->setRepoRoot($repo); + } + + /** + * Set the svn binary client of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setClient($repo) + { + if($this->config->svn->client == '') die("You must set the svn client file.\n"); + $this->client = $this->config->svn->client . " --non-interactive"; + if(isset($repo->username)) $this->client .= " --username $repo->username --password $repo->password --no-auth-cache"; + } + + /** + * Set the log file of a repo. + * + * @param string $repoName + * @access public + * @return void + */ + public function setLogFile($repoName) + { + $this->logFile = $this->logRoot . $repoName; + } + + /** + * set the root path of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepoRoot($repo) + { + $cmd = $this->client . " info --xml $repo->path"; + $info = `$cmd`; + $info = simplexml_load_string($info); + $repoRoot = $info->entry->repository->root; + $this->repoRoot = $repoRoot; + } + + /** + * Get repo logs. + * + * @param object $repo + * @param int $fromRevision + * @access public + * @return array + */ + public function getRepoLogs($repo, $fromRevision) + { + $parsedLogs = array(); + + /* The svn log command. */ + $cmd = $this->client . " log -r $fromRevision:HEAD -v --xml $repo->path"; + $rawLogs = `$cmd`; + $logs = @simplexml_load_string($rawLogs); // Convert it to object. + if(!$logs) die("Some error occers: \nThe command is $cmd\n the svn logs is $rawLogs\n"); + + /* Process logs. */ + foreach($logs->logentry as $entry) $parsedLogs[] = $this->convertLog($entry); + return $parsedLogs; + } + + /** + * Convert log from xml format to object. + * + * @param object $log + * @access public + * @return ojbect + */ + public function convertLog($log) + { + /* Get author, revision, msg, date attributes. */ + $parsedLog = new stdClass(); + $parsedLog->author = (string)$log->author; + $parsedLog->revision = (int)$log['revision']; + $parsedLog->msg = trim((string)$log->msg); + $parsedLog->date = date('Y-m-d H:i:s', strtotime($log->date)); + + /* Process files. */ + $parsedLog->files = array(); + foreach ($log->paths as $key => $paths) + { + $parsedFiles = array(); + foreach($paths as $path) + { + $action = (string)$path['action']; + $parsedFiles[$action][] = (string)$path; + } + } + $parsedLog->files = $parsedFiles; + + return $parsedLog; + } + + /** + * Parse the comment of svn, extract object id list from it. + * + * @param string $comment + * @access public + * @return array + */ + public function parseComment($comment) + { + $stories = array(); + $tasks = array(); + $bugs = array(); + + // bug|story|task(case insensitive) + some space + #|:|:(Chinese) + id lists(maybe join with space or ,) + // $comment = "bug # 1,2,3,4 Bug:1 2 3 4 5 story:9999,1234566 story:456,1234566"; + $commonReg = "(?:\s){0,}(?:#|:|:){0,}([0-9, ]{1,})"; + $taskReg = '/task' . $commonReg . '/i'; + $storyReg = '/story' . $commonReg . '/i'; + $bugReg = '/bug' . $commonReg . '/i'; + + if(preg_match_all($storyReg, $comment, $result)) $stories = join(' ', $result[1]); + if(preg_match_all($taskReg, $comment, $result)) $tasks = join(' ', $result[1]); + if(preg_match_all($bugReg, $comment, $result)) $bugs = join(' ', $result[1]); + + if($stories) $stories = array_unique(explode(' ', str_replace(',', ' ', $stories))); + if($tasks) $tasks = array_unique(explode(' ', str_replace(',', ' ', $tasks))); + if($bugs) $bugs = array_unique(explode(' ', str_replace(',', ' ', $bugs))); + + if(!$stories and !$tasks and !$bugs) return array(); + return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs); + } + + /** + * Convert the comment to uft-8. + * + * @param string $comment + * @access public + * @return string + */ + public function iconvComment($comment) + { + /* Get encodings. */ + $encodings = str_replace(' ', '', trim($comment)); + if($encodings == '') return $comment; + $encodings = explode(',', $encodings); + + /* Try convert. */ + foreach($encodings as $encoding) + { + $result = @iconv($encoding, 'utf-8', $comment); + if($result) return $result; + } + + return $comment; + } + + /** + * Diff a url. + * + * @param string $url + * @param int $revision + * @access public + * @return string|bool + */ + public function diff($url, $revision) + { + $repo = $this->getRepoByURL($url); + if(!$repo) return false; + + $this->setClient($repo); + + $oldRevision = $revision - 1; + $cmd = $this->client . " diff --old=$url@$oldRevision --new=$url@$revision"; + $diff = `$cmd`; + return $diff; + } + + /** + * Cat a url. + * + * @param string $url + * @param int $revision + * @access public + * @return string|bool + */ + public function cat($url, $revision) + { + $repo = $this->getRepoByURL($url); + if(!$repo) return false; + + $this->setClient($repo); + + $cmd = $this->client . " cat $url@$revision"; + $code = `$cmd`; + return $code; + } + + /** + * Get repo by url. + * + * @param string $url + * @access public + * @return object|bool + */ + public function getRepoByURL($url) + { + foreach($this->config->svn->repos as $repo) if(strpos($url, $repo['path']) !== false) return (object)$repo; + return false; + } + + /** + * Save action to pms. + * + * @param array $objects + * @param object $log + * @param string $repoRoot + * @access public + * @return void + */ + public function saveAction2PMS($objects, $log, $repoRoot = '') + { + $action->actor = $log->author; + $action->action = 'svncommited'; + $action->date = $log->date; + $action->comment = $this->iconvComment($log->msg); + $action->extra = $log->revision; + + $changes = $this->createActionChanges($log, $repoRoot); + + if($objects['stories']) + { + $products = $this->getStoryProducts($objects['stories']); + foreach($objects['stories'] as $storyID) + { + $storyID = (int)$storyID; + if(!isset($products[$storyID])) continue; + + $action->objectType = 'story'; + $action->objectID = $storyID; + $action->product = $products[$storyID]; + $action->project = 0; + + $this->saveRecord($action, $changes); + } + } + + if($objects['tasks']) + { + $productsAndProjects = $this->getTaskProductsAndProjects($objects['tasks']); + foreach($objects['tasks'] as $taskID) + { + $taskID = (int)$taskID; + if(!isset($productsAndProjects[$taskID])) continue; + + $action->objectType = 'task'; + $action->objectID = $taskID; + $action->product = $productsAndProjects[$taskID]['product']; + $action->project = $productsAndProjects[$taskID]['project']; + + $this->saveRecord($action, $changes); + } + } + + if($objects['bugs']) + { + $productsAndProjects = $this->getBugProductsAndProjects($objects['bugs']); + + foreach($objects['bugs'] as $bugID) + { + $bugID = (int)$bugID; + if(!isset($productsAndProjects[$bugID])) continue; + + $action->objectType = 'bug'; + $action->objectID = $bugID; + $action->product = $productsAndProjects[$bugID]->product; + $action->project = $productsAndProjects[$bugID]->project; + + $this->saveRecord($action, $changes); + } + } + } + + /** + * Save an action to pms. + * + * @param object $action + * @param object $log + * @access public + * @return bool + */ + public function saveRecord($action, $changes) + { + $record = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectType')->eq($action->objectType) + ->andWhere('objectID')->eq($action->objectID) + ->andWhere('extra')->eq($action->extra) + ->andWhere('action')->eq('svncommited') + ->fetch(); + if($record) + { + $this->dao->update(TABLE_ACTION)->data($action)->where('id')->eq($record->id)->exec(); + if($changes) + { + $historyID = $this->dao->findByAction($record->id)->from(TABLE_HISTORY)->fetch('id'); + $this->dao->update(TABLE_HISTORY)->data($changes)->where('id')->eq($historyID)->exec(); + } + } + else + { + $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); + if($changes) + { + $actionID = $this->dao->lastInsertID(); + $this->action->logHistory($actionID, array($changes)); + } + } + } + + /** + * Create changes for action from a log. + * + * @param object $log + * @param string $repoRoot + * @access public + * @return array + */ + public function createActionChanges($log, $repoRoot) + { + if(!$log->files) return array(); + $diff = ''; + + $oldSelf = $this->server->PHP_SELF; + $this->server->set('PHP_SELF', $this->config->webRoot); + + if(!$repoRoot) $repoRoot = $this->repoRoot; + + foreach($log->files as $action => $actionFiles) + { + foreach($actionFiles as $file) + { + $param = array('url' => helper::safe64Encode($repoRoot . $file), 'revision' => $log->revision); + $catLink = trim(html::a(helper::createLink('svn', 'cat', $param, 'html'), 'view', '', "class='svnlink'")); + $diffLink = trim(html::a(helper::createLink('svn', 'diff', $param, 'html'), 'diff', '', "class='svnlink'")); + $diff .= $action . " " . $file . " $catLink "; + $diff .= $action == 'M' ? "$diffLink\n" : "\n" ; + } + } + $changes->field = 'subversion'; + $changes->old = ''; + $changes->new = ''; + $changes->diff = trim($diff); + + $this->server->set('PHP_SELF', $oldSelf); + return (array)$changes; + } + + /** + * Get products of stories. + * + * @param array $stories + * @access public + * @return array + */ + public function getStoryProducts($stories) + { + return $this->dao->select('id, product')->from(TABLE_STORY)->where('id')->in($stories)->fetchPairs(); + } + + /** + * Get products and projects of tasks. + * + * @param array $tasks + * @access public + * @return array + */ + public function getTaskProductsAndProjects($tasks) + { + $records = array(); + $products = $this->dao->select('t1.id, t2.product') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where('t1.id')->in($tasks)->fetchPairs(); + + $projects = $this->dao->select('id, project')->from(TABLE_TASK)->where('id')->in($tasks)->fetchPairs(); + + foreach($projects as $taskID => $projectID) + { + $record = array(); + $record['project'] = $projectID; + $record['product'] = isset($products[$taskID]) ? $products[$taskID] : 0; + $records[$taskID] = $record; + } + return $records; + } + + /** + * Get products and projects of bugs. + * + * @param array $bugs + * @access public + * @return array + */ + public function getBugProductsAndProjects($bugs) + { + return $this->dao->select('id, project, product')->from(TABLE_BUG)->where('id')->in($bugs)->fetchAll('id'); + } + + /** + * Get the saved revision. + * + * @access public + * @return int + */ + public function getSavedRevision() + { + if(!file_exists($this->logFile)) return 0; + if(file_exists($this->restartFile)) return 0; + return (int)trim(file_get_contents($this->logFile)); + } + + /** + * Save the last revision. + * + * @param int $revision + * @access public + * @return void + */ + public function saveLastRevision($revision) + { + file_put_contents($this->logFile, $revision); + } + + /** + * Pring log. + * + * @param sting $log + * @access public + * @return void + */ + public function printLog($log) + { + echo helper::now() . " $log\n"; + } +} diff --git a/module/svn/syncer/syncer.php b/module/svn/syncer/syncer.php index 965fdfdd41..cbb9503b85 100644 --- a/module/svn/syncer/syncer.php +++ b/module/svn/syncer/syncer.php @@ -1,299 +1,299 @@ - - * @package svn - * @version $Id$ - * @link http://www.zentao.net - */ -error_reporting(E_ALL ^ E_STRICT ^ E_WARNING); - -include './config.php'; -include './api.class.php'; - -$syncer = new syncer($config); -$syncer->run(); - -class syncer -{ - /** - * The svn binary svnClient. - * - * @var string - * @access public - */ - public $svnClient; - - /** - * The zentao client. - * - * @var string - * @access public - */ - public $zentaoClient; - - /** - * Repos. - * - * @var array - * @access public - */ - public $repos = array(); - - /** - * The log root. - * - * @var string - * @access public - */ - public $logRoot = ''; - - /** - * The construct function. - * - * @access public - * @return void - */ - public function __construct($config) - { - $this->setConfig($config); - $this->setTimeZone(); - $this->setRepos(); - $this->setLogRoot(); - $this->loginZentao(); - } - - /** - * Set config. - * - * @param object $config - * @access public - * @return void - */ - public function setConfig($config) - { - $this->config = $config; - } - - /** - * Set timezone. - * - * @access public - * @return void - */ - public function setTimeZone() - { - date_default_timezone_set($this->config->timezone); - } - - /** - * Set the repos. - * - * @access public - * @return void - */ - public function setRepos() - { - if(!$this->config->svn->repos) die("You must set one svn repo.\n"); - $this->repos = $this->config->svn->repos; - } - - /** - * Set the log root. - * - * @access public - * @return void - */ - public function setLogRoot() - { - $this->logRoot = './log/'; - if(!is_dir($this->logRoot)) mkdir($this->logRoot); - } - - /** - * Login to zentao. - * - * @access public - * @return void - */ - public function loginZentao() - { - if(!$this->config->zentao->path or !$this->config->zentao->user) die("You must set the zentao path and user.\n"); - $zentaoConfig = $this->config->zentao; - $this->zentaoClient = new ztclient($zentaoConfig->path, $zentaoConfig->user, $zentaoConfig->password); - } - - /** - * Run. - * - * @access public - * @return void - */ - public function run() - { - while(true) - { - foreach($this->repos as $name => $repo) - { - $this->printLog("begin repo $name"); - $repo = (object)$repo; - $repo->name = $name; - - $this->setRepo($repo); - - $savedRevision = $this->getSavedRevision(); - $this->printLog("start from revision $savedRevision"); - $logs = $this->getRepoLogs($repo, $savedRevision); - $revisions = $this->getRevisionsFromLogs($logs); - if(!$revisions) - { - $this->printLog("no logs"); - continue; - } - $this->printLog('fetched ' . count($revisions) . ' logs'); - - $this->printLog('begin posting logs'); - $objects = $this->zentaoClient->post('svn', 'apiSync', array('logs' => $logs, 'repoRoot' => $this->repoRoot)); - $objects = $objects->parsedObjects; - - $this->printLog('parsed objects:'); - echo 'story: ' . join(',', (array)$objects->stories) . "\n"; - echo 'task: ' . join(',', (array)$objects->tasks) . "\n"; - echo 'bugs: ' . join(',', (array)$objects->bugs) . "\n"; - - $this->saveLastRevision(max($revisions)); - echo "----------------------\n"; - } - $this->printLog("sleeping {$this->config->sleep} seconds"); - sleep($this->config->sleep); - } - } - - /** - * Set repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setRepo($repo) - { - $this->setClient($repo); - $this->setLogFile($repo->name); - $this->setRepoRoot($repo); - } - - /** - * Set the svn binary svnClient of a repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setClient($repo) - { - if($this->config->svn->client == '') die("You must set the svn svnClient file.\n"); - $this->svnClient = $this->config->svn->client . " --non-interactive"; - if(isset($repo->username)) $this->svnClient .= " --username $repo->username --password $repo->password --no-auth-cache"; - } - - /** - * Set the log file of a repo. - * - * @param string $repoName - * @access public - * @return void - */ - public function setLogFile($repoName) - { - $this->logFile = $this->logRoot . $repoName; - } - - /** - * set the root path of a repo. - * - * @param object $repo - * @access public - * @return void - */ - public function setRepoRoot($repo) - { - $cmd = $this->svnClient . " info --xml $repo->path"; - $info = `$cmd`; - $info = simplexml_load_string($info); - $repoRoot = (string)$info->entry->repository->root; - $this->repoRoot = $repoRoot; - } - - /** - * Get repo logs. - * - * @param object $repo - * @param int $fromRevision - * @access public - * @return string - */ - public function getRepoLogs($repo, $fromRevision) - { - $parsedLogs = array(); - - /* The svn log command. */ - $cmd = $this->svnClient . " log -r $fromRevision:HEAD -v --xml $repo->path"; - $logs = `$cmd`; - - return $logs; - } - - /** - * Get the saved revision. - * - * @access public - * @return int - */ - public function getSavedRevision() - { - if(!file_exists($this->logFile)) return 0; - return (int)trim(file_get_contents($this->logFile)); - } - - /** - * Get revisons from logs. - * - * @param string $logs - * @access public - * @return array|bool - */ - public function getRevisionsFromLogs($logs) - { - if(!preg_match_all('|revision="(.*)"|', $logs, $results)) return false; - $revisions = $results[1]; - return $revisions; - } - - /** - * Save the last revision. - * - * @param int $revision - * @access public - * @return void - */ - public function saveLastRevision($revision) - { - file_put_contents($this->logFile, $revision); - } - - /** - * Pring log. - * - * @param sting $log - * @access public - * @return void - */ - public function printLog($log) - { - echo date('Y-m-d H:i:s') . " $log\n"; - } -} + + * @package svn + * @version $Id$ + * @link http://www.zentao.net + */ +error_reporting(E_ALL ^ E_STRICT ^ E_WARNING); + +include './config.php'; +include './api.class.php'; + +$syncer = new syncer($config); +$syncer->run(); + +class syncer +{ + /** + * The svn binary svnClient. + * + * @var string + * @access public + */ + public $svnClient; + + /** + * The zentao client. + * + * @var string + * @access public + */ + public $zentaoClient; + + /** + * Repos. + * + * @var array + * @access public + */ + public $repos = array(); + + /** + * The log root. + * + * @var string + * @access public + */ + public $logRoot = ''; + + /** + * The construct function. + * + * @access public + * @return void + */ + public function __construct($config) + { + $this->setConfig($config); + $this->setTimeZone(); + $this->setRepos(); + $this->setLogRoot(); + $this->loginZentao(); + } + + /** + * Set config. + * + * @param object $config + * @access public + * @return void + */ + public function setConfig($config) + { + $this->config = $config; + } + + /** + * Set timezone. + * + * @access public + * @return void + */ + public function setTimeZone() + { + date_default_timezone_set($this->config->timezone); + } + + /** + * Set the repos. + * + * @access public + * @return void + */ + public function setRepos() + { + if(!$this->config->svn->repos) die("You must set one svn repo.\n"); + $this->repos = $this->config->svn->repos; + } + + /** + * Set the log root. + * + * @access public + * @return void + */ + public function setLogRoot() + { + $this->logRoot = './log/'; + if(!is_dir($this->logRoot)) mkdir($this->logRoot); + } + + /** + * Login to zentao. + * + * @access public + * @return void + */ + public function loginZentao() + { + if(!$this->config->zentao->path or !$this->config->zentao->user) die("You must set the zentao path and user.\n"); + $zentaoConfig = $this->config->zentao; + $this->zentaoClient = new ztclient($zentaoConfig->path, $zentaoConfig->user, $zentaoConfig->password); + } + + /** + * Run. + * + * @access public + * @return void + */ + public function run() + { + while(true) + { + foreach($this->repos as $name => $repo) + { + $this->printLog("begin repo $name"); + $repo = (object)$repo; + $repo->name = $name; + + $this->setRepo($repo); + + $savedRevision = $this->getSavedRevision(); + $this->printLog("start from revision $savedRevision"); + $logs = $this->getRepoLogs($repo, $savedRevision); + $revisions = $this->getRevisionsFromLogs($logs); + if(!$revisions) + { + $this->printLog("no logs"); + continue; + } + $this->printLog('fetched ' . count($revisions) . ' logs'); + + $this->printLog('begin posting logs'); + $objects = $this->zentaoClient->post('svn', 'apiSync', array('logs' => $logs, 'repoRoot' => $this->repoRoot)); + $objects = $objects->parsedObjects; + + $this->printLog('parsed objects:'); + echo 'story: ' . join(',', (array)$objects->stories) . "\n"; + echo 'task: ' . join(',', (array)$objects->tasks) . "\n"; + echo 'bugs: ' . join(',', (array)$objects->bugs) . "\n"; + + $this->saveLastRevision(max($revisions)); + echo "----------------------\n"; + } + $this->printLog("sleeping {$this->config->sleep} seconds"); + sleep($this->config->sleep); + } + } + + /** + * Set repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepo($repo) + { + $this->setClient($repo); + $this->setLogFile($repo->name); + $this->setRepoRoot($repo); + } + + /** + * Set the svn binary svnClient of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setClient($repo) + { + if($this->config->svn->client == '') die("You must set the svn svnClient file.\n"); + $this->svnClient = $this->config->svn->client . " --non-interactive"; + if(isset($repo->username)) $this->svnClient .= " --username $repo->username --password $repo->password --no-auth-cache"; + } + + /** + * Set the log file of a repo. + * + * @param string $repoName + * @access public + * @return void + */ + public function setLogFile($repoName) + { + $this->logFile = $this->logRoot . $repoName; + } + + /** + * set the root path of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepoRoot($repo) + { + $cmd = $this->svnClient . " info --xml $repo->path"; + $info = `$cmd`; + $info = simplexml_load_string($info); + $repoRoot = (string)$info->entry->repository->root; + $this->repoRoot = $repoRoot; + } + + /** + * Get repo logs. + * + * @param object $repo + * @param int $fromRevision + * @access public + * @return string + */ + public function getRepoLogs($repo, $fromRevision) + { + $parsedLogs = array(); + + /* The svn log command. */ + $cmd = $this->svnClient . " log -r $fromRevision:HEAD -v --xml $repo->path"; + $logs = `$cmd`; + + return $logs; + } + + /** + * Get the saved revision. + * + * @access public + * @return int + */ + public function getSavedRevision() + { + if(!file_exists($this->logFile)) return 0; + return (int)trim(file_get_contents($this->logFile)); + } + + /** + * Get revisons from logs. + * + * @param string $logs + * @access public + * @return array|bool + */ + public function getRevisionsFromLogs($logs) + { + if(!preg_match_all('|revision="(.*)"|', $logs, $results)) return false; + $revisions = $results[1]; + return $revisions; + } + + /** + * Save the last revision. + * + * @param int $revision + * @access public + * @return void + */ + public function saveLastRevision($revision) + { + file_put_contents($this->logFile, $revision); + } + + /** + * Pring log. + * + * @param sting $log + * @access public + * @return void + */ + public function printLog($log) + { + echo date('Y-m-d H:i:s') . " $log\n"; + } +} diff --git a/module/svn/view/cat.html.php b/module/svn/view/cat.html.php index a169548170..9233839927 100644 --- a/module/svn/view/cat.html.php +++ b/module/svn/view/cat.html.php @@ -1,16 +1,16 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          <?php echo $code;?>
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          <?php echo $code;?>
          + diff --git a/module/svn/view/diff.html.php b/module/svn/view/diff.html.php index 36a74cc9a0..b901bd3332 100644 --- a/module/svn/view/diff.html.php +++ b/module/svn/view/diff.html.php @@ -1,17 +1,17 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          <?php echo $diff;?>
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          <?php echo $diff;?>
          + diff --git a/module/task/control.php b/module/task/control.php index 4abdf63f2d..c85ab26d1a 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -1,730 +1,730 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -class task extends control -{ - /** - * Construct function, load model of project and story modules. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('project'); - $this->loadModel('story'); - } - - /** - * Create a task. - * - * @param int $projectID - * @param int $storyID - * @access public - * @return void - */ - public function create($projectID = 0, $storyID = 0) - { - $project = $this->project->getById($projectID); - $taskLink = $this->createLink('project', 'browse', "projectID=$projectID&tab=task"); - $storyLink = $this->session->storyList ? $this->session->storyList : $this->createLink('project', 'story', "projectID=$projectID"); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - - /* Set menu. */ - $this->project->setMenu($this->project->getPairs(), $project->id); - - if(!empty($_POST)) - { - $tasksID = $this->task->create($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - /* Create actions. */ - $this->loadModel('action'); - foreach($tasksID as $taskID) - { - $actionID = $this->action->create('task', $taskID, 'Opened', ''); - $this->sendmail($taskID, $actionID); - } - - /* Locate the browser. */ - if($this->post->after == 'continueAdding') - { - echo js::alert($this->lang->task->successSaved . $this->lang->task->afterChoices['continueAdding']); - die(js::locate($this->createLink('task', 'create', "projectID=$projectID&storyID={$this->post->story}"), 'parent')); - } - elseif($this->post->after == 'toTastList') - { - die(js::locate($taskLink, 'parent')); - } - elseif($this->post->after == 'toStoryList') - { - die(js::locate($storyLink, 'parent')); - } - } - - $stories = $this->story->getProjectStoryPairs($projectID); - $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); - $header['title'] = $project->name . $this->lang->colon . $this->lang->task->create; - $position[] = html::a($taskLink, $project->name); - $position[] = $this->lang->task->create; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->project = $project; - $this->view->stories = $stories; - $this->view->storyID = $storyID; - $this->view->members = $members; - $this->display(); - } - - /** - * Create a task. - * - * @param int $projectID - * @param int $storyID - * @access public - * @return void - */ - public function batchCreate($projectID = 0, $storyID = 0) - { - $project = $this->project->getById($projectID); - $taskLink = $this->createLink('project', 'browse', "projectID=$projectID&tab=task"); - $storyLink = $this->session->storyList ? $this->session->storyList : $this->createLink('project', 'story', "projectID=$projectID"); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - - /* Set menu. */ - $this->project->setMenu($this->project->getPairs(), $project->id); - - if(!empty($_POST)) - { - $mails = $this->task->batchCreate($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - foreach($mails as $mail) - { - $this->sendmail($mail->taskID, $mail->actionID); - } - - /* Locate the browser. */ - die(js::locate($taskLink, 'parent')); - } - - $stories = $this->story->getProjectStoryPairs($projectID); - $stories['same'] = $this->lang->task->same; - $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); - $header['title'] = $project->name . $this->lang->colon . $this->lang->task->create; - $position[] = html::a($taskLink, $project->name); - $position[] = $this->lang->task->create; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->project = $project; - $this->view->stories = $stories; - $this->view->storyID = $storyID; - $this->view->members = $members; - $this->display(); - } - - /** - * Common actions of task module. - * - * @param int $taskID - * @access public - * @return void - */ - public function commonAction($taskID) - { - $this->view->task = $this->loadModel('task')->getByID($taskID); - $this->view->project = $this->project->getById($this->view->task->project); - $this->view->members = $this->project->getTeamMemberPairs($this->view->project->id ,'nodeleted'); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->actions = $this->loadModel('action')->getList('task', $taskID); - - /* Set menu. */ - $this->project->setMenu($this->project->getPairs(), $this->view->project->id); - $this->view->position[] = html::a($this->createLink('project', 'browse', "project={$this->view->task->project}"), $this->view->project->name); - - } - - /** - * Edit a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function edit($taskID, $comment = false) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = array(); - $files = array(); - if($comment == false) - { - $changes = $this->task->update($taskID); - if(dao::isError()) die(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('task', $taskID); - } - - $task = $this->task->getById($taskID); - if($this->post->comment != '' or !empty($changes) or !empty($files)) - { - $action = !empty($changes) ? 'Edited' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; - $actionID = $this->action->create('task', $taskID, $action, $fileAction . $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - - if($task->fromBug != 0) - { - foreach($changes as $change) - { - if($change['field'] == 'status') - { - $confirmURL = $this->createLink('bug', 'view', "id=$task->fromBug"); - $cancelURL = $this->server->HTTP_REFERER; - die(js::confirm(sprintf($this->lang->task->remindBug, $task->fromBug), $confirmURL, $cancelURL, 'parent', 'parent')); - } - } - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->lang->task->edit; - $this->view->position[] = $this->lang->task->edit; - $this->view->stories = $this->story->getProjectStoryPairs($this->view->project->id); - $this->view->members = $this->loadModel('user')->appendDeleted($this->view->members, $this->view->task->assignedTo); - - $this->display(); - } - - /** - * Update assign of task - * - * @param int $requestID - * @access public - * @return void - */ - public function assignTo($projectID, $taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $actionID = $this->task->assign($taskID); - if(dao::isError()) die(js::error(dao::getError())); - $this->sendmail($taskID, $actionID); - - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon . $this->lang->task->assign; - $this->view->position[] = $this->lang->task->assign; - - $this->view->users = $this->project->getTeamMemberPairs($projectID); - $this->display(); - } - - /** - * View a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function view($taskID) - { - $task = $this->task->getById($taskID); - if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Set menu. */ - $project = $this->project->getById($task->project); - $this->project->setMenu($this->project->getPairs(), $project->id); - - $header['title'] = $project->name . $this->lang->colon . $this->lang->task->view; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$task->project"), $project->name); - $position[] = $this->lang->task->view; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->project = $project; - $this->view->task = $task; - $this->view->actions = $this->loadModel('action')->getList('task', $taskID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Confirm story change - * - * @param int $taskID - * @access public - * @return void - */ - public function confirmStoryChange($taskID) - { - $task = $this->task->getById($taskID); - $this->dao->update(TABLE_TASK)->set('storyVersion')->eq($task->latestStoryVersion)->where('id')->eq($taskID)->exec(); - $this->loadModel('action')->create('task', $taskID, 'confirmed', '', $task->latestStoryVersion); - die(js::reload('parent')); - } - - /** - * Start a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function start($taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->task->start($taskID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('task', $taskID, 'Started', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->start; - $this->view->position[] = $this->lang->task->start; - $this->display(); - } - - /** - * Finish a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function finish($taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->task->finish($taskID); - if(dao::isError()) die(js::error(dao::getError())); - - $task = $this->task->getById($taskID); - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('task', $taskID, 'Finished', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - - if($task->fromBug != 0) - { - foreach($changes as $change) - { - if($change['field'] == 'status') - { - $confirmURL = $this->createLink('bug', 'view', "id=$task->fromBug"); - $cancelURL = $this->server->HTTP_REFERER; - die(js::confirm(sprintf($this->lang->task->remindBug, $task->fromBug), $confirmURL, $cancelURL, 'parent', 'parent')); - } - } - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->finish; - $this->view->position[] = $this->lang->task->finish; - - $this->display(); - } - - /** - * Close a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function close($taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->task->close($taskID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('task', $taskID, 'Closed', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->finish; - $this->view->position[] = $this->lang->task->finish; - - $this->display(); - - } - - /** - * Batch close tasks. - * - * @access public - * @return void - */ - public function batchClose() - { - if($this->post->tasks) - { - $tasks = $this->post->tasks; - unset($_POST['tasks']); - $this->loadModel('action'); - - foreach($tasks as $taskID) - { - $this->commonAction($taskID); - $task = $this->task->getById($taskID); - if($task->status == 'wait' or $task->status == 'doing') continue; - - $changes = $this->task->close($taskID); - - if($changes) - { - $actionID = $this->action->create('task', $taskID, 'Closed', ''); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - } - } - die(js::reload('parent')); - } - - /** - * Cancel a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function cancel($taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->task->cancel($taskID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('task', $taskID, 'Canceled', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->cancel; - $this->view->position[] = $this->lang->task->cancel; - - $this->display(); - } - - /** - * Activate a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function activate($taskID) - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->task->activate($taskID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('task', $taskID, 'Activated', $this->post->comment); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - } - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->activate; - $this->view->position[] = $this->lang->task->activate; - $this->display(); - } - - /** - * Delete a task. - * - * @param int $projectID - * @param int $taskID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($projectID, $taskID, $confirm = 'no') - { - $task = $this->task->getById($taskID); - if($confirm == 'no') - { - die(js::confirm($this->lang->task->confirmDelete, inlink('delete', "projectID=$projectID&taskID=$taskID&confirm=yes"))); - } - else - { - $story = $this->dao->select('story')->from(TABLE_TASK)->where('id')->eq($taskID)->fetch('story'); - $this->task->delete(TABLE_TASK, $taskID); - if($task->fromBug != 0) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($task->fromBug)->exec(); - if($story) $this->loadModel('story')->setStage($story); - die(js::locate($this->session->taskList, 'parent')); - } - } - - /** - * Send email. - * - * @param int $taskID - * @param int $actionID - * @access private - * @return void - */ - private function sendmail($taskID, $actionID) - { - /* Set toList and ccList. */ - $task = $this->task->getById($taskID); - $projectName = $this->project->getById($task->project)->name; - $toList = $task->assignedTo; - $ccList = trim($task->mailto, ','); - - if($toList == '') - { - if($ccList == '') return; - if(strpos($ccList, ',') === false) - { - $toList = $ccList; - $ccList = ''; - } - else - { - $commaPos = strpos($ccList, ','); - $toList = substr($ccList, 0, $commaPos); - $ccList = substr($ccList, $commaPos + 1); - } - } - elseif(strtolower($toList) == 'closed') - { - $toList = $task->finishedBy; - } - - /* Get action info. */ - $action = $this->loadModel('action')->getById($actionID); - $history = $this->action->getHistory($actionID); - $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); - - /* Create the email content. */ - $this->view->task = $task; - $this->view->action = $action; - $this->clear(); - $mailContent = $this->parse($this->moduleName, 'sendmail'); - - /* Send emails. */ - $this->loadModel('mail')->send($toList, $projectName . ':' . 'TASK#' . $task->id . $this->lang->colon . $task->name, $mailContent, $ccList); - if($this->mail->isError()) echo js::error($this->mail->getError()); - } - - /** - * AJAX: return tasks of a user in html select. - * - * @param string $account - * @param string $status - * @access public - * @return string - */ - public function ajaxGetUserTasks($account = '', $status = 'wait,doing') - { - if($account == '') $account = $this->app->user->account; - $tasks = $this->task->getUserTaskPairs($account, $status); - die(html::select('task', $tasks, '', 'class=select-1')); - } - - /** - * AJAX: return project tasks in html select. - * - * @param int $projectID - * @param int $taskID - * @access public - * @return string - */ - public function ajaxGetProjectTasks($projectID, $taskID = 0) - { - $tasks = $this->task->getProjectTaskPairs((int)$projectID); - die(html::select('task', $tasks, $taskID)); - } - - /** - * The report page. - * - * @param int $projectID - * @param string $browseType - * @access public - * @return void - */ - public function report($projectID, $browseType = 'all') - { - - $this->loadModel('report'); - $this->view->charts = array(); - $this->view->renderJS = ''; - - if(!empty($_POST)) - { - foreach($this->post->charts as $chart) - { - $chartFunc = 'getDataOf' . $chart; - $chartData = $this->task->$chartFunc(); - $chartOption = $this->lang->task->report->$chart; - $this->task->mergeChartOption($chart); - - $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); - $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); - $this->view->datas[$chart] = $this->report->computePercent($chartData); - } - $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); - } - - $this->project->setMenu($this->project->getPairs(), $projectID); - $this->projects = $this->project->getPairs(); - $this->view->header->title = $this->projects[$projectID] . $this->lang->colon . $this->lang->task->report->common; - $this->view->projectID = $projectID; - $this->view->browseType = $browseType; - $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; - - $this->display(); - } - - /** - * get data to export - * - * @param int $projectID - * @param string $orderBy - * @access public - * @return void - */ - public function export($projectID, $orderBy) - { - if($_POST) - { - $taskLang = $this->lang->task; - $taskConfig = $this->config->task; - - /* Create field lists. */ - $fields = explode(',', $taskConfig->exportFields); - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($taskLang->$fieldName) ? $taskLang->$fieldName : $fieldName; - unset($fields[$key]); - } - - /* Get tasks. */ - $tasks = $this->dao->select('*')->from(TABLE_TASK)->alias('t1')->where($this->session->taskReportCondition)->orderBy($orderBy)->fetchAll('id'); - - /* Get users and projects. */ - $users = $this->loadModel('user')->getPairs('noletter'); - $projects = $this->loadModel('project')->getPairs('all'); - - /* Get related objects id lists. */ - $relatedStoryIdList = array(); - foreach($tasks as $task) $relatedStoryIdList[$task->story] = $task->story; - - /* Get related objects title or names. */ - $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); - $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('task')->andWhere('objectID')->in(@array_keys($tasks))->fetchGroup('objectID'); - - foreach($tasks as $task) - { - if($this->post->fileType == 'csv') - { - $task->desc = htmlspecialchars_decode($task->desc); - $task->desc = str_replace("
          ", "\n", $task->desc); - $task->desc = str_replace('"', '""', $task->desc); - } - - /* fill some field with useful value. */ - $task->story = isset($relatedStories[$task->story]) ? $relatedStories[$task->story] : ''; - - if(isset($projects[$task->project])) $task->project = $projects[$task->project]; - if(isset($taskLang->typeList[$task->type])) $task->type = $taskLang->typeList[$task->type]; - if(isset($taskLang->priList[$task->pri])) $task->pri = $taskLang->priList[$task->pri]; - if(isset($taskLang->statusList[$task->status])) $task->status = $taskLang->statusList[$task->status]; - if(isset($taskLang->reasonList[$task->closedReason])) $task->closedReason = $taskLang->reasonList[$task->closedReason]; - - if(isset($users[$task->openedBy])) $task->openedBy = $users[$task->openedBy]; - if(isset($users[$task->assignedTo])) $task->assignedTo = $users[$task->assignedTo]; - if(isset($users[$task->finishedBy])) $task->finishedBy = $users[$task->finishedBy]; - if(isset($users[$task->canceledBy])) $task->canceledBy = $users[$task->canceledBy]; - if(isset($users[$task->closedBy])) $task->closedBy = $users[$task->closedBy]; - if(isset($users[$task->lastEditedBy])) $task->lastEditedBy = $users[$task->lastEditedBy]; - - $task->openedDate = substr($task->openedDate, 0, 10); - $task->assignedDate = substr($task->assignedDate, 0, 10); - $task->finishedDate = substr($task->finishedDate, 0, 10); - $task->canceledDate = substr($task->canceledDate, 0, 10); - $task->closedDate = substr($task->closedDate, 0, 10); - $task->lastEditedDate = substr($task->lastEditedDate, 0, 10); - - /* Set related files. */ - if(isset($relatedFiles[$task->id])) - { - foreach($relatedFiles[$task->id] as $file) - { - $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$task->company/" . $file->pathname; - $task->files .= html::a($fileURL, $file->title, '_blank') . '
          '; - } - } - } - - $this->post->set('fields', $fields); - $this->post->set('rows', $tasks); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +class task extends control +{ + /** + * Construct function, load model of project and story modules. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('project'); + $this->loadModel('story'); + } + + /** + * Create a task. + * + * @param int $projectID + * @param int $storyID + * @access public + * @return void + */ + public function create($projectID = 0, $storyID = 0) + { + $project = $this->project->getById($projectID); + $taskLink = $this->createLink('project', 'browse', "projectID=$projectID&tab=task"); + $storyLink = $this->session->storyList ? $this->session->storyList : $this->createLink('project', 'story', "projectID=$projectID"); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + + /* Set menu. */ + $this->project->setMenu($this->project->getPairs(), $project->id); + + if(!empty($_POST)) + { + $tasksID = $this->task->create($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + /* Create actions. */ + $this->loadModel('action'); + foreach($tasksID as $taskID) + { + $actionID = $this->action->create('task', $taskID, 'Opened', ''); + $this->sendmail($taskID, $actionID); + } + + /* Locate the browser. */ + if($this->post->after == 'continueAdding') + { + echo js::alert($this->lang->task->successSaved . $this->lang->task->afterChoices['continueAdding']); + die(js::locate($this->createLink('task', 'create', "projectID=$projectID&storyID={$this->post->story}"), 'parent')); + } + elseif($this->post->after == 'toTastList') + { + die(js::locate($taskLink, 'parent')); + } + elseif($this->post->after == 'toStoryList') + { + die(js::locate($storyLink, 'parent')); + } + } + + $stories = $this->story->getProjectStoryPairs($projectID); + $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + $header['title'] = $project->name . $this->lang->colon . $this->lang->task->create; + $position[] = html::a($taskLink, $project->name); + $position[] = $this->lang->task->create; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->project = $project; + $this->view->stories = $stories; + $this->view->storyID = $storyID; + $this->view->members = $members; + $this->display(); + } + + /** + * Create a task. + * + * @param int $projectID + * @param int $storyID + * @access public + * @return void + */ + public function batchCreate($projectID = 0, $storyID = 0) + { + $project = $this->project->getById($projectID); + $taskLink = $this->createLink('project', 'browse', "projectID=$projectID&tab=task"); + $storyLink = $this->session->storyList ? $this->session->storyList : $this->createLink('project', 'story', "projectID=$projectID"); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + + /* Set menu. */ + $this->project->setMenu($this->project->getPairs(), $project->id); + + if(!empty($_POST)) + { + $mails = $this->task->batchCreate($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + foreach($mails as $mail) + { + $this->sendmail($mail->taskID, $mail->actionID); + } + + /* Locate the browser. */ + die(js::locate($taskLink, 'parent')); + } + + $stories = $this->story->getProjectStoryPairs($projectID); + $stories['same'] = $this->lang->task->same; + $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + $header['title'] = $project->name . $this->lang->colon . $this->lang->task->create; + $position[] = html::a($taskLink, $project->name); + $position[] = $this->lang->task->create; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->project = $project; + $this->view->stories = $stories; + $this->view->storyID = $storyID; + $this->view->members = $members; + $this->display(); + } + + /** + * Common actions of task module. + * + * @param int $taskID + * @access public + * @return void + */ + public function commonAction($taskID) + { + $this->view->task = $this->loadModel('task')->getByID($taskID); + $this->view->project = $this->project->getById($this->view->task->project); + $this->view->members = $this->project->getTeamMemberPairs($this->view->project->id ,'nodeleted'); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->actions = $this->loadModel('action')->getList('task', $taskID); + + /* Set menu. */ + $this->project->setMenu($this->project->getPairs(), $this->view->project->id); + $this->view->position[] = html::a($this->createLink('project', 'browse', "project={$this->view->task->project}"), $this->view->project->name); + + } + + /** + * Edit a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function edit($taskID, $comment = false) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = array(); + $files = array(); + if($comment == false) + { + $changes = $this->task->update($taskID); + if(dao::isError()) die(js::error(dao::getError())); + $files = $this->loadModel('file')->saveUpload('task', $taskID); + } + + $task = $this->task->getById($taskID); + if($this->post->comment != '' or !empty($changes) or !empty($files)) + { + $action = !empty($changes) ? 'Edited' : 'Commented'; + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n" ; + $actionID = $this->action->create('task', $taskID, $action, $fileAction . $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + + if($task->fromBug != 0) + { + foreach($changes as $change) + { + if($change['field'] == 'status') + { + $confirmURL = $this->createLink('bug', 'view', "id=$task->fromBug"); + $cancelURL = $this->server->HTTP_REFERER; + die(js::confirm(sprintf($this->lang->task->remindBug, $task->fromBug), $confirmURL, $cancelURL, 'parent', 'parent')); + } + } + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->lang->task->edit; + $this->view->position[] = $this->lang->task->edit; + $this->view->stories = $this->story->getProjectStoryPairs($this->view->project->id); + $this->view->members = $this->loadModel('user')->appendDeleted($this->view->members, $this->view->task->assignedTo); + + $this->display(); + } + + /** + * Update assign of task + * + * @param int $requestID + * @access public + * @return void + */ + public function assignTo($projectID, $taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $actionID = $this->task->assign($taskID); + if(dao::isError()) die(js::error(dao::getError())); + $this->sendmail($taskID, $actionID); + + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon . $this->lang->task->assign; + $this->view->position[] = $this->lang->task->assign; + + $this->view->users = $this->project->getTeamMemberPairs($projectID); + $this->display(); + } + + /** + * View a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function view($taskID) + { + $task = $this->task->getById($taskID); + if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Set menu. */ + $project = $this->project->getById($task->project); + $this->project->setMenu($this->project->getPairs(), $project->id); + + $header['title'] = $project->name . $this->lang->colon . $this->lang->task->view; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$task->project"), $project->name); + $position[] = $this->lang->task->view; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->project = $project; + $this->view->task = $task; + $this->view->actions = $this->loadModel('action')->getList('task', $taskID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Confirm story change + * + * @param int $taskID + * @access public + * @return void + */ + public function confirmStoryChange($taskID) + { + $task = $this->task->getById($taskID); + $this->dao->update(TABLE_TASK)->set('storyVersion')->eq($task->latestStoryVersion)->where('id')->eq($taskID)->exec(); + $this->loadModel('action')->create('task', $taskID, 'confirmed', '', $task->latestStoryVersion); + die(js::reload('parent')); + } + + /** + * Start a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function start($taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->task->start($taskID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('task', $taskID, 'Started', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->start; + $this->view->position[] = $this->lang->task->start; + $this->display(); + } + + /** + * Finish a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function finish($taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->task->finish($taskID); + if(dao::isError()) die(js::error(dao::getError())); + + $task = $this->task->getById($taskID); + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('task', $taskID, 'Finished', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + + if($task->fromBug != 0) + { + foreach($changes as $change) + { + if($change['field'] == 'status') + { + $confirmURL = $this->createLink('bug', 'view', "id=$task->fromBug"); + $cancelURL = $this->server->HTTP_REFERER; + die(js::confirm(sprintf($this->lang->task->remindBug, $task->fromBug), $confirmURL, $cancelURL, 'parent', 'parent')); + } + } + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->finish; + $this->view->position[] = $this->lang->task->finish; + + $this->display(); + } + + /** + * Close a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function close($taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->task->close($taskID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('task', $taskID, 'Closed', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->finish; + $this->view->position[] = $this->lang->task->finish; + + $this->display(); + + } + + /** + * Batch close tasks. + * + * @access public + * @return void + */ + public function batchClose() + { + if($this->post->tasks) + { + $tasks = $this->post->tasks; + unset($_POST['tasks']); + $this->loadModel('action'); + + foreach($tasks as $taskID) + { + $this->commonAction($taskID); + $task = $this->task->getById($taskID); + if($task->status == 'wait' or $task->status == 'doing') continue; + + $changes = $this->task->close($taskID); + + if($changes) + { + $actionID = $this->action->create('task', $taskID, 'Closed', ''); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + } + } + die(js::reload('parent')); + } + + /** + * Cancel a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function cancel($taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->task->cancel($taskID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('task', $taskID, 'Canceled', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->cancel; + $this->view->position[] = $this->lang->task->cancel; + + $this->display(); + } + + /** + * Activate a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function activate($taskID) + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->task->activate($taskID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('task', $taskID, 'Activated', $this->post->comment); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + } + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->task->activate; + $this->view->position[] = $this->lang->task->activate; + $this->display(); + } + + /** + * Delete a task. + * + * @param int $projectID + * @param int $taskID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($projectID, $taskID, $confirm = 'no') + { + $task = $this->task->getById($taskID); + if($confirm == 'no') + { + die(js::confirm($this->lang->task->confirmDelete, inlink('delete', "projectID=$projectID&taskID=$taskID&confirm=yes"))); + } + else + { + $story = $this->dao->select('story')->from(TABLE_TASK)->where('id')->eq($taskID)->fetch('story'); + $this->task->delete(TABLE_TASK, $taskID); + if($task->fromBug != 0) $this->dao->update(TABLE_BUG)->set('toTask')->eq(0)->where('id')->eq($task->fromBug)->exec(); + if($story) $this->loadModel('story')->setStage($story); + die(js::locate($this->session->taskList, 'parent')); + } + } + + /** + * Send email. + * + * @param int $taskID + * @param int $actionID + * @access private + * @return void + */ + private function sendmail($taskID, $actionID) + { + /* Set toList and ccList. */ + $task = $this->task->getById($taskID); + $projectName = $this->project->getById($task->project)->name; + $toList = $task->assignedTo; + $ccList = trim($task->mailto, ','); + + if($toList == '') + { + if($ccList == '') return; + if(strpos($ccList, ',') === false) + { + $toList = $ccList; + $ccList = ''; + } + else + { + $commaPos = strpos($ccList, ','); + $toList = substr($ccList, 0, $commaPos); + $ccList = substr($ccList, $commaPos + 1); + } + } + elseif(strtolower($toList) == 'closed') + { + $toList = $task->finishedBy; + } + + /* Get action info. */ + $action = $this->loadModel('action')->getById($actionID); + $history = $this->action->getHistory($actionID); + $action->history = isset($history[$actionID]) ? $history[$actionID] : array(); + + /* Create the email content. */ + $this->view->task = $task; + $this->view->action = $action; + $this->clear(); + $mailContent = $this->parse($this->moduleName, 'sendmail'); + + /* Send emails. */ + $this->loadModel('mail')->send($toList, $projectName . ':' . 'TASK#' . $task->id . $this->lang->colon . $task->name, $mailContent, $ccList); + if($this->mail->isError()) echo js::error($this->mail->getError()); + } + + /** + * AJAX: return tasks of a user in html select. + * + * @param string $account + * @param string $status + * @access public + * @return string + */ + public function ajaxGetUserTasks($account = '', $status = 'wait,doing') + { + if($account == '') $account = $this->app->user->account; + $tasks = $this->task->getUserTaskPairs($account, $status); + die(html::select('task', $tasks, '', 'class=select-1')); + } + + /** + * AJAX: return project tasks in html select. + * + * @param int $projectID + * @param int $taskID + * @access public + * @return string + */ + public function ajaxGetProjectTasks($projectID, $taskID = 0) + { + $tasks = $this->task->getProjectTaskPairs((int)$projectID); + die(html::select('task', $tasks, $taskID)); + } + + /** + * The report page. + * + * @param int $projectID + * @param string $browseType + * @access public + * @return void + */ + public function report($projectID, $browseType = 'all') + { + + $this->loadModel('report'); + $this->view->charts = array(); + $this->view->renderJS = ''; + + if(!empty($_POST)) + { + foreach($this->post->charts as $chart) + { + $chartFunc = 'getDataOf' . $chart; + $chartData = $this->task->$chartFunc(); + $chartOption = $this->lang->task->report->$chart; + $this->task->mergeChartOption($chart); + + $chartXML = $this->report->createSingleXML($chartData, $chartOption->graph); + $this->view->charts[$chart] = $this->report->createJSChart($chartOption->swf, $chartXML, $chartOption->width, $chartOption->height); + $this->view->datas[$chart] = $this->report->computePercent($chartData); + } + $this->view->renderJS = $this->report->renderJsCharts(count($this->view->charts)); + } + + $this->project->setMenu($this->project->getPairs(), $projectID); + $this->projects = $this->project->getPairs(); + $this->view->header->title = $this->projects[$projectID] . $this->lang->colon . $this->lang->task->report->common; + $this->view->projectID = $projectID; + $this->view->browseType = $browseType; + $this->view->checkedCharts = $this->post->charts ? join(',', $this->post->charts) : ''; + + $this->display(); + } + + /** + * get data to export + * + * @param int $projectID + * @param string $orderBy + * @access public + * @return void + */ + public function export($projectID, $orderBy) + { + if($_POST) + { + $taskLang = $this->lang->task; + $taskConfig = $this->config->task; + + /* Create field lists. */ + $fields = explode(',', $taskConfig->exportFields); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($taskLang->$fieldName) ? $taskLang->$fieldName : $fieldName; + unset($fields[$key]); + } + + /* Get tasks. */ + $tasks = $this->dao->select('*')->from(TABLE_TASK)->alias('t1')->where($this->session->taskReportCondition)->orderBy($orderBy)->fetchAll('id'); + + /* Get users and projects. */ + $users = $this->loadModel('user')->getPairs('noletter'); + $projects = $this->loadModel('project')->getPairs('all'); + + /* Get related objects id lists. */ + $relatedStoryIdList = array(); + foreach($tasks as $task) $relatedStoryIdList[$task->story] = $task->story; + + /* Get related objects title or names. */ + $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); + $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('task')->andWhere('objectID')->in(@array_keys($tasks))->fetchGroup('objectID'); + + foreach($tasks as $task) + { + if($this->post->fileType == 'csv') + { + $task->desc = htmlspecialchars_decode($task->desc); + $task->desc = str_replace("
          ", "\n", $task->desc); + $task->desc = str_replace('"', '""', $task->desc); + } + + /* fill some field with useful value. */ + $task->story = isset($relatedStories[$task->story]) ? $relatedStories[$task->story] : ''; + + if(isset($projects[$task->project])) $task->project = $projects[$task->project]; + if(isset($taskLang->typeList[$task->type])) $task->type = $taskLang->typeList[$task->type]; + if(isset($taskLang->priList[$task->pri])) $task->pri = $taskLang->priList[$task->pri]; + if(isset($taskLang->statusList[$task->status])) $task->status = $taskLang->statusList[$task->status]; + if(isset($taskLang->reasonList[$task->closedReason])) $task->closedReason = $taskLang->reasonList[$task->closedReason]; + + if(isset($users[$task->openedBy])) $task->openedBy = $users[$task->openedBy]; + if(isset($users[$task->assignedTo])) $task->assignedTo = $users[$task->assignedTo]; + if(isset($users[$task->finishedBy])) $task->finishedBy = $users[$task->finishedBy]; + if(isset($users[$task->canceledBy])) $task->canceledBy = $users[$task->canceledBy]; + if(isset($users[$task->closedBy])) $task->closedBy = $users[$task->closedBy]; + if(isset($users[$task->lastEditedBy])) $task->lastEditedBy = $users[$task->lastEditedBy]; + + $task->openedDate = substr($task->openedDate, 0, 10); + $task->assignedDate = substr($task->assignedDate, 0, 10); + $task->finishedDate = substr($task->finishedDate, 0, 10); + $task->canceledDate = substr($task->canceledDate, 0, 10); + $task->closedDate = substr($task->closedDate, 0, 10); + $task->lastEditedDate = substr($task->lastEditedDate, 0, 10); + + /* Set related files. */ + if(isset($relatedFiles[$task->id])) + { + foreach($relatedFiles[$task->id] as $file) + { + $fileURL = 'http://' . $this->server->http_host . $this->config->webRoot . "data/upload/$task->company/" . $file->pathname; + $task->files .= html::a($fileURL, $file->title, '_blank') . '
          '; + } + } + } + + $this->post->set('fields', $fields); + $this->post->set('rows', $tasks); + $this->fetch('file', 'export2' . $this->post->fileType, $_POST); + } + + $this->display(); + } +} diff --git a/module/task/lang/en.php b/module/task/lang/en.php index 0fdab8b5d0..8fc3f61e99 100644 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -1,179 +1,179 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->task->index = "Index"; -$lang->task->create = "Create"; -$lang->task->batchCreate = "Batch create"; -$lang->task->import = "Import undone"; -$lang->task->edit = "Update"; -$lang->task->delete = "Delete"; -$lang->task->view = "Info"; -$lang->task->logEfforts = "Efforts"; -$lang->task->start = "Start"; -$lang->task->finish = "Finish"; -$lang->task->close = "Close"; -$lang->task->batchClose = "Batch close"; -$lang->task->cancel = "Cancel"; -$lang->task->activate = "Activate"; -$lang->task->export = "Export"; -$lang->task->reportChart = "Report chart"; -$lang->task->fromBug = 'From Bug'; -$lang->task->confirmStoryChange = "Confirm story change"; - -$lang->task->common = 'Task'; -$lang->task->id = 'ID'; -$lang->task->project = 'Project'; -$lang->task->story = 'Story'; -$lang->task->storyVersion = 'Version'; -$lang->task->name = 'Name'; -$lang->task->type = 'Type'; -$lang->task->pri = 'Pri'; -$lang->task->mailto = 'Mailto'; -$lang->task->estimate = 'Estimate'; -$lang->task->estimateAB = 'Est'; -$lang->task->left = 'Left'; -$lang->task->leftAB = 'Left'; -$lang->task->consumed = 'Consumed'; -$lang->task->consumedAB = 'Use'; -$lang->task->deadline = 'Deadline'; -$lang->task->deadlineAB = 'Deadline'; -$lang->task->status = 'Status'; -$lang->task->statusCustom = 'Status Order'; -$lang->task->desc = 'Desc'; -$lang->task->assign = 'Assign'; -$lang->task->assignedTo = 'Assigned To'; -$lang->task->assignedToAB = 'Assign'; -$lang->task->assignedDate = 'Assigned Date'; -$lang->task->openedBy = 'Opened By'; -$lang->task->openedByAB = 'Open'; -$lang->task->openedDate = 'Opened Date'; -$lang->task->openedDateAB = 'Open'; -$lang->task->finishedBy = 'Finished By'; -$lang->task->finishedByAB = 'Finishe'; -$lang->task->finishedDate = 'Finished Date'; -$lang->task->finishedDateAB = 'Date'; -$lang->task->canceledBy = 'Canceled By'; -$lang->task->canceledDate = 'Canceled Date'; -$lang->task->closedBy = 'Closed By'; -$lang->task->closedDate = 'Closed Date'; -$lang->task->closedReason = 'Closed Reason'; -$lang->task->lastEditedBy = 'Last Edited By'; -$lang->task->lastEditedDate = 'Last Edited Date'; -$lang->task->lastEdited = 'Last Edited'; - -$lang->task->same = 'The same as above'; -$lang->task->notes = '(Notes: the name, type, pri and estimate must be written, otherwise it is no use)'; - -$lang->task->statusList[''] = ''; -$lang->task->statusList['wait'] = 'Waiting'; -$lang->task->statusList['doing'] = 'Doing'; -$lang->task->statusList['done'] = 'Done'; -$lang->task->statusList['cancel'] = 'Canceled'; -$lang->task->statusList['closed'] = 'Closed'; - -$lang->task->typeList[''] = ''; -$lang->task->typeList['design'] = 'Design'; -$lang->task->typeList['devel'] = 'Devel'; -$lang->task->typeList['test'] = 'Test'; -$lang->task->typeList['study'] = 'Study'; -$lang->task->typeList['discuss'] = 'Discuss'; -$lang->task->typeList['ui'] = 'UI'; -$lang->task->typeList['affair'] = 'Affair'; -$lang->task->typeList['misc'] = 'Misc'; - -$lang->task->priList[0] = ''; -$lang->task->priList[3] = '3'; -$lang->task->priList[1] = '1'; -$lang->task->priList[2] = '2'; -$lang->task->priList[4] = '4'; - -$lang->task->reasonList[''] = ''; -$lang->task->reasonList['done'] = 'Done'; -$lang->task->reasonList['cancel'] = 'Canceled'; - -$lang->task->afterChoices['continueAdding'] = 'Continue add task for this story'; -$lang->task->afterChoices['toTastList'] = 'To task list'; -$lang->task->afterChoices['toStoryList'] = 'To story list'; - -$lang->task->buttonEdit = 'Edit'; -$lang->task->buttonClose = 'Close'; -$lang->task->buttonCancel = 'Cancel'; -$lang->task->buttonActivate = 'Activate'; -$lang->task->buttonLogEfforts = 'Efforts'; -$lang->task->buttonDelete = 'Delete'; -$lang->task->buttonBackToList = 'Back'; -$lang->task->buttonStart = 'Start'; -$lang->task->buttonDone = 'Done'; - -$lang->task->legendBasic = 'Basic info'; -$lang->task->legendEffort = 'Effort'; -$lang->task->legendLife = 'Lifetime'; -$lang->task->legendDesc = 'Desc'; -$lang->task->legendAction = 'Action'; - -$lang->task->ajaxGetUserTasks = "API:My tasks"; -$lang->task->ajaxGetProjectTasks = "API:Project tasks"; -$lang->task->confirmDelete = "Are you sure to delete this task?"; -$lang->task->copyStoryTitle = "Same as story"; -$lang->task->afterSubmit = "After created"; -$lang->task->successSaved = "Success saved"; -$lang->task->delayWarning = " Postponed %s days "; -$lang->task->remindBug = "This task from Bug, update the Bug:%s or not?"; - -/* Report. */ -$lang->task->report->common = 'Report'; -$lang->task->report->select = 'Select'; -$lang->task->report->create = 'Create'; -$lang->task->report->selectAll = 'All'; -$lang->task->report->selectReverse = 'Reverse'; - -$lang->task->report->charts['tasksPerProject'] = 'Project tasks'; -$lang->task->report->charts['tasksPerAssignedTo'] = 'Assigned To'; -$lang->task->report->charts['tasksPerType'] = 'Type'; -$lang->task->report->charts['tasksPerPri'] = 'Priority'; -$lang->task->report->charts['tasksPerStatus'] = 'Status'; -$lang->task->report->charts['tasksPerDeadline'] = 'Deadline'; -$lang->task->report->charts['tasksPerEstimate'] = 'Estimate time'; -$lang->task->report->charts['tasksPerLeft'] = 'Left time'; -$lang->task->report->charts['tasksPerConsumed'] = 'Consumed time'; -$lang->task->report->charts['tasksPerFinishedBy'] = 'Finished By'; -$lang->task->report->charts['tasksPerClosedReason'] = 'Closed reason'; -$lang->task->report->charts['finishedTasksPerDay'] = 'Finished tasks per day'; - -$lang->task->report->options->swf = 'pie2d'; -$lang->task->report->options->width = 'auto'; -$lang->task->report->options->height = 300; -$lang->task->report->options->graph->baseFontSize = 12; -$lang->task->report->options->graph->showNames = 1; -$lang->task->report->options->graph->formatNumber = 1; -$lang->task->report->options->graph->decimalPrecision = 0; -$lang->task->report->options->graph->animation = 0; -$lang->task->report->options->graph->rotateNames = 0; -$lang->task->report->options->graph->yAxisName = 'COUNT'; -$lang->task->report->options->graph->pieRadius = 100; -$lang->task->report->options->graph->showColumnShadow = 0; - -$lang->task->report->tasksPerProject->graph->xAxisName = 'Project'; -$lang->task->report->tasksPerAssignedTo->graph->xAxisName = 'User'; -$lang->task->report->tasksPerType->graph->xAxisName = 'Type'; -$lang->task->report->tasksPerPri->graph->xAxisName = 'Pri'; -$lang->task->report->tasksPerStatus->graph->xAxisName = 'Status'; -$lang->task->report->tasksPerDeadline->graph->xAxisName = 'Date'; -$lang->task->report->tasksPerEstimate->graph->xAxisName = 'Time'; -$lang->task->report->tasksPerLeft->graph->xAxisName = 'Time'; -$lang->task->report->tasksPerConsumed->graph->xAxisName = 'Time'; -$lang->task->report->tasksPerFinishedBy->graph->xAxisName = 'User'; -$lang->task->report->tasksPerClosedReason->graph->xAxisName = 'Closed Reason'; - -$lang->task->report->finishedTasksPerDay->swf = 'column2d'; -$lang->task->report->finishedTasksPerDay->height = 400; -$lang->task->report->finishedTasksPerDay->graph->xAxisName = 'Date'; -$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->task->index = "Index"; +$lang->task->create = "Create"; +$lang->task->batchCreate = "Batch create"; +$lang->task->import = "Import undone"; +$lang->task->edit = "Update"; +$lang->task->delete = "Delete"; +$lang->task->view = "Info"; +$lang->task->logEfforts = "Efforts"; +$lang->task->start = "Start"; +$lang->task->finish = "Finish"; +$lang->task->close = "Close"; +$lang->task->batchClose = "Batch close"; +$lang->task->cancel = "Cancel"; +$lang->task->activate = "Activate"; +$lang->task->export = "Export"; +$lang->task->reportChart = "Report chart"; +$lang->task->fromBug = 'From Bug'; +$lang->task->confirmStoryChange = "Confirm story change"; + +$lang->task->common = 'Task'; +$lang->task->id = 'ID'; +$lang->task->project = 'Project'; +$lang->task->story = 'Story'; +$lang->task->storyVersion = 'Version'; +$lang->task->name = 'Name'; +$lang->task->type = 'Type'; +$lang->task->pri = 'Pri'; +$lang->task->mailto = 'Mailto'; +$lang->task->estimate = 'Estimate'; +$lang->task->estimateAB = 'Est'; +$lang->task->left = 'Left'; +$lang->task->leftAB = 'Left'; +$lang->task->consumed = 'Consumed'; +$lang->task->consumedAB = 'Use'; +$lang->task->deadline = 'Deadline'; +$lang->task->deadlineAB = 'Deadline'; +$lang->task->status = 'Status'; +$lang->task->statusCustom = 'Status Order'; +$lang->task->desc = 'Desc'; +$lang->task->assign = 'Assign'; +$lang->task->assignedTo = 'Assigned To'; +$lang->task->assignedToAB = 'Assign'; +$lang->task->assignedDate = 'Assigned Date'; +$lang->task->openedBy = 'Opened By'; +$lang->task->openedByAB = 'Open'; +$lang->task->openedDate = 'Opened Date'; +$lang->task->openedDateAB = 'Open'; +$lang->task->finishedBy = 'Finished By'; +$lang->task->finishedByAB = 'Finishe'; +$lang->task->finishedDate = 'Finished Date'; +$lang->task->finishedDateAB = 'Date'; +$lang->task->canceledBy = 'Canceled By'; +$lang->task->canceledDate = 'Canceled Date'; +$lang->task->closedBy = 'Closed By'; +$lang->task->closedDate = 'Closed Date'; +$lang->task->closedReason = 'Closed Reason'; +$lang->task->lastEditedBy = 'Last Edited By'; +$lang->task->lastEditedDate = 'Last Edited Date'; +$lang->task->lastEdited = 'Last Edited'; + +$lang->task->same = 'The same as above'; +$lang->task->notes = '(Notes: the name, type, pri and estimate must be written, otherwise it is no use)'; + +$lang->task->statusList[''] = ''; +$lang->task->statusList['wait'] = 'Waiting'; +$lang->task->statusList['doing'] = 'Doing'; +$lang->task->statusList['done'] = 'Done'; +$lang->task->statusList['cancel'] = 'Canceled'; +$lang->task->statusList['closed'] = 'Closed'; + +$lang->task->typeList[''] = ''; +$lang->task->typeList['design'] = 'Design'; +$lang->task->typeList['devel'] = 'Devel'; +$lang->task->typeList['test'] = 'Test'; +$lang->task->typeList['study'] = 'Study'; +$lang->task->typeList['discuss'] = 'Discuss'; +$lang->task->typeList['ui'] = 'UI'; +$lang->task->typeList['affair'] = 'Affair'; +$lang->task->typeList['misc'] = 'Misc'; + +$lang->task->priList[0] = ''; +$lang->task->priList[3] = '3'; +$lang->task->priList[1] = '1'; +$lang->task->priList[2] = '2'; +$lang->task->priList[4] = '4'; + +$lang->task->reasonList[''] = ''; +$lang->task->reasonList['done'] = 'Done'; +$lang->task->reasonList['cancel'] = 'Canceled'; + +$lang->task->afterChoices['continueAdding'] = 'Continue add task for this story'; +$lang->task->afterChoices['toTastList'] = 'To task list'; +$lang->task->afterChoices['toStoryList'] = 'To story list'; + +$lang->task->buttonEdit = 'Edit'; +$lang->task->buttonClose = 'Close'; +$lang->task->buttonCancel = 'Cancel'; +$lang->task->buttonActivate = 'Activate'; +$lang->task->buttonLogEfforts = 'Efforts'; +$lang->task->buttonDelete = 'Delete'; +$lang->task->buttonBackToList = 'Back'; +$lang->task->buttonStart = 'Start'; +$lang->task->buttonDone = 'Done'; + +$lang->task->legendBasic = 'Basic info'; +$lang->task->legendEffort = 'Effort'; +$lang->task->legendLife = 'Lifetime'; +$lang->task->legendDesc = 'Desc'; +$lang->task->legendAction = 'Action'; + +$lang->task->ajaxGetUserTasks = "API:My tasks"; +$lang->task->ajaxGetProjectTasks = "API:Project tasks"; +$lang->task->confirmDelete = "Are you sure to delete this task?"; +$lang->task->copyStoryTitle = "Same as story"; +$lang->task->afterSubmit = "After created"; +$lang->task->successSaved = "Success saved"; +$lang->task->delayWarning = " Postponed %s days "; +$lang->task->remindBug = "This task from Bug, update the Bug:%s or not?"; + +/* Report. */ +$lang->task->report->common = 'Report'; +$lang->task->report->select = 'Select'; +$lang->task->report->create = 'Create'; +$lang->task->report->selectAll = 'All'; +$lang->task->report->selectReverse = 'Reverse'; + +$lang->task->report->charts['tasksPerProject'] = 'Project tasks'; +$lang->task->report->charts['tasksPerAssignedTo'] = 'Assigned To'; +$lang->task->report->charts['tasksPerType'] = 'Type'; +$lang->task->report->charts['tasksPerPri'] = 'Priority'; +$lang->task->report->charts['tasksPerStatus'] = 'Status'; +$lang->task->report->charts['tasksPerDeadline'] = 'Deadline'; +$lang->task->report->charts['tasksPerEstimate'] = 'Estimate time'; +$lang->task->report->charts['tasksPerLeft'] = 'Left time'; +$lang->task->report->charts['tasksPerConsumed'] = 'Consumed time'; +$lang->task->report->charts['tasksPerFinishedBy'] = 'Finished By'; +$lang->task->report->charts['tasksPerClosedReason'] = 'Closed reason'; +$lang->task->report->charts['finishedTasksPerDay'] = 'Finished tasks per day'; + +$lang->task->report->options->swf = 'pie2d'; +$lang->task->report->options->width = 'auto'; +$lang->task->report->options->height = 300; +$lang->task->report->options->graph->baseFontSize = 12; +$lang->task->report->options->graph->showNames = 1; +$lang->task->report->options->graph->formatNumber = 1; +$lang->task->report->options->graph->decimalPrecision = 0; +$lang->task->report->options->graph->animation = 0; +$lang->task->report->options->graph->rotateNames = 0; +$lang->task->report->options->graph->yAxisName = 'COUNT'; +$lang->task->report->options->graph->pieRadius = 100; +$lang->task->report->options->graph->showColumnShadow = 0; + +$lang->task->report->tasksPerProject->graph->xAxisName = 'Project'; +$lang->task->report->tasksPerAssignedTo->graph->xAxisName = 'User'; +$lang->task->report->tasksPerType->graph->xAxisName = 'Type'; +$lang->task->report->tasksPerPri->graph->xAxisName = 'Pri'; +$lang->task->report->tasksPerStatus->graph->xAxisName = 'Status'; +$lang->task->report->tasksPerDeadline->graph->xAxisName = 'Date'; +$lang->task->report->tasksPerEstimate->graph->xAxisName = 'Time'; +$lang->task->report->tasksPerLeft->graph->xAxisName = 'Time'; +$lang->task->report->tasksPerConsumed->graph->xAxisName = 'Time'; +$lang->task->report->tasksPerFinishedBy->graph->xAxisName = 'User'; +$lang->task->report->tasksPerClosedReason->graph->xAxisName = 'Closed Reason'; + +$lang->task->report->finishedTasksPerDay->swf = 'column2d'; +$lang->task->report->finishedTasksPerDay->height = 400; +$lang->task->report->finishedTasksPerDay->graph->xAxisName = 'Date'; +$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index c3a2c66627..8aba9a896a 100644 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -1,179 +1,179 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->task->index = "任务一览"; -$lang->task->create = "新增任务"; -$lang->task->batchCreate = "批量添加"; -$lang->task->import = "导入之前未完任务"; -$lang->task->edit = "编辑任务"; -$lang->task->delete = "删除任务"; -$lang->task->view = "查看任务"; -$lang->task->logEfforts = "记录工时"; -$lang->task->start = "开始任务"; -$lang->task->finish = "完成任务"; -$lang->task->close = "关闭任务"; -$lang->task->batchClose = "批量关闭"; -$lang->task->cancel = "取消任务"; -$lang->task->activate = "激活任务"; -$lang->task->export = "导出数据"; -$lang->task->reportChart = "报表统计"; -$lang->task->fromBug = '来源Bug'; -$lang->task->confirmStoryChange = "确认需求变动"; - -$lang->task->common = '任务'; -$lang->task->id = '编号'; -$lang->task->project = '所属项目'; -$lang->task->story = '相关需求'; -$lang->task->storyVersion = '需求版本'; -$lang->task->name = '任务名称'; -$lang->task->type = '任务类型'; -$lang->task->pri = '优先级'; -$lang->task->mailto = '抄送给'; -$lang->task->estimate = '最初预计'; -$lang->task->estimateAB = '预'; -$lang->task->left = '预计剩余'; -$lang->task->leftAB = '剩'; -$lang->task->consumed = '已经消耗'; -$lang->task->consumedAB = '耗'; -$lang->task->deadline = '截止日期'; -$lang->task->deadlineAB = '截止'; -$lang->task->status = '任务状态'; -$lang->task->statusCustom = '状态排序'; -$lang->task->desc = '任务描述'; -$lang->task->assign = '指派'; -$lang->task->assignedTo = '指派给'; -$lang->task->assignedToAB = '指派给'; -$lang->task->assignedDate = '指派日期'; -$lang->task->openedBy = '由谁创建'; -$lang->task->openedByAB = '创建者'; -$lang->task->openedDate = '创建日期'; -$lang->task->openedDateAB = '创建'; -$lang->task->finishedBy = '由谁完成'; -$lang->task->finishedByAB = '完成者'; -$lang->task->finishedDate = '完成时间'; -$lang->task->finishedDateAB = '完成'; -$lang->task->canceledBy = '由谁取消'; -$lang->task->canceledDate = '取消时间'; -$lang->task->closedBy = '由谁关闭'; -$lang->task->closedDate = '关闭时间'; -$lang->task->closedReason = '关闭原因'; -$lang->task->lastEditedBy = '最后修改'; -$lang->task->lastEditedDate = '最后修改日期'; -$lang->task->lastEdited = '最后编辑'; - -$lang->task->same = '同上'; -$lang->task->notes = '(注:“任务类型”、“任务名称”、“优先级”和“预计工时”必需填写,否则此行无效)'; - -$lang->task->statusList[''] = ''; -$lang->task->statusList['wait'] = '未开始'; -$lang->task->statusList['doing'] = '进行中'; -$lang->task->statusList['done'] = '已完成'; -$lang->task->statusList['cancel'] = '已取消'; -$lang->task->statusList['closed'] = '已关闭'; - -$lang->task->typeList[''] = ''; -$lang->task->typeList['design'] = '设计'; -$lang->task->typeList['devel'] = '开发'; -$lang->task->typeList['test'] = '测试'; -$lang->task->typeList['study'] = '研究'; -$lang->task->typeList['discuss'] = '讨论'; -$lang->task->typeList['ui'] = '界面'; -$lang->task->typeList['affair'] = '事务'; -$lang->task->typeList['misc'] = '其他'; - -$lang->task->priList[0] = ''; -$lang->task->priList[3] = '3'; -$lang->task->priList[1] = '1'; -$lang->task->priList[2] = '2'; -$lang->task->priList[4] = '4'; - -$lang->task->reasonList[''] = ''; -$lang->task->reasonList['done'] = '已完成'; -$lang->task->reasonList['cancel'] = '已取消'; - -$lang->task->afterChoices['continueAdding'] = '继续为该需求添加任务'; -$lang->task->afterChoices['toTastList'] = '返回任务列表'; -$lang->task->afterChoices['toStoryList'] = '返回需求列表'; - -$lang->task->buttonEdit = '编辑'; -$lang->task->buttonClose = '关闭'; -$lang->task->buttonCancel = '取消'; -$lang->task->buttonActivate = '激活'; -$lang->task->buttonLogEfforts = '记录工时'; -$lang->task->buttonDelete = '删除'; -$lang->task->buttonBackToList = '返回'; -$lang->task->buttonStart = '开始'; -$lang->task->buttonDone = '完成'; - -$lang->task->legendBasic = '基本信息'; -$lang->task->legendEffort = '工时信息'; -$lang->task->legendLife = '任务的一生'; -$lang->task->legendDesc = '任务描述'; -$lang->task->legendAction = '操作'; - -$lang->task->ajaxGetUserTasks = "接口:我的任务"; -$lang->task->ajaxGetProjectTasks = "接口:项目任务"; -$lang->task->confirmDelete = "您确定要删除这个任务吗?"; -$lang->task->copyStoryTitle = "同需求"; -$lang->task->afterSubmit = "添加之后"; -$lang->task->successSaved = "成功添加,"; -$lang->task->delayWarning = " 延期%s天 "; -$lang->task->remindBug = "该任务为Bug转化得到,是否更新Bug:%s ?"; - -/* 统计报表。*/ -$lang->task->report->common = '统计报表'; -$lang->task->report->select = '请选择报表类型'; -$lang->task->report->create = '生成报表'; -$lang->task->report->selectAll = '全选'; -$lang->task->report->selectReverse = '反选'; - -$lang->task->report->charts['tasksPerProject'] = '项目任务数统计'; -$lang->task->report->charts['tasksPerAssignedTo'] = '指派给统计'; -$lang->task->report->charts['tasksPerType'] = '任务类型统计'; -$lang->task->report->charts['tasksPerPri'] = '优先级统计'; -$lang->task->report->charts['tasksPerStatus'] = '任务状态统计'; -$lang->task->report->charts['tasksPerDeadline'] = '截止日期统计'; -$lang->task->report->charts['tasksPerEstimate'] = '预计时间统计'; -$lang->task->report->charts['tasksPerLeft'] = '剩余时间统计'; -$lang->task->report->charts['tasksPerConsumed'] = '消耗时间统计'; -$lang->task->report->charts['tasksPerFinishedBy'] = '由谁完成统计'; -$lang->task->report->charts['tasksPerClosedReason'] = '关闭原因统计'; -$lang->task->report->charts['finishedTasksPerDay'] = '每天完成统计'; - -$lang->task->report->options->swf = 'pie2d'; -$lang->task->report->options->width = 'auto'; -$lang->task->report->options->height = 300; -$lang->task->report->options->graph->baseFontSize = 12; -$lang->task->report->options->graph->showNames = 1; -$lang->task->report->options->graph->formatNumber = 1; -$lang->task->report->options->graph->decimalPrecision = 0; -$lang->task->report->options->graph->animation = 0; -$lang->task->report->options->graph->rotateNames = 0; -$lang->task->report->options->graph->yAxisName = 'COUNT'; -$lang->task->report->options->graph->pieRadius = 100; // 饼图直径。 -$lang->task->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 - -$lang->task->report->tasksPerProject->graph->xAxisName = '项目'; -$lang->task->report->tasksPerAssignedTo->graph->xAxisName = '用户'; -$lang->task->report->tasksPerType->graph->xAxisName = '类型'; -$lang->task->report->tasksPerPri->graph->xAxisName = '优先级'; -$lang->task->report->tasksPerStatus->graph->xAxisName = '状态'; -$lang->task->report->tasksPerDeadline->graph->xAxisName = '日期'; -$lang->task->report->tasksPerEstimate->graph->xAxisName = '时间'; -$lang->task->report->tasksPerLeft->graph->xAxisName = '时间'; -$lang->task->report->tasksPerConsumed->graph->xAxisName = '时间'; -$lang->task->report->tasksPerFinishedBy->graph->xAxisName = '用户'; -$lang->task->report->tasksPerClosedReason->graph->xAxisName = '关闭原因'; - -$lang->task->report->finishedTasksPerDay->swf = 'column2d'; -$lang->task->report->finishedTasksPerDay->height = 400; -$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; -$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->task->index = "任务一览"; +$lang->task->create = "新增任务"; +$lang->task->batchCreate = "批量添加"; +$lang->task->import = "导入之前未完任务"; +$lang->task->edit = "编辑任务"; +$lang->task->delete = "删除任务"; +$lang->task->view = "查看任务"; +$lang->task->logEfforts = "记录工时"; +$lang->task->start = "开始任务"; +$lang->task->finish = "完成任务"; +$lang->task->close = "关闭任务"; +$lang->task->batchClose = "批量关闭"; +$lang->task->cancel = "取消任务"; +$lang->task->activate = "激活任务"; +$lang->task->export = "导出数据"; +$lang->task->reportChart = "报表统计"; +$lang->task->fromBug = '来源Bug'; +$lang->task->confirmStoryChange = "确认需求变动"; + +$lang->task->common = '任务'; +$lang->task->id = '编号'; +$lang->task->project = '所属项目'; +$lang->task->story = '相关需求'; +$lang->task->storyVersion = '需求版本'; +$lang->task->name = '任务名称'; +$lang->task->type = '任务类型'; +$lang->task->pri = '优先级'; +$lang->task->mailto = '抄送给'; +$lang->task->estimate = '最初预计'; +$lang->task->estimateAB = '预'; +$lang->task->left = '预计剩余'; +$lang->task->leftAB = '剩'; +$lang->task->consumed = '已经消耗'; +$lang->task->consumedAB = '耗'; +$lang->task->deadline = '截止日期'; +$lang->task->deadlineAB = '截止'; +$lang->task->status = '任务状态'; +$lang->task->statusCustom = '状态排序'; +$lang->task->desc = '任务描述'; +$lang->task->assign = '指派'; +$lang->task->assignedTo = '指派给'; +$lang->task->assignedToAB = '指派给'; +$lang->task->assignedDate = '指派日期'; +$lang->task->openedBy = '由谁创建'; +$lang->task->openedByAB = '创建者'; +$lang->task->openedDate = '创建日期'; +$lang->task->openedDateAB = '创建'; +$lang->task->finishedBy = '由谁完成'; +$lang->task->finishedByAB = '完成者'; +$lang->task->finishedDate = '完成时间'; +$lang->task->finishedDateAB = '完成'; +$lang->task->canceledBy = '由谁取消'; +$lang->task->canceledDate = '取消时间'; +$lang->task->closedBy = '由谁关闭'; +$lang->task->closedDate = '关闭时间'; +$lang->task->closedReason = '关闭原因'; +$lang->task->lastEditedBy = '最后修改'; +$lang->task->lastEditedDate = '最后修改日期'; +$lang->task->lastEdited = '最后编辑'; + +$lang->task->same = '同上'; +$lang->task->notes = '(注:“任务类型”、“任务名称”、“优先级”和“预计工时”必需填写,否则此行无效)'; + +$lang->task->statusList[''] = ''; +$lang->task->statusList['wait'] = '未开始'; +$lang->task->statusList['doing'] = '进行中'; +$lang->task->statusList['done'] = '已完成'; +$lang->task->statusList['cancel'] = '已取消'; +$lang->task->statusList['closed'] = '已关闭'; + +$lang->task->typeList[''] = ''; +$lang->task->typeList['design'] = '设计'; +$lang->task->typeList['devel'] = '开发'; +$lang->task->typeList['test'] = '测试'; +$lang->task->typeList['study'] = '研究'; +$lang->task->typeList['discuss'] = '讨论'; +$lang->task->typeList['ui'] = '界面'; +$lang->task->typeList['affair'] = '事务'; +$lang->task->typeList['misc'] = '其他'; + +$lang->task->priList[0] = ''; +$lang->task->priList[3] = '3'; +$lang->task->priList[1] = '1'; +$lang->task->priList[2] = '2'; +$lang->task->priList[4] = '4'; + +$lang->task->reasonList[''] = ''; +$lang->task->reasonList['done'] = '已完成'; +$lang->task->reasonList['cancel'] = '已取消'; + +$lang->task->afterChoices['continueAdding'] = '继续为该需求添加任务'; +$lang->task->afterChoices['toTastList'] = '返回任务列表'; +$lang->task->afterChoices['toStoryList'] = '返回需求列表'; + +$lang->task->buttonEdit = '编辑'; +$lang->task->buttonClose = '关闭'; +$lang->task->buttonCancel = '取消'; +$lang->task->buttonActivate = '激活'; +$lang->task->buttonLogEfforts = '记录工时'; +$lang->task->buttonDelete = '删除'; +$lang->task->buttonBackToList = '返回'; +$lang->task->buttonStart = '开始'; +$lang->task->buttonDone = '完成'; + +$lang->task->legendBasic = '基本信息'; +$lang->task->legendEffort = '工时信息'; +$lang->task->legendLife = '任务的一生'; +$lang->task->legendDesc = '任务描述'; +$lang->task->legendAction = '操作'; + +$lang->task->ajaxGetUserTasks = "接口:我的任务"; +$lang->task->ajaxGetProjectTasks = "接口:项目任务"; +$lang->task->confirmDelete = "您确定要删除这个任务吗?"; +$lang->task->copyStoryTitle = "同需求"; +$lang->task->afterSubmit = "添加之后"; +$lang->task->successSaved = "成功添加,"; +$lang->task->delayWarning = " 延期%s天 "; +$lang->task->remindBug = "该任务为Bug转化得到,是否更新Bug:%s ?"; + +/* 统计报表。*/ +$lang->task->report->common = '统计报表'; +$lang->task->report->select = '请选择报表类型'; +$lang->task->report->create = '生成报表'; +$lang->task->report->selectAll = '全选'; +$lang->task->report->selectReverse = '反选'; + +$lang->task->report->charts['tasksPerProject'] = '项目任务数统计'; +$lang->task->report->charts['tasksPerAssignedTo'] = '指派给统计'; +$lang->task->report->charts['tasksPerType'] = '任务类型统计'; +$lang->task->report->charts['tasksPerPri'] = '优先级统计'; +$lang->task->report->charts['tasksPerStatus'] = '任务状态统计'; +$lang->task->report->charts['tasksPerDeadline'] = '截止日期统计'; +$lang->task->report->charts['tasksPerEstimate'] = '预计时间统计'; +$lang->task->report->charts['tasksPerLeft'] = '剩余时间统计'; +$lang->task->report->charts['tasksPerConsumed'] = '消耗时间统计'; +$lang->task->report->charts['tasksPerFinishedBy'] = '由谁完成统计'; +$lang->task->report->charts['tasksPerClosedReason'] = '关闭原因统计'; +$lang->task->report->charts['finishedTasksPerDay'] = '每天完成统计'; + +$lang->task->report->options->swf = 'pie2d'; +$lang->task->report->options->width = 'auto'; +$lang->task->report->options->height = 300; +$lang->task->report->options->graph->baseFontSize = 12; +$lang->task->report->options->graph->showNames = 1; +$lang->task->report->options->graph->formatNumber = 1; +$lang->task->report->options->graph->decimalPrecision = 0; +$lang->task->report->options->graph->animation = 0; +$lang->task->report->options->graph->rotateNames = 0; +$lang->task->report->options->graph->yAxisName = 'COUNT'; +$lang->task->report->options->graph->pieRadius = 100; // 饼图直径。 +$lang->task->report->options->graph->showColumnShadow = 0; // 是否显示柱状图阴影。 + +$lang->task->report->tasksPerProject->graph->xAxisName = '项目'; +$lang->task->report->tasksPerAssignedTo->graph->xAxisName = '用户'; +$lang->task->report->tasksPerType->graph->xAxisName = '类型'; +$lang->task->report->tasksPerPri->graph->xAxisName = '优先级'; +$lang->task->report->tasksPerStatus->graph->xAxisName = '状态'; +$lang->task->report->tasksPerDeadline->graph->xAxisName = '日期'; +$lang->task->report->tasksPerEstimate->graph->xAxisName = '时间'; +$lang->task->report->tasksPerLeft->graph->xAxisName = '时间'; +$lang->task->report->tasksPerConsumed->graph->xAxisName = '时间'; +$lang->task->report->tasksPerFinishedBy->graph->xAxisName = '用户'; +$lang->task->report->tasksPerClosedReason->graph->xAxisName = '关闭原因'; + +$lang->task->report->finishedTasksPerDay->swf = 'column2d'; +$lang->task->report->finishedTasksPerDay->height = 400; +$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; +$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; diff --git a/module/task/lang/zh-tw.php b/module/task/lang/zh-tw.php index 345d6fd184..57c37ea13a 100644 --- a/module/task/lang/zh-tw.php +++ b/module/task/lang/zh-tw.php @@ -1,179 +1,179 @@ - - * @package task - * @version $Id: zh-tw.php 2442 2011-12-17 02:47:00Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->task->index = "任務一覽"; -$lang->task->create = "新增任務"; -$lang->task->batchCreate = "批量添加"; -$lang->task->import = "導入之前未完任務"; -$lang->task->edit = "編輯任務"; -$lang->task->delete = "刪除任務"; -$lang->task->view = "查看任務"; -$lang->task->logEfforts = "記錄工時"; -$lang->task->start = "開始任務"; -$lang->task->finish = "完成任務"; -$lang->task->close = "關閉任務"; -$lang->task->batchClose = "批量關閉"; -$lang->task->cancel = "取消任務"; -$lang->task->activate = "激活任務"; -$lang->task->export = "導出數據"; -$lang->task->reportChart = "報表統計"; -$lang->task->fromBug = '來源Bug'; -$lang->task->confirmStoryChange = "確認需求變動"; - -$lang->task->common = '任務'; -$lang->task->id = '編號'; -$lang->task->project = '所屬項目'; -$lang->task->story = '相關需求'; -$lang->task->storyVersion = '需求版本'; -$lang->task->name = '任務名稱'; -$lang->task->type = '任務類型'; -$lang->task->pri = '優先順序'; -$lang->task->mailto = '抄送給'; -$lang->task->estimate = '最初預計'; -$lang->task->estimateAB = '預'; -$lang->task->left = '預計剩餘'; -$lang->task->leftAB = '剩'; -$lang->task->consumed = '已經消耗'; -$lang->task->consumedAB = '耗'; -$lang->task->deadline = '截止日期'; -$lang->task->deadlineAB = '截止'; -$lang->task->status = '任務狀態'; -$lang->task->statusCustom = '狀態排序'; -$lang->task->desc = '任務描述'; -$lang->task->assign = '指派'; -$lang->task->assignedTo = '指派給'; -$lang->task->assignedToAB = '指派給'; -$lang->task->assignedDate = '指派日期'; -$lang->task->openedBy = '由誰創建'; -$lang->task->openedByAB = '創建者'; -$lang->task->openedDate = '創建日期'; -$lang->task->openedDateAB = '創建'; -$lang->task->finishedBy = '由誰完成'; -$lang->task->finishedByAB = '完成者'; -$lang->task->finishedDate = '完成時間'; -$lang->task->finishedDateAB = '完成'; -$lang->task->canceledBy = '由誰取消'; -$lang->task->canceledDate = '取消時間'; -$lang->task->closedBy = '由誰關閉'; -$lang->task->closedDate = '關閉時間'; -$lang->task->closedReason = '關閉原因'; -$lang->task->lastEditedBy = '最後修改'; -$lang->task->lastEditedDate = '最後修改日期'; -$lang->task->lastEdited = '最後編輯'; - -$lang->task->same = '同上'; -$lang->task->notes = '(註:“任務類型”、“任務名稱”、“優先順序”和“預計工時”必需填寫,否則此行無效)'; - -$lang->task->statusList[''] = ''; -$lang->task->statusList['wait'] = '未開始'; -$lang->task->statusList['doing'] = '進行中'; -$lang->task->statusList['done'] = '已完成'; -$lang->task->statusList['cancel'] = '已取消'; -$lang->task->statusList['closed'] = '已關閉'; - -$lang->task->typeList[''] = ''; -$lang->task->typeList['design'] = '設計'; -$lang->task->typeList['devel'] = '開發'; -$lang->task->typeList['test'] = '測試'; -$lang->task->typeList['study'] = '研究'; -$lang->task->typeList['discuss'] = '討論'; -$lang->task->typeList['ui'] = '界面'; -$lang->task->typeList['affair'] = '事務'; -$lang->task->typeList['misc'] = '其他'; - -$lang->task->priList[0] = ''; -$lang->task->priList[3] = '3'; -$lang->task->priList[1] = '1'; -$lang->task->priList[2] = '2'; -$lang->task->priList[4] = '4'; - -$lang->task->reasonList[''] = ''; -$lang->task->reasonList['done'] = '已完成'; -$lang->task->reasonList['cancel'] = '已取消'; - -$lang->task->afterChoices['continueAdding'] = '繼續為該需求添加任務'; -$lang->task->afterChoices['toTastList'] = '返回任務列表'; -$lang->task->afterChoices['toStoryList'] = '返回需求列表'; - -$lang->task->buttonEdit = '編輯'; -$lang->task->buttonClose = '關閉'; -$lang->task->buttonCancel = '取消'; -$lang->task->buttonActivate = '激活'; -$lang->task->buttonLogEfforts = '記錄工時'; -$lang->task->buttonDelete = '刪除'; -$lang->task->buttonBackToList = '返回'; -$lang->task->buttonStart = '開始'; -$lang->task->buttonDone = '完成'; - -$lang->task->legendBasic = '基本信息'; -$lang->task->legendEffort = '工時信息'; -$lang->task->legendLife = '任務的一生'; -$lang->task->legendDesc = '任務描述'; -$lang->task->legendAction = '操作'; - -$lang->task->ajaxGetUserTasks = "介面:我的任務"; -$lang->task->ajaxGetProjectTasks = "介面:項目任務"; -$lang->task->confirmDelete = "您確定要刪除這個任務嗎?"; -$lang->task->copyStoryTitle = "同需求"; -$lang->task->afterSubmit = "添加之後"; -$lang->task->successSaved = "成功添加,"; -$lang->task->delayWarning = " 延期%s天 "; -$lang->task->remindBug = "該任務為Bug轉化得到,是否更新Bug:%s ?"; - -/* 統計報表。*/ -$lang->task->report->common = '統計報表'; -$lang->task->report->select = '請選擇報表類型'; -$lang->task->report->create = '生成報表'; -$lang->task->report->selectAll = '全選'; -$lang->task->report->selectReverse = '反選'; - -$lang->task->report->charts['tasksPerProject'] = '項目任務數統計'; -$lang->task->report->charts['tasksPerAssignedTo'] = '指派給統計'; -$lang->task->report->charts['tasksPerType'] = '任務類型統計'; -$lang->task->report->charts['tasksPerPri'] = '優先順序統計'; -$lang->task->report->charts['tasksPerStatus'] = '任務狀態統計'; -$lang->task->report->charts['tasksPerDeadline'] = '截止日期統計'; -$lang->task->report->charts['tasksPerEstimate'] = '預計時間統計'; -$lang->task->report->charts['tasksPerLeft'] = '剩餘時間統計'; -$lang->task->report->charts['tasksPerConsumed'] = '消耗時間統計'; -$lang->task->report->charts['tasksPerFinishedBy'] = '由誰完成統計'; -$lang->task->report->charts['tasksPerClosedReason'] = '關閉原因統計'; -$lang->task->report->charts['finishedTasksPerDay'] = '每天完成統計'; - -$lang->task->report->options->swf = 'pie2d'; -$lang->task->report->options->width = 'auto'; -$lang->task->report->options->height = 300; -$lang->task->report->options->graph->baseFontSize = 12; -$lang->task->report->options->graph->showNames = 1; -$lang->task->report->options->graph->formatNumber = 1; -$lang->task->report->options->graph->decimalPrecision = 0; -$lang->task->report->options->graph->animation = 0; -$lang->task->report->options->graph->rotateNames = 0; -$lang->task->report->options->graph->yAxisName = 'COUNT'; -$lang->task->report->options->graph->pieRadius = 100; // 餅圖直徑。 -$lang->task->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 - -$lang->task->report->tasksPerProject->graph->xAxisName = '項目'; -$lang->task->report->tasksPerAssignedTo->graph->xAxisName = '用戶'; -$lang->task->report->tasksPerType->graph->xAxisName = '類型'; -$lang->task->report->tasksPerPri->graph->xAxisName = '優先順序'; -$lang->task->report->tasksPerStatus->graph->xAxisName = '狀態'; -$lang->task->report->tasksPerDeadline->graph->xAxisName = '日期'; -$lang->task->report->tasksPerEstimate->graph->xAxisName = '時間'; -$lang->task->report->tasksPerLeft->graph->xAxisName = '時間'; -$lang->task->report->tasksPerConsumed->graph->xAxisName = '時間'; -$lang->task->report->tasksPerFinishedBy->graph->xAxisName = '用戶'; -$lang->task->report->tasksPerClosedReason->graph->xAxisName = '關閉原因'; - -$lang->task->report->finishedTasksPerDay->swf = 'column2d'; -$lang->task->report->finishedTasksPerDay->height = 400; -$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; -$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; + + * @package task + * @version $Id: zh-tw.php 2442 2011-12-17 02:47:00Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->task->index = "任務一覽"; +$lang->task->create = "新增任務"; +$lang->task->batchCreate = "批量添加"; +$lang->task->import = "導入之前未完任務"; +$lang->task->edit = "編輯任務"; +$lang->task->delete = "刪除任務"; +$lang->task->view = "查看任務"; +$lang->task->logEfforts = "記錄工時"; +$lang->task->start = "開始任務"; +$lang->task->finish = "完成任務"; +$lang->task->close = "關閉任務"; +$lang->task->batchClose = "批量關閉"; +$lang->task->cancel = "取消任務"; +$lang->task->activate = "激活任務"; +$lang->task->export = "導出數據"; +$lang->task->reportChart = "報表統計"; +$lang->task->fromBug = '來源Bug'; +$lang->task->confirmStoryChange = "確認需求變動"; + +$lang->task->common = '任務'; +$lang->task->id = '編號'; +$lang->task->project = '所屬項目'; +$lang->task->story = '相關需求'; +$lang->task->storyVersion = '需求版本'; +$lang->task->name = '任務名稱'; +$lang->task->type = '任務類型'; +$lang->task->pri = '優先順序'; +$lang->task->mailto = '抄送給'; +$lang->task->estimate = '最初預計'; +$lang->task->estimateAB = '預'; +$lang->task->left = '預計剩餘'; +$lang->task->leftAB = '剩'; +$lang->task->consumed = '已經消耗'; +$lang->task->consumedAB = '耗'; +$lang->task->deadline = '截止日期'; +$lang->task->deadlineAB = '截止'; +$lang->task->status = '任務狀態'; +$lang->task->statusCustom = '狀態排序'; +$lang->task->desc = '任務描述'; +$lang->task->assign = '指派'; +$lang->task->assignedTo = '指派給'; +$lang->task->assignedToAB = '指派給'; +$lang->task->assignedDate = '指派日期'; +$lang->task->openedBy = '由誰創建'; +$lang->task->openedByAB = '創建者'; +$lang->task->openedDate = '創建日期'; +$lang->task->openedDateAB = '創建'; +$lang->task->finishedBy = '由誰完成'; +$lang->task->finishedByAB = '完成者'; +$lang->task->finishedDate = '完成時間'; +$lang->task->finishedDateAB = '完成'; +$lang->task->canceledBy = '由誰取消'; +$lang->task->canceledDate = '取消時間'; +$lang->task->closedBy = '由誰關閉'; +$lang->task->closedDate = '關閉時間'; +$lang->task->closedReason = '關閉原因'; +$lang->task->lastEditedBy = '最後修改'; +$lang->task->lastEditedDate = '最後修改日期'; +$lang->task->lastEdited = '最後編輯'; + +$lang->task->same = '同上'; +$lang->task->notes = '(註:“任務類型”、“任務名稱”、“優先順序”和“預計工時”必需填寫,否則此行無效)'; + +$lang->task->statusList[''] = ''; +$lang->task->statusList['wait'] = '未開始'; +$lang->task->statusList['doing'] = '進行中'; +$lang->task->statusList['done'] = '已完成'; +$lang->task->statusList['cancel'] = '已取消'; +$lang->task->statusList['closed'] = '已關閉'; + +$lang->task->typeList[''] = ''; +$lang->task->typeList['design'] = '設計'; +$lang->task->typeList['devel'] = '開發'; +$lang->task->typeList['test'] = '測試'; +$lang->task->typeList['study'] = '研究'; +$lang->task->typeList['discuss'] = '討論'; +$lang->task->typeList['ui'] = '界面'; +$lang->task->typeList['affair'] = '事務'; +$lang->task->typeList['misc'] = '其他'; + +$lang->task->priList[0] = ''; +$lang->task->priList[3] = '3'; +$lang->task->priList[1] = '1'; +$lang->task->priList[2] = '2'; +$lang->task->priList[4] = '4'; + +$lang->task->reasonList[''] = ''; +$lang->task->reasonList['done'] = '已完成'; +$lang->task->reasonList['cancel'] = '已取消'; + +$lang->task->afterChoices['continueAdding'] = '繼續為該需求添加任務'; +$lang->task->afterChoices['toTastList'] = '返回任務列表'; +$lang->task->afterChoices['toStoryList'] = '返回需求列表'; + +$lang->task->buttonEdit = '編輯'; +$lang->task->buttonClose = '關閉'; +$lang->task->buttonCancel = '取消'; +$lang->task->buttonActivate = '激活'; +$lang->task->buttonLogEfforts = '記錄工時'; +$lang->task->buttonDelete = '刪除'; +$lang->task->buttonBackToList = '返回'; +$lang->task->buttonStart = '開始'; +$lang->task->buttonDone = '完成'; + +$lang->task->legendBasic = '基本信息'; +$lang->task->legendEffort = '工時信息'; +$lang->task->legendLife = '任務的一生'; +$lang->task->legendDesc = '任務描述'; +$lang->task->legendAction = '操作'; + +$lang->task->ajaxGetUserTasks = "介面:我的任務"; +$lang->task->ajaxGetProjectTasks = "介面:項目任務"; +$lang->task->confirmDelete = "您確定要刪除這個任務嗎?"; +$lang->task->copyStoryTitle = "同需求"; +$lang->task->afterSubmit = "添加之後"; +$lang->task->successSaved = "成功添加,"; +$lang->task->delayWarning = " 延期%s天 "; +$lang->task->remindBug = "該任務為Bug轉化得到,是否更新Bug:%s ?"; + +/* 統計報表。*/ +$lang->task->report->common = '統計報表'; +$lang->task->report->select = '請選擇報表類型'; +$lang->task->report->create = '生成報表'; +$lang->task->report->selectAll = '全選'; +$lang->task->report->selectReverse = '反選'; + +$lang->task->report->charts['tasksPerProject'] = '項目任務數統計'; +$lang->task->report->charts['tasksPerAssignedTo'] = '指派給統計'; +$lang->task->report->charts['tasksPerType'] = '任務類型統計'; +$lang->task->report->charts['tasksPerPri'] = '優先順序統計'; +$lang->task->report->charts['tasksPerStatus'] = '任務狀態統計'; +$lang->task->report->charts['tasksPerDeadline'] = '截止日期統計'; +$lang->task->report->charts['tasksPerEstimate'] = '預計時間統計'; +$lang->task->report->charts['tasksPerLeft'] = '剩餘時間統計'; +$lang->task->report->charts['tasksPerConsumed'] = '消耗時間統計'; +$lang->task->report->charts['tasksPerFinishedBy'] = '由誰完成統計'; +$lang->task->report->charts['tasksPerClosedReason'] = '關閉原因統計'; +$lang->task->report->charts['finishedTasksPerDay'] = '每天完成統計'; + +$lang->task->report->options->swf = 'pie2d'; +$lang->task->report->options->width = 'auto'; +$lang->task->report->options->height = 300; +$lang->task->report->options->graph->baseFontSize = 12; +$lang->task->report->options->graph->showNames = 1; +$lang->task->report->options->graph->formatNumber = 1; +$lang->task->report->options->graph->decimalPrecision = 0; +$lang->task->report->options->graph->animation = 0; +$lang->task->report->options->graph->rotateNames = 0; +$lang->task->report->options->graph->yAxisName = 'COUNT'; +$lang->task->report->options->graph->pieRadius = 100; // 餅圖直徑。 +$lang->task->report->options->graph->showColumnShadow = 0; // 是否顯示柱狀圖陰影。 + +$lang->task->report->tasksPerProject->graph->xAxisName = '項目'; +$lang->task->report->tasksPerAssignedTo->graph->xAxisName = '用戶'; +$lang->task->report->tasksPerType->graph->xAxisName = '類型'; +$lang->task->report->tasksPerPri->graph->xAxisName = '優先順序'; +$lang->task->report->tasksPerStatus->graph->xAxisName = '狀態'; +$lang->task->report->tasksPerDeadline->graph->xAxisName = '日期'; +$lang->task->report->tasksPerEstimate->graph->xAxisName = '時間'; +$lang->task->report->tasksPerLeft->graph->xAxisName = '時間'; +$lang->task->report->tasksPerConsumed->graph->xAxisName = '時間'; +$lang->task->report->tasksPerFinishedBy->graph->xAxisName = '用戶'; +$lang->task->report->tasksPerClosedReason->graph->xAxisName = '關閉原因'; + +$lang->task->report->finishedTasksPerDay->swf = 'column2d'; +$lang->task->report->finishedTasksPerDay->height = 400; +$lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期'; +$lang->task->report->finishedTasksPerDay->graph->rotateNames = '1'; diff --git a/module/task/model.php b/module/task/model.php index d01b919f89..5581a44ed5 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1,900 +1,900 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> -post->assignedTo as $assignedTo) - { - $task = fixer::input('post') - ->striptags('name') - ->add('project', (int)$projectID) - ->setDefault('estimate, left, story', 0) - ->setDefault('deadline', '0000-00-00') - ->setDefault('status', 'wait') - ->setIF($this->post->estimate != false, 'left', $this->post->estimate) - ->setForce('assignedTo', $assignedTo) - ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - ->setDefault('openedBy', $this->app->user->account) - ->setDefault('openedDate', helper::now()) - ->remove('after,files,labels') - ->get(); - - if($assignedTo) $task->assignedDate = helper::now(); - - $this->setStatus($task); - - $this->dao->insert(TABLE_TASK)->data($task) - ->autoCheck() - ->batchCheck($this->config->task->create->requiredFields, 'notempty') - ->checkIF($task->estimate != '', 'estimate', 'float') - ->exec(); - - if(!dao::isError()) - { - $taskID = $this->dao->lastInsertID(); - if($this->post->story) $this->loadModel('story')->setStage($this->post->story); - if(!empty($taskFile)) - { - $taskFile->objectID = $taskID; - $this->dao->insert(TABLE_FILE)->data($taskFile)->exec(); - } - else - { - $taskFileTitle = $this->loadModel('file')->saveUpload('task', $taskID); - $taskFile = $this->dao->select('*')->from(TABLE_FILE)->where('id')->eq(key($taskFileTitle))->fetch(); - unset($taskFile->id); - } - $tasksID[$assignedTo] = $taskID; - } - else - { - return false; - } - } - return $tasksID; - } - - /** - * Create a batch task. - * - * @param int $projectID - * @access public - * @return void - */ - public function batchCreate($projectID) - { - $now = helper::now(); - $tasks = fixer::input('post')->get(); - for($i = 0; $i < $this->config->task->batchCreate; $i++) - { - if($tasks->type[$i] != '' and $tasks->name[$i] != '' and $tasks->pri[$i] != 0 and $tasks->estimate[$i] != '') - { - $data[$i]->story = $tasks->story[$i] != 'same' ? $tasks->story[$i] : ($i == 0 ? 0 : $data[$i-1]->story); - $data[$i]->type = $tasks->type[$i] == 'same' ? ($i == 0 ? '' : $data[$i-1]->type) : $tasks->type[$i]; - $data[$i]->name = $tasks->name[$i]; - $data[$i]->desc = $tasks->desc[$i]; - $data[$i]->assignedTo = $tasks->assignedTo[$i]; - $data[$i]->pri = $tasks->pri[$i]; - $data[$i]->estimate = $tasks->estimate[$i]; - $data[$i]->left = $tasks->estimate[$i]; - $data[$i]->project = $projectID; - $data[$i]->deadline = '0000-00-00'; - $data[$i]->status = 'wait'; - $data[$i]->openedBy = $this->app->user->account; - $data[$i]->openedDate = $now; - $data[$i]->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, 'wait') + 1; - if($tasks->story[$i] != '') $data[$i]->storyVersion = $this->loadModel('story')->getVersion($data[$i]->story); - if($tasks->assignedTo[$i] != '') $data[$i]->assignedDate = $now; - - $this->dao->insert(TABLE_TASK)->data($data[$i]) - ->autoCheck() - ->batchCheck($this->config->task->create->requiredFields, 'notempty') - ->checkIF($data[$i]->estimate != '', 'estimate', 'float') - ->exec(); - - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - - $taskID = $this->dao->lastInsertID(); - if($tasks->story[$i] != false) $this->story->setStage($tasks->story[$i]); - $actionID = $this->loadModel('action')->create('task', $taskID, 'Opened', ''); - $mails[$i]->taskID = $taskID; - $mails[$i]->actionID = $actionID; - } - else - { - unset($tasks->story[$i]); - unset($tasks->type[$i]); - unset($tasks->name[$i]); - unset($tasks->desc[$i]); - unset($tasks->assignedTo[$i]); - unset($tasks->pri[$i]); - unset($tasks->estimate[$i]); - } - } - return $mails; - } - - /** - * Update a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function update($taskID) - { - $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->striptags('name') - ->setDefault('story, estimate, left, consumed', 0) - ->setDefault('deadline', '0000-00-00') - ->setIF($this->post->story != false and $this->post->story != $oldTask->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - - ->setIF($this->post->status == 'done', 'left', 0) - ->setIF($this->post->status == 'done' and !$this->post->finishedBy, 'finishedBy', $this->app->user->account) - ->setIF($this->post->status == 'done' and !$this->post->finishedDate, 'finishedDate', $now) - - ->setIF($this->post->status == 'cancel' and !$this->post->canceledBy, 'canceledBy', $this->app->user->account) - ->setIF($this->post->status == 'cancel' and !$this->post->canceledDate, 'canceledDate', $now) - ->setIF($this->post->status == 'cancel', 'assignedTo', $oldTask->openedBy) - ->setIF($this->post->status == 'cancel', 'assignedDate', $now) - - ->setIF($this->post->status == 'closed' and !$this->post->closedBy, 'closedBy', $this->app->user->account) - ->setIF($this->post->status == 'closed' and !$this->post->closedDate, 'closedDate', $now) - ->setIF($this->post->consumed > 0 and $this->post->left > 0 and $this->post->status == 'wait', 'status', 'doing') - - ->setIF($this->post->assignedTo != $oldTask->assignedTo, 'assignedDate', $now) - - ->setIF($this->post->status == 'wait' and $this->post->left == $oldTask->left and $this->post->consumed == 0, 'left', $this->post->estimate) - - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->remove('comment,files,labels') - ->get(); - $task->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, $task->status) + 1; - - $this->dao->update(TABLE_TASK)->data($task) - ->autoCheck() - ->batchCheckIF($task->status != 'cancel', $this->config->task->edit->requiredFields, 'notempty') - - ->checkIF($task->estimate != false, 'estimate', 'float') - ->checkIF($task->left != false, 'left', 'float') - ->checkIF($task->consumed != false, 'consumed', 'float') - ->checkIF($task->left == 0 and $task->status != 'cancel' and $task->status != 'closed', 'status', 'equal', 'done') - - ->batchCheckIF($task->status == 'wait' or $task->status == 'doing', 'finishedBy, finishedDate,canceledBy, canceledDate, closedBy, closedDate, closedReason', 'empty') - - ->checkIF($task->status == 'done', 'consumed', 'notempty') - ->checkIF($task->status == 'done' and $task->closedReason, 'closedReason', 'equal', 'done') - ->batchCheckIF($task->status == 'done', 'canceledBy, canceledDate', 'empty') - - ->checkIF($task->status == 'closed', 'closedReason', 'notempty') - ->batchCheckIF($task->closedReason == 'cancel', 'finishedBy, finishedDate', 'empty') - ->where('id')->eq((int)$taskID)->exec(); - - if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Assign a task to a user again. - * - * @param int $taskID - * @access public - * @return void - */ - public function assign($taskID) - { - $now = helper::now(); - $oldTask = $this->getById($taskID); - $this->dao->update(TABLE_TASK) - ->set('assignedTo')->eq($this->post->assignedTo) - ->set('lastEditedBy')->eq($this->app->user->account) - ->set('lastEditedDate')->eq($now) - ->where('id')->eq($taskID)->exec(); - - $actionID = $this->loadModel('action')->create('task', $taskID, 'Assigned', $this->post->comment, $this->post->assignedTo); - $this->dao->insert(TABLE_HISTORY) - ->set('company')->eq(1) - ->set('action')->eq($actionID) - ->set('field')->eq('assignedTo') - ->set('old')->eq($oldTask->assignedTo) - ->set('new')->eq($this->post->assignedTo) - ->exec(); - return $actionID; - } - - /** - * Start a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function start($taskID) - { - $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->setDefault('status', 'doing') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) - ->remove('comment')->get(); - $this->setStatus($task); - - $this->dao->update(TABLE_TASK)->data($task) - ->autoCheck() - ->check('consumed,left', 'float') - ->where('id')->eq((int)$taskID)->exec(); - - if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Finish a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function finish($taskID) - { - $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->setDefault('left', 0) - ->setDefault('assignedTo', $oldTask->openedBy) - ->setDefault('assignedDate', $now) - ->setDefault('status', 'done') - ->setDefault('finishedBy, lastEditedBy', $this->app->user->account) - ->setDefault('finishedDate, lastEditedDate', $now) - ->remove('comment')->get(); - $this->setStatus($task); - - $this->dao->update(TABLE_TASK)->data($task) - ->autoCheck() - ->check('consumed', 'notempty') - ->where('id')->eq((int)$taskID)->exec(); - - if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Close a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function close($taskID) - { - $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->setDefault('status', 'closed') - ->setDefault('assignedTo', 'closed') - ->setDefault('assignedDate', $now) - ->setDefault('closedBy, lastEditedBy', $this->app->user->account) - ->setDefault('closedDate, lastEditedDate', $now) - ->setIF($oldTask->status == 'done', 'closedReason', 'done') - ->setIF($oldTask->status == 'cancel', 'closedReason', 'cancel') - ->remove('comment')->get(); - $this->setStatus($task); - - $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); - - if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Cancel a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function cancel($taskID) - { - $oldTask = $this->getById($taskID); - $now = helper::now(); - $task = fixer::input('post') - ->setDefault('status', 'cancel') - ->setDefault('assignedTo', $oldTask->openedBy) - ->setDefault('assignedDate', $now) - ->setDefault('finishedBy', '') - ->setDefault('finishedDate', '0000-00-00') - ->setDefault('canceledBy, lastEditedBy', $this->app->user->account) - ->setDefault('canceledDate, lastEditedDate', $now) - ->remove('comment')->get(); - $this->setStatus($task); - - $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); - - if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Activate a task. - * - * @param int $taskID - * @access public - * @return void - */ - public function activate($taskID) - { - $oldTask = $this->getById($taskID); - $task = fixer::input('post') - ->setDefault('left', 0) - ->setDefault('status', 'doing') - ->setDefault('finishedBy, canceledBy, closedBy, closedReason', '') - ->setDefault('finishedDate, canceledDate, closedDate', '0000-00-00') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', helper::now()) - ->remove('comment')->get(); - $this->setStatus($task); - - $this->dao->update(TABLE_TASK)->data($task) - ->autoCheck() - ->check('left', 'notempty') - ->where('id')->eq((int)$taskID)->exec(); - - if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) return common::createChanges($oldTask, $task); - - } - - /** - * Get task info by Id. - * - * @param int $taskID - * @access public - * @return object|bool - */ - public function getById($taskID) - { - $task = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2') - ->on('t1.story = t2.id') - ->leftJoin(TABLE_USER)->alias('t3') - ->on('t1.assignedTo = t3.account') - ->where('t1.id')->eq((int)$taskID) - ->fetch(); - if(!$task) return false; - $task->desc = $this->loadModel('file')->setImgSize($task->desc); - if($task->assignedTo == 'closed') $task->assignedToRealName = 'Closed'; - foreach($task as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $task->$key = ''; - if($task->mailto) - { - $task->mailto = ltrim(trim($task->mailto), ','); // remove the first , - $task->mailto = str_replace(' ', '', $task->mailto); - $task->mailto = rtrim($task->mailto, ',') . ','; - $task->mailto = str_replace(',', ', ', $task->mailto); - } - $task->files = $this->loadModel('file')->getByObject('task', $taskID); - return $this->processTask($task); - } - - /** - * Get tasks of a project. - * - * @param int $projectID - * @param string $status all|needConfirm|wait|doing|done|cancel - * @param string $type - * @param object $pager - * @access public - * @return array - */ - public function getProjectTasks($projectID, $type = 'all', $orderBy = 'status_asc, id_desc', $pager = null) - { - $orderBy = str_replace('status', 'statusCustom', $orderBy); - $type = strtolower($type); - $tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t1.deleted')->eq(0) - ->beginIF($type == 'needconfirm')->andWhere('t2.version > t1.storyVersion')->andWhere("t2.status = 'active'")->fi() - ->beginIF($type == 'assignedtome')->andWhere('t1.assignedTo')->eq($this->app->user->account)->fi() - ->beginIF($type == 'finishedbyme')->andWhere('t1.finishedby')->eq($this->app->user->account)->fi() - ->beginIF($type == 'delayed')->andWhere('deadline')->between('1970-1-1', helper::now())->andWhere('t1.status')->in('wait,doing')->fi() - ->beginIF(strpos('all|needconfirm|assignedtome|delayed|finishedbyme', $type) === false)->andWhere('t1.status')->in($type)->fi() - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - - $sql = explode('WHERE', $this->dao->get()); - $sql = explode('ORDER', $sql[1]); - $this->session->set('taskReportCondition', $sql[0]); - - if($tasks) return $this->processTasks($tasks); - return array(); - } - - /** - * Get project tasks pairs. - * - * @param int $projectID - * @param string $status - * @param string $orderBy - * @access public - * @return array - */ - public function getProjectTaskPairs($projectID, $status = 'all', $orderBy = 'finishedBy, id_desc') - { - $tasks = array('' => ''); - $stmt = $this->dao->select('t1.id, t1.name, t2.realname AS finishedByRealName') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_USER)->alias('t2')->on('t1.finishedBy = t2.account') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t1.deleted')->eq(0) - ->beginIF($status != 'all')->andWhere('t1.status')->in($status)->fi() - ->orderBy($orderBy) - ->query(); - while($task = $stmt->fetch()) $tasks[$task->id] = "$task->id:$task->finishedByRealName:$task->name"; - return $tasks; - } - - /** - * Get tasks of a user. - * - * @param string $account - * @param string $type the query type - * @param int $limit - * @access public - * @return array - */ - public function getUserTasks($account, $type = 'assignedto', $limit = 0) - { - $type = strtolower($type); - $tasks = $this->dao->select('t1.*, t2.id as projectID, t2.name as projectName, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion') - ->from(TABLE_TASK)->alias('t1') - ->leftjoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->leftjoin(TABLE_STORY)->alias('t3') - ->on('t1.story = t3.id') - ->where('t1.deleted')->eq(0) - ->beginIF($type == 'openedby')->andWhere('t1.openedBy')->eq($account)->fi() - ->beginIF($type == 'assignedto')->andWhere('t1.assignedto')->eq($account)->fi() - ->beginIF($type == 'finishedby')->andWhere('t1.finishedby')->eq($account)->fi() - ->beginIF($type == 'closedby')->andWhere('t1.closedby')->eq($account)->fi() - ->beginIF($type == 'canceledby')->andWhere('t1.canceledby')->eq($account)->fi() - ->orderBy('id desc') - ->beginIF($limit > 0)->limit($limit)->fi() - ->fetchAll(); - if($tasks) return $this->processTasks($tasks); - return array(); - } - - /** - * Get tasks pairs of a user. - * - * @param string $account - * @param string $status - * @access public - * @return array - */ - public function getUserTaskPairs($account, $status = 'all') - { - $tasks = array(); - $sql = $this->dao->select('t1.id, t1.name, t2.name as project') - ->from(TABLE_TASK)->alias('t1') - ->leftjoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.assignedTo')->eq($account) - ->andWhere('t1.deleted')->eq(0); - if($status != 'all') $sql->andwhere('t1.status')->in($status); - $stmt = $sql->query(); - while($task = $stmt->fetch()) - { - $tasks[$task->id] = $task->project . ' / ' . $task->name; - } - return $tasks; - } - - /** - * Get task pairs of a story. - * - * @param int $storyID - * @param int $projectID - * @access public - * @return array - */ - public function getStoryTaskPairs($storyID, $projectID = 0) - { - return $this->dao->select('id, name') - ->from(TABLE_TASK) - ->where('story')->eq((int)$storyID) - ->andWhere('deleted')->eq(0) - ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() - ->fetchPairs(); - } - - /** - * Get counts of some stories' tasks. - * - * @param array $stories - * @param int $projectID - * @access public - * @return int - */ - public function getStoryTaskCounts($stories, $projectID = 0) - { - $taskCounts = $this->dao->select('story, COUNT(*) AS tasks') - ->from(TABLE_TASK) - ->where('story')->in($stories) - ->andWhere('deleted')->eq(0) - ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() - ->groupBy('story') - ->fetchPairs(); - foreach($stories as $storyID) if(!isset($taskCounts[$storyID])) $taskCounts[$storyID] = 0; - return $taskCounts; - } - - /** - * Batch process tasks. - * - * @param int $tasks - * @access private - * @return void - */ - private function processTasks($tasks) - { - $today = helper::today(); - foreach($tasks as $task) - { - /* Delayed or not. */ - if($task->status !== 'done' and $task->status !== 'cancel') - { - if($task->deadline != '0000-00-00') - { - $delay = helper::diffDate($today, $task->deadline); - if($delay > 0) $task->delay = $delay; - } - } - - /* Story changed or not. */ - $task->needConfirm = false; - if($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) - { - $task->needConfirm = true; - } - } - return $tasks; - } - - /** - * Process a task, judge it's status. - * - * @param object $task - * @access private - * @return object - */ - private function processTask($task) - { - $today = helper::today(); - - /* Delayed or not?. */ - if($task->status !== 'done' and $task->status !== 'cancel') - { - if($task->deadline != '0000-00-00') - { - if($task->status == 'closed' && $task->closedReason == 'done') - { - if($task->finishedDate == '') $delay = helper::diffDate(substr($task->closedDate, 0, 10), $task->deadline); - if($task->finishedDate != '') $delay = helper::diffDate(substr($task->finishedDate, 0, 10), $task->deadline); - } - else - { - $delay = helper::diffDate($today, $task->deadline); - } - if($delay > 0) $task->delay = $delay; - } - } - - /* Story changed or not. */ - $task->needConfirm = false; - if($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) - { - $task->needConfirm = true; - } - return $task; - } - - /** - * Set the status field of a task. - * - * @param object $task - * @access private - * @return void - */ - private function setStatus($task) - { - $task->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, $task->status) + 1; - } - - /** - * Merge the default chart settings and the settings of current chart. - * - * @param string $chartType - * @access public - * @return void - */ - public function mergeChartOption($chartType) - { - $chartOption = $this->lang->task->report->$chartType; - $commonOption = $this->lang->task->report->options; - - $chartOption->graph->caption = $this->lang->task->report->charts[$chartType]; - if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; - if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; - if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; - - /* merge configuration */ - foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; - } - - /** - * Get report data of tasks per project - * - * @access public - * @return array - */ - public function getDataOftasksPerProject() - { - $datas = $this->dao->select('project as name, count(*) as value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('project') - ->orderBy('value DESC') - ->fetchAll('name'); - if(!$datas) return array(); - $projects = $this->loadModel('project')->getPairs('all'); - foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined; - return $datas; - } - - /** - * Get report data of tasks per assignedTo - * - * @access public - * @return array - */ - public function getDataOftasksPerAssignedTo() - { - $datas = $this->dao->select('assignedTo AS name, count(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('assignedTo') - ->orderBy('value DESC') - ->fetchAll('name'); - if(!$datas) return array(); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - return $datas; - } - - /** - * Get report data of tasks per type - * - * @access public - * @return array - */ - public function getDataOftasksPerType() - { - $datas = $this->dao->select('type AS name, count(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('type') - ->orderBy('value DESC') - ->fetchAll('name'); - if(!$datas) return array(); - foreach($datas as $type => $data) if(isset($this->lang->task->typeList[$type])) $data->name = $this->lang->task->typeList[$type]; - return $datas; - } - - /** - * Get report data of tasks per priority - * - * @access public - * @return array - */ - public function getDataOftasksPerPri() - { - return $this->dao->select('pri AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('pri') - ->orderBy('value DESC') - ->fetchAll('name'); - } - - /** - * Get report data of tasks per deadline - * - * @access public - * @return array - */ - public function getDataOftasksPerDeadline() - { - return $this->dao->select('deadline AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('deadline') - ->orderBy('value DESC') - ->fetchAll('name'); - } - - /** - * Get report data of tasks per estimate - * - * @access public - * @return array - */ - public function getDataOftasksPerEstimate() - { - return $this->dao->select('estimate AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('estimate') - ->orderBy('value DESC') - ->fetchAll('name'); - } - - /** - * Get report data of tasks per left - * - * @access public - * @return array - */ - public function getDataOftasksPerLeft() - { - return $this->dao->select('`left` AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('`left`') - ->orderBy('value DESC') - ->fetchAll('name'); - } - - /** - * Get report data of tasks per consumed - * - * @access public - * @return array - */ - public function getDataOftasksPerConsumed() - { - return $this->dao->select('consumed AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('consumed') - ->orderBy('value DESC') - ->fetchAll('name'); - } - - /** - * Get report data of tasks per finishedBy - * - * @access public - * @return array - */ - public function getDataOftasksPerFinishedBy() - { - $datas = $this->dao->select('finishedBy AS name, COUNT(finishedBy) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->andWhere('finishedBy')->ne('') - ->groupBy('finishedBy') - ->orderBy('value DESC') - ->fetchAll('name'); - if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); - foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; - - return $datas; - } - - /** - * Get report data of tasks per closed reason - * - * @access public - * @return array - */ - public function getDataOftasksPerClosedReason() - { - $datas = $this->dao->select('closedReason AS name, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('closedReason') - ->orderBy('value DESC') - ->fetchAll('name'); - - foreach($datas as $closedReason => $data) - { - if(isset($this->lang->task->reasonList[$closedReason])) - { - $data->name = $this->lang->task->reasonList[$closedReason]; - } - } - return $datas; - } - - /** - * Get report data of finished tasks per day - * - * @access public - * @return array - */ - public function getDataOffinishedTasksPerDay() - { - $datas= $this->dao->select('DATE_FORMAT(finishedDate, "%Y-%m-%d") AS date, COUNT(*) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('date') - ->having('date != "0000-00-00"') - ->orderBy('finishedDate') - ->fetchAll(); - - /* Change data to name, because the task table has name field, conflicts. */ - foreach($datas as $data) - { - $data->name = $data->date; - unset($data->date); - } - return $datas; - } - - /** - * Get report data of status - * - * @access public - * @return array - */ - public function getDataOftasksPerStatus() - { - $datas = $this->dao->select('status AS name, COUNT(status) AS value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->session->taskReportCondition) - ->groupBy('status') - ->orderBy('value DESC') - ->fetchAll('name'); - if(!$datas)return array(); - foreach($datas as $status => $data) - { - $data->name = $this->lang->task->statusList[$status]; - } - return $datas; - } -} + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> +post->assignedTo as $assignedTo) + { + $task = fixer::input('post') + ->striptags('name') + ->add('project', (int)$projectID) + ->setDefault('estimate, left, story', 0) + ->setDefault('deadline', '0000-00-00') + ->setDefault('status', 'wait') + ->setIF($this->post->estimate != false, 'left', $this->post->estimate) + ->setForce('assignedTo', $assignedTo) + ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + ->setDefault('openedBy', $this->app->user->account) + ->setDefault('openedDate', helper::now()) + ->remove('after,files,labels') + ->get(); + + if($assignedTo) $task->assignedDate = helper::now(); + + $this->setStatus($task); + + $this->dao->insert(TABLE_TASK)->data($task) + ->autoCheck() + ->batchCheck($this->config->task->create->requiredFields, 'notempty') + ->checkIF($task->estimate != '', 'estimate', 'float') + ->exec(); + + if(!dao::isError()) + { + $taskID = $this->dao->lastInsertID(); + if($this->post->story) $this->loadModel('story')->setStage($this->post->story); + if(!empty($taskFile)) + { + $taskFile->objectID = $taskID; + $this->dao->insert(TABLE_FILE)->data($taskFile)->exec(); + } + else + { + $taskFileTitle = $this->loadModel('file')->saveUpload('task', $taskID); + $taskFile = $this->dao->select('*')->from(TABLE_FILE)->where('id')->eq(key($taskFileTitle))->fetch(); + unset($taskFile->id); + } + $tasksID[$assignedTo] = $taskID; + } + else + { + return false; + } + } + return $tasksID; + } + + /** + * Create a batch task. + * + * @param int $projectID + * @access public + * @return void + */ + public function batchCreate($projectID) + { + $now = helper::now(); + $tasks = fixer::input('post')->get(); + for($i = 0; $i < $this->config->task->batchCreate; $i++) + { + if($tasks->type[$i] != '' and $tasks->name[$i] != '' and $tasks->pri[$i] != 0 and $tasks->estimate[$i] != '') + { + $data[$i]->story = $tasks->story[$i] != 'same' ? $tasks->story[$i] : ($i == 0 ? 0 : $data[$i-1]->story); + $data[$i]->type = $tasks->type[$i] == 'same' ? ($i == 0 ? '' : $data[$i-1]->type) : $tasks->type[$i]; + $data[$i]->name = $tasks->name[$i]; + $data[$i]->desc = $tasks->desc[$i]; + $data[$i]->assignedTo = $tasks->assignedTo[$i]; + $data[$i]->pri = $tasks->pri[$i]; + $data[$i]->estimate = $tasks->estimate[$i]; + $data[$i]->left = $tasks->estimate[$i]; + $data[$i]->project = $projectID; + $data[$i]->deadline = '0000-00-00'; + $data[$i]->status = 'wait'; + $data[$i]->openedBy = $this->app->user->account; + $data[$i]->openedDate = $now; + $data[$i]->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, 'wait') + 1; + if($tasks->story[$i] != '') $data[$i]->storyVersion = $this->loadModel('story')->getVersion($data[$i]->story); + if($tasks->assignedTo[$i] != '') $data[$i]->assignedDate = $now; + + $this->dao->insert(TABLE_TASK)->data($data[$i]) + ->autoCheck() + ->batchCheck($this->config->task->create->requiredFields, 'notempty') + ->checkIF($data[$i]->estimate != '', 'estimate', 'float') + ->exec(); + + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + + $taskID = $this->dao->lastInsertID(); + if($tasks->story[$i] != false) $this->story->setStage($tasks->story[$i]); + $actionID = $this->loadModel('action')->create('task', $taskID, 'Opened', ''); + $mails[$i]->taskID = $taskID; + $mails[$i]->actionID = $actionID; + } + else + { + unset($tasks->story[$i]); + unset($tasks->type[$i]); + unset($tasks->name[$i]); + unset($tasks->desc[$i]); + unset($tasks->assignedTo[$i]); + unset($tasks->pri[$i]); + unset($tasks->estimate[$i]); + } + } + return $mails; + } + + /** + * Update a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function update($taskID) + { + $oldTask = $this->getById($taskID); + $now = helper::now(); + $task = fixer::input('post') + ->striptags('name') + ->setDefault('story, estimate, left, consumed', 0) + ->setDefault('deadline', '0000-00-00') + ->setIF($this->post->story != false and $this->post->story != $oldTask->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + + ->setIF($this->post->status == 'done', 'left', 0) + ->setIF($this->post->status == 'done' and !$this->post->finishedBy, 'finishedBy', $this->app->user->account) + ->setIF($this->post->status == 'done' and !$this->post->finishedDate, 'finishedDate', $now) + + ->setIF($this->post->status == 'cancel' and !$this->post->canceledBy, 'canceledBy', $this->app->user->account) + ->setIF($this->post->status == 'cancel' and !$this->post->canceledDate, 'canceledDate', $now) + ->setIF($this->post->status == 'cancel', 'assignedTo', $oldTask->openedBy) + ->setIF($this->post->status == 'cancel', 'assignedDate', $now) + + ->setIF($this->post->status == 'closed' and !$this->post->closedBy, 'closedBy', $this->app->user->account) + ->setIF($this->post->status == 'closed' and !$this->post->closedDate, 'closedDate', $now) + ->setIF($this->post->consumed > 0 and $this->post->left > 0 and $this->post->status == 'wait', 'status', 'doing') + + ->setIF($this->post->assignedTo != $oldTask->assignedTo, 'assignedDate', $now) + + ->setIF($this->post->status == 'wait' and $this->post->left == $oldTask->left and $this->post->consumed == 0, 'left', $this->post->estimate) + + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->remove('comment,files,labels') + ->get(); + $task->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, $task->status) + 1; + + $this->dao->update(TABLE_TASK)->data($task) + ->autoCheck() + ->batchCheckIF($task->status != 'cancel', $this->config->task->edit->requiredFields, 'notempty') + + ->checkIF($task->estimate != false, 'estimate', 'float') + ->checkIF($task->left != false, 'left', 'float') + ->checkIF($task->consumed != false, 'consumed', 'float') + ->checkIF($task->left == 0 and $task->status != 'cancel' and $task->status != 'closed', 'status', 'equal', 'done') + + ->batchCheckIF($task->status == 'wait' or $task->status == 'doing', 'finishedBy, finishedDate,canceledBy, canceledDate, closedBy, closedDate, closedReason', 'empty') + + ->checkIF($task->status == 'done', 'consumed', 'notempty') + ->checkIF($task->status == 'done' and $task->closedReason, 'closedReason', 'equal', 'done') + ->batchCheckIF($task->status == 'done', 'canceledBy, canceledDate', 'empty') + + ->checkIF($task->status == 'closed', 'closedReason', 'notempty') + ->batchCheckIF($task->closedReason == 'cancel', 'finishedBy, finishedDate', 'empty') + ->where('id')->eq((int)$taskID)->exec(); + + if($this->post->story != false) $this->loadModel('story')->setStage($this->post->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Assign a task to a user again. + * + * @param int $taskID + * @access public + * @return void + */ + public function assign($taskID) + { + $now = helper::now(); + $oldTask = $this->getById($taskID); + $this->dao->update(TABLE_TASK) + ->set('assignedTo')->eq($this->post->assignedTo) + ->set('lastEditedBy')->eq($this->app->user->account) + ->set('lastEditedDate')->eq($now) + ->where('id')->eq($taskID)->exec(); + + $actionID = $this->loadModel('action')->create('task', $taskID, 'Assigned', $this->post->comment, $this->post->assignedTo); + $this->dao->insert(TABLE_HISTORY) + ->set('company')->eq(1) + ->set('action')->eq($actionID) + ->set('field')->eq('assignedTo') + ->set('old')->eq($oldTask->assignedTo) + ->set('new')->eq($this->post->assignedTo) + ->exec(); + return $actionID; + } + + /** + * Start a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function start($taskID) + { + $oldTask = $this->getById($taskID); + $now = helper::now(); + $task = fixer::input('post') + ->setDefault('status', 'doing') + ->setDefault('lastEditedBy', $this->app->user->account) + ->setDefault('lastEditedDate', $now) + ->remove('comment')->get(); + $this->setStatus($task); + + $this->dao->update(TABLE_TASK)->data($task) + ->autoCheck() + ->check('consumed,left', 'float') + ->where('id')->eq((int)$taskID)->exec(); + + if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Finish a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function finish($taskID) + { + $oldTask = $this->getById($taskID); + $now = helper::now(); + $task = fixer::input('post') + ->setDefault('left', 0) + ->setDefault('assignedTo', $oldTask->openedBy) + ->setDefault('assignedDate', $now) + ->setDefault('status', 'done') + ->setDefault('finishedBy, lastEditedBy', $this->app->user->account) + ->setDefault('finishedDate, lastEditedDate', $now) + ->remove('comment')->get(); + $this->setStatus($task); + + $this->dao->update(TABLE_TASK)->data($task) + ->autoCheck() + ->check('consumed', 'notempty') + ->where('id')->eq((int)$taskID)->exec(); + + if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Close a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function close($taskID) + { + $oldTask = $this->getById($taskID); + $now = helper::now(); + $task = fixer::input('post') + ->setDefault('status', 'closed') + ->setDefault('assignedTo', 'closed') + ->setDefault('assignedDate', $now) + ->setDefault('closedBy, lastEditedBy', $this->app->user->account) + ->setDefault('closedDate, lastEditedDate', $now) + ->setIF($oldTask->status == 'done', 'closedReason', 'done') + ->setIF($oldTask->status == 'cancel', 'closedReason', 'cancel') + ->remove('comment')->get(); + $this->setStatus($task); + + $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); + + if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Cancel a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function cancel($taskID) + { + $oldTask = $this->getById($taskID); + $now = helper::now(); + $task = fixer::input('post') + ->setDefault('status', 'cancel') + ->setDefault('assignedTo', $oldTask->openedBy) + ->setDefault('assignedDate', $now) + ->setDefault('finishedBy', '') + ->setDefault('finishedDate', '0000-00-00') + ->setDefault('canceledBy, lastEditedBy', $this->app->user->account) + ->setDefault('canceledDate, lastEditedDate', $now) + ->remove('comment')->get(); + $this->setStatus($task); + + $this->dao->update(TABLE_TASK)->data($task)->autoCheck()->where('id')->eq((int)$taskID)->exec(); + + if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Activate a task. + * + * @param int $taskID + * @access public + * @return void + */ + public function activate($taskID) + { + $oldTask = $this->getById($taskID); + $task = fixer::input('post') + ->setDefault('left', 0) + ->setDefault('status', 'doing') + ->setDefault('finishedBy, canceledBy, closedBy, closedReason', '') + ->setDefault('finishedDate, canceledDate, closedDate', '0000-00-00') + ->setDefault('lastEditedBy', $this->app->user->account) + ->setDefault('lastEditedDate', helper::now()) + ->remove('comment')->get(); + $this->setStatus($task); + + $this->dao->update(TABLE_TASK)->data($task) + ->autoCheck() + ->check('left', 'notempty') + ->where('id')->eq((int)$taskID)->exec(); + + if($oldTask->story) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) return common::createChanges($oldTask, $task); + + } + + /** + * Get task info by Id. + * + * @param int $taskID + * @access public + * @return object|bool + */ + public function getById($taskID) + { + $task = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2') + ->on('t1.story = t2.id') + ->leftJoin(TABLE_USER)->alias('t3') + ->on('t1.assignedTo = t3.account') + ->where('t1.id')->eq((int)$taskID) + ->fetch(); + if(!$task) return false; + $task->desc = $this->loadModel('file')->setImgSize($task->desc); + if($task->assignedTo == 'closed') $task->assignedToRealName = 'Closed'; + foreach($task as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $task->$key = ''; + if($task->mailto) + { + $task->mailto = ltrim(trim($task->mailto), ','); // remove the first , + $task->mailto = str_replace(' ', '', $task->mailto); + $task->mailto = rtrim($task->mailto, ',') . ','; + $task->mailto = str_replace(',', ', ', $task->mailto); + } + $task->files = $this->loadModel('file')->getByObject('task', $taskID); + return $this->processTask($task); + } + + /** + * Get tasks of a project. + * + * @param int $projectID + * @param string $status all|needConfirm|wait|doing|done|cancel + * @param string $type + * @param object $pager + * @access public + * @return array + */ + public function getProjectTasks($projectID, $type = 'all', $orderBy = 'status_asc, id_desc', $pager = null) + { + $orderBy = str_replace('status', 'statusCustom', $orderBy); + $type = strtolower($type); + $tasks = $this->dao->select('t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->leftJoin(TABLE_USER)->alias('t3')->on('t1.assignedTo = t3.account') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t1.deleted')->eq(0) + ->beginIF($type == 'needconfirm')->andWhere('t2.version > t1.storyVersion')->andWhere("t2.status = 'active'")->fi() + ->beginIF($type == 'assignedtome')->andWhere('t1.assignedTo')->eq($this->app->user->account)->fi() + ->beginIF($type == 'finishedbyme')->andWhere('t1.finishedby')->eq($this->app->user->account)->fi() + ->beginIF($type == 'delayed')->andWhere('deadline')->between('1970-1-1', helper::now())->andWhere('t1.status')->in('wait,doing')->fi() + ->beginIF(strpos('all|needconfirm|assignedtome|delayed|finishedbyme', $type) === false)->andWhere('t1.status')->in($type)->fi() + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + + $sql = explode('WHERE', $this->dao->get()); + $sql = explode('ORDER', $sql[1]); + $this->session->set('taskReportCondition', $sql[0]); + + if($tasks) return $this->processTasks($tasks); + return array(); + } + + /** + * Get project tasks pairs. + * + * @param int $projectID + * @param string $status + * @param string $orderBy + * @access public + * @return array + */ + public function getProjectTaskPairs($projectID, $status = 'all', $orderBy = 'finishedBy, id_desc') + { + $tasks = array('' => ''); + $stmt = $this->dao->select('t1.id, t1.name, t2.realname AS finishedByRealName') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.finishedBy = t2.account') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t1.deleted')->eq(0) + ->beginIF($status != 'all')->andWhere('t1.status')->in($status)->fi() + ->orderBy($orderBy) + ->query(); + while($task = $stmt->fetch()) $tasks[$task->id] = "$task->id:$task->finishedByRealName:$task->name"; + return $tasks; + } + + /** + * Get tasks of a user. + * + * @param string $account + * @param string $type the query type + * @param int $limit + * @access public + * @return array + */ + public function getUserTasks($account, $type = 'assignedto', $limit = 0) + { + $type = strtolower($type); + $tasks = $this->dao->select('t1.*, t2.id as projectID, t2.name as projectName, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion') + ->from(TABLE_TASK)->alias('t1') + ->leftjoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->leftjoin(TABLE_STORY)->alias('t3') + ->on('t1.story = t3.id') + ->where('t1.deleted')->eq(0) + ->beginIF($type == 'openedby')->andWhere('t1.openedBy')->eq($account)->fi() + ->beginIF($type == 'assignedto')->andWhere('t1.assignedto')->eq($account)->fi() + ->beginIF($type == 'finishedby')->andWhere('t1.finishedby')->eq($account)->fi() + ->beginIF($type == 'closedby')->andWhere('t1.closedby')->eq($account)->fi() + ->beginIF($type == 'canceledby')->andWhere('t1.canceledby')->eq($account)->fi() + ->orderBy('id desc') + ->beginIF($limit > 0)->limit($limit)->fi() + ->fetchAll(); + if($tasks) return $this->processTasks($tasks); + return array(); + } + + /** + * Get tasks pairs of a user. + * + * @param string $account + * @param string $status + * @access public + * @return array + */ + public function getUserTaskPairs($account, $status = 'all') + { + $tasks = array(); + $sql = $this->dao->select('t1.id, t1.name, t2.name as project') + ->from(TABLE_TASK)->alias('t1') + ->leftjoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.assignedTo')->eq($account) + ->andWhere('t1.deleted')->eq(0); + if($status != 'all') $sql->andwhere('t1.status')->in($status); + $stmt = $sql->query(); + while($task = $stmt->fetch()) + { + $tasks[$task->id] = $task->project . ' / ' . $task->name; + } + return $tasks; + } + + /** + * Get task pairs of a story. + * + * @param int $storyID + * @param int $projectID + * @access public + * @return array + */ + public function getStoryTaskPairs($storyID, $projectID = 0) + { + return $this->dao->select('id, name') + ->from(TABLE_TASK) + ->where('story')->eq((int)$storyID) + ->andWhere('deleted')->eq(0) + ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() + ->fetchPairs(); + } + + /** + * Get counts of some stories' tasks. + * + * @param array $stories + * @param int $projectID + * @access public + * @return int + */ + public function getStoryTaskCounts($stories, $projectID = 0) + { + $taskCounts = $this->dao->select('story, COUNT(*) AS tasks') + ->from(TABLE_TASK) + ->where('story')->in($stories) + ->andWhere('deleted')->eq(0) + ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() + ->groupBy('story') + ->fetchPairs(); + foreach($stories as $storyID) if(!isset($taskCounts[$storyID])) $taskCounts[$storyID] = 0; + return $taskCounts; + } + + /** + * Batch process tasks. + * + * @param int $tasks + * @access private + * @return void + */ + private function processTasks($tasks) + { + $today = helper::today(); + foreach($tasks as $task) + { + /* Delayed or not. */ + if($task->status !== 'done' and $task->status !== 'cancel') + { + if($task->deadline != '0000-00-00') + { + $delay = helper::diffDate($today, $task->deadline); + if($delay > 0) $task->delay = $delay; + } + } + + /* Story changed or not. */ + $task->needConfirm = false; + if($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) + { + $task->needConfirm = true; + } + } + return $tasks; + } + + /** + * Process a task, judge it's status. + * + * @param object $task + * @access private + * @return object + */ + private function processTask($task) + { + $today = helper::today(); + + /* Delayed or not?. */ + if($task->status !== 'done' and $task->status !== 'cancel') + { + if($task->deadline != '0000-00-00') + { + if($task->status == 'closed' && $task->closedReason == 'done') + { + if($task->finishedDate == '') $delay = helper::diffDate(substr($task->closedDate, 0, 10), $task->deadline); + if($task->finishedDate != '') $delay = helper::diffDate(substr($task->finishedDate, 0, 10), $task->deadline); + } + else + { + $delay = helper::diffDate($today, $task->deadline); + } + if($delay > 0) $task->delay = $delay; + } + } + + /* Story changed or not. */ + $task->needConfirm = false; + if($task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion) + { + $task->needConfirm = true; + } + return $task; + } + + /** + * Set the status field of a task. + * + * @param object $task + * @access private + * @return void + */ + private function setStatus($task) + { + $task->statusCustom = strpos(self::CUSTOM_STATUS_ORDER, $task->status) + 1; + } + + /** + * Merge the default chart settings and the settings of current chart. + * + * @param string $chartType + * @access public + * @return void + */ + public function mergeChartOption($chartType) + { + $chartOption = $this->lang->task->report->$chartType; + $commonOption = $this->lang->task->report->options; + + $chartOption->graph->caption = $this->lang->task->report->charts[$chartType]; + if(!isset($chartOption->swf)) $chartOption->swf = $commonOption->swf; + if(!isset($chartOption->width)) $chartOption->width = $commonOption->width; + if(!isset($chartOption->height)) $chartOption->height = $commonOption->height; + + /* merge configuration */ + foreach($commonOption->graph as $key => $value) if(!isset($chartOption->graph->$key)) $chartOption->graph->$key = $value; + } + + /** + * Get report data of tasks per project + * + * @access public + * @return array + */ + public function getDataOftasksPerProject() + { + $datas = $this->dao->select('project as name, count(*) as value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('project') + ->orderBy('value DESC') + ->fetchAll('name'); + if(!$datas) return array(); + $projects = $this->loadModel('project')->getPairs('all'); + foreach($datas as $projectID => $data) $data->name = isset($projects[$projectID]) ? $projects[$projectID] : $this->lang->report->undefined; + return $datas; + } + + /** + * Get report data of tasks per assignedTo + * + * @access public + * @return array + */ + public function getDataOftasksPerAssignedTo() + { + $datas = $this->dao->select('assignedTo AS name, count(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('assignedTo') + ->orderBy('value DESC') + ->fetchAll('name'); + if(!$datas) return array(); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + return $datas; + } + + /** + * Get report data of tasks per type + * + * @access public + * @return array + */ + public function getDataOftasksPerType() + { + $datas = $this->dao->select('type AS name, count(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('type') + ->orderBy('value DESC') + ->fetchAll('name'); + if(!$datas) return array(); + foreach($datas as $type => $data) if(isset($this->lang->task->typeList[$type])) $data->name = $this->lang->task->typeList[$type]; + return $datas; + } + + /** + * Get report data of tasks per priority + * + * @access public + * @return array + */ + public function getDataOftasksPerPri() + { + return $this->dao->select('pri AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('pri') + ->orderBy('value DESC') + ->fetchAll('name'); + } + + /** + * Get report data of tasks per deadline + * + * @access public + * @return array + */ + public function getDataOftasksPerDeadline() + { + return $this->dao->select('deadline AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('deadline') + ->orderBy('value DESC') + ->fetchAll('name'); + } + + /** + * Get report data of tasks per estimate + * + * @access public + * @return array + */ + public function getDataOftasksPerEstimate() + { + return $this->dao->select('estimate AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('estimate') + ->orderBy('value DESC') + ->fetchAll('name'); + } + + /** + * Get report data of tasks per left + * + * @access public + * @return array + */ + public function getDataOftasksPerLeft() + { + return $this->dao->select('`left` AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('`left`') + ->orderBy('value DESC') + ->fetchAll('name'); + } + + /** + * Get report data of tasks per consumed + * + * @access public + * @return array + */ + public function getDataOftasksPerConsumed() + { + return $this->dao->select('consumed AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('consumed') + ->orderBy('value DESC') + ->fetchAll('name'); + } + + /** + * Get report data of tasks per finishedBy + * + * @access public + * @return array + */ + public function getDataOftasksPerFinishedBy() + { + $datas = $this->dao->select('finishedBy AS name, COUNT(finishedBy) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->andWhere('finishedBy')->ne('') + ->groupBy('finishedBy') + ->orderBy('value DESC') + ->fetchAll('name'); + if(!isset($this->users)) $this->users = $this->loadModel('user')->getPairs('noletter'); + foreach($datas as $account => $data) if(isset($this->users[$account])) $data->name = $this->users[$account]; + + return $datas; + } + + /** + * Get report data of tasks per closed reason + * + * @access public + * @return array + */ + public function getDataOftasksPerClosedReason() + { + $datas = $this->dao->select('closedReason AS name, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('closedReason') + ->orderBy('value DESC') + ->fetchAll('name'); + + foreach($datas as $closedReason => $data) + { + if(isset($this->lang->task->reasonList[$closedReason])) + { + $data->name = $this->lang->task->reasonList[$closedReason]; + } + } + return $datas; + } + + /** + * Get report data of finished tasks per day + * + * @access public + * @return array + */ + public function getDataOffinishedTasksPerDay() + { + $datas= $this->dao->select('DATE_FORMAT(finishedDate, "%Y-%m-%d") AS date, COUNT(*) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('date') + ->having('date != "0000-00-00"') + ->orderBy('finishedDate') + ->fetchAll(); + + /* Change data to name, because the task table has name field, conflicts. */ + foreach($datas as $data) + { + $data->name = $data->date; + unset($data->date); + } + return $datas; + } + + /** + * Get report data of status + * + * @access public + * @return array + */ + public function getDataOftasksPerStatus() + { + $datas = $this->dao->select('status AS name, COUNT(status) AS value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->session->taskReportCondition) + ->groupBy('status') + ->orderBy('value DESC') + ->fetchAll('name'); + if(!$datas)return array(); + foreach($datas as $status => $data) + { + $data->name = $this->lang->task->statusList[$status]; + } + return $datas; + } +} diff --git a/module/task/view/activate.html.php b/module/task/view/activate.html.php index 9559a8e69d..77d2c65ee3 100644 --- a/module/task/view/activate.html.php +++ b/module/task/view/activate.html.php @@ -1,40 +1,40 @@ - - * @package task - * @version $Id: start.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - - - -
          name;?>
          task->assignedTo;?>finishedBy, "class='select-3'");?>
          task->left;?>
          comment;?>
          - goback, $this->session->taskList); - ?> -
          - -
          - + + * @package task + * @version $Id: start.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + + + +
          name;?>
          task->assignedTo;?>finishedBy, "class='select-3'");?>
          task->left;?>
          comment;?>
          + goback, $this->session->taskList); + ?> +
          + +
          + diff --git a/module/task/view/assignto.html.php b/module/task/view/assignto.html.php index 5b0fc01030..633ff17d1f 100644 --- a/module/task/view/assignto.html.php +++ b/module/task/view/assignto.html.php @@ -1,31 +1,31 @@ - - * @package task - * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - -
          name;?>
          task->assignedTo;?>
          comment;?>
          goback, $this->session->taskList);?>
          - -
          - + + * @package task + * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + +
          name;?>
          task->assignedTo;?>
          comment;?>
          goback, $this->session->taskList);?>
          + +
          + diff --git a/module/task/view/batchcreate.html.php b/module/task/view/batchcreate.html.php index 4d4abc628c..7a1fa8f6b6 100644 --- a/module/task/view/batchcreate.html.php +++ b/module/task/view/batchcreate.html.php @@ -1,51 +1,51 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - task->batchCreate; $i++):?> - - task->typeList['same'] = $lang->task->same; $type = $i == 0 ? '' : 'same';?> - - - - - - - - - - - - - - - - -
          task->project . $lang->colon . $lang->task->batchCreate;?>
          idAB;?>task->story;?>task->name;?>task->desc;?>typeAB;?>task->assignedTo;?>task->pri;?>task->estimate;?>
          *";?>task->typeList, $type, 'class=select-1'); echo "*";?>task->priList, $pri, 'class=select-1'); echo "*";?>*";?>
          -
          task->notes;?>
          -
          -
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + task->batchCreate; $i++):?> + + task->typeList['same'] = $lang->task->same; $type = $i == 0 ? '' : 'same';?> + + + + + + + + + + + + + + + + +
          task->project . $lang->colon . $lang->task->batchCreate;?>
          idAB;?>task->story;?>task->name;?>task->desc;?>typeAB;?>task->assignedTo;?>task->pri;?>task->estimate;?>
          *";?>task->typeList, $type, 'class=select-1'); echo "*";?>task->priList, $pri, 'class=select-1'); echo "*";?>*";?>
          +
          task->notes;?>
          +
          +
          +
          + diff --git a/module/task/view/browse.html.php b/module/task/view/browse.html.php index 4252fceba5..d4fdf5bba5 100644 --- a/module/task/view/browse.html.php +++ b/module/task/view/browse.html.php @@ -1,36 +1,36 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - -
          task->browse;?>
          task->id;?>task->name;?>task->assignedTo;?>
          id;?>name;?>assignedTo;?>
          - createLink($this->moduleName, 'create', $vars); - echo "{$lang->task->create}"; - ?> -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + +
          task->browse;?>
          task->id;?>task->name;?>task->assignedTo;?>
          id;?>name;?>assignedTo;?>
          + createLink($this->moduleName, 'create', $vars); + echo "{$lang->task->create}"; + ?> +
          + diff --git a/module/task/view/cancel.html.php b/module/task/view/cancel.html.php index 07c97bede2..22625cd245 100644 --- a/module/task/view/cancel.html.php +++ b/module/task/view/cancel.html.php @@ -1,27 +1,27 @@ - - * @package task - * @version $Id: cancel.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList);?>;
          - -
          - + + * @package task + * @version $Id: cancel.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList);?>;
          + +
          + diff --git a/module/task/view/close.html.php b/module/task/view/close.html.php index e83ef9f170..fcc918d8ed 100644 --- a/module/task/view/close.html.php +++ b/module/task/view/close.html.php @@ -1,27 +1,27 @@ - - * @package task - * @version $Id: cancel.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList);?>
          - -
          - + + * @package task + * @version $Id: cancel.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList);?>
          + +
          + diff --git a/module/task/view/create.html.php b/module/task/view/create.html.php index 847e0bd994..1bd3764901 100644 --- a/module/task/view/create.html.php +++ b/module/task/view/create.html.php @@ -1,86 +1,86 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->create;?>
          task->project;?>name;?>
          task->assignedTo;?>
          task->story;?> - - preview;?> -
          task->name;?> - task->copyStoryTitle, 'onclick=copyStoryTitle()');?> -
          task->desc;?>
          task->pri;?>task->priList, '', 'class=select-3');?> -
          task->estimate;?>
          task->deadline;?>
          task->type;?>task->typeList, '', 'class=select-3 onchange="setOwners(this.value)"');?>
          task->mailto;?>
          files;?>fetch('file', 'buildform');?>
          task->afterSubmit;?>task->afterChoices, 'continueAdding');?>
          -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->create;?>
          task->project;?>name;?>
          task->assignedTo;?>
          task->story;?> + + preview;?> +
          task->name;?> + task->copyStoryTitle, 'onclick=copyStoryTitle()');?> +
          task->desc;?>
          task->pri;?>task->priList, '', 'class=select-3');?> +
          task->estimate;?>
          task->deadline;?>
          task->type;?>task->typeList, '', 'class=select-3 onchange="setOwners(this.value)"');?>
          task->mailto;?>
          files;?>fetch('file', 'buildform');?>
          task->afterSubmit;?>task->afterChoices, 'continueAdding');?>
          +
          + diff --git a/module/task/view/edit.html.php b/module/task/view/edit.html.php index ea4e867bf6..f079258339 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -1,145 +1,145 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          -
          -
          TASK #id . $lang->colon . html::input('name', $task->name, 'class="text-1"');?>
          -
          -
          - - - - - - - -
          - - -
          -
          - task->desc;?> - desc), "rows='8' class='area-1'");?> -
          -
          - comment;?> - -
          -
          - files;?> - fetch('file', 'buildform');?> -
          -
          -
          goback, $this->inlink('view', "taskID=$task->id"));?>
          - -
          -
          - task->legendBasic;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->project;?>name;?>
          task->story;?>
          story, 'class=select-1');?>
          - createLink('search', 'select', "productID=0&projectID=$project->id&module=story&storyID=$task->story"), $lang->go, "_blank", "class='search' id='searchStories'");?> -
          task->assignedTo;?>assignedTo, 'class=select-1');?> -
          task->type;?>task->typeList, $task->type, 'class=select-1');?>
          task->status;?>task->statusList, $task->status, 'class=select-1');?>
          task->pri;?>task->priList, $task->pri, 'class=select-1');?> -
          task->mailto;?>mailto, 'class="text-1"');?>
          -
          -
          - task->legendEffort;?> - - - - - - - - - - - - - - - - - -
          task->deadline;?>deadline, "class='text-1 date'");?>
          task->estimate;?>estimate, "class='text-1'");?>
          task->consumed;?>consumed, "class='text-1'");?>
          task->left;?>left, "class='text-1'");?>
          -
          -
          - task->legendLife;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->openedBy;?>openedBy];?>
          task->finishedBy;?>finishedBy, 'class="select-1"');?>
          task->finishedDate;?>finishedDate, 'class="text-1"');?>
          task->canceledBy;?>canceledBy, 'class="select-1"');?>
          task->canceledDate;?>canceledDate, 'class="text-1"');?>
          task->closedBy;?>closedBy, 'class="select-1"');?>
          task->closedReason;?>task->reasonList, $task->closedReason, 'class="select-1"');?>
          task->closedDate;?>closedDate, 'class="text-1"');?>
          -
          -
          -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          +
          +
          TASK #id . $lang->colon . html::input('name', $task->name, 'class="text-1"');?>
          +
          +
          + + + + + + + +
          + + +
          +
          + task->desc;?> + desc), "rows='8' class='area-1'");?> +
          +
          + comment;?> + +
          +
          + files;?> + fetch('file', 'buildform');?> +
          +
          +
          goback, $this->inlink('view', "taskID=$task->id"));?>
          + +
          +
          + task->legendBasic;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->project;?>name;?>
          task->story;?>
          story, 'class=select-1');?>
          + createLink('search', 'select', "productID=0&projectID=$project->id&module=story&storyID=$task->story"), $lang->go, "_blank", "class='search' id='searchStories'");?> +
          task->assignedTo;?>assignedTo, 'class=select-1');?> +
          task->type;?>task->typeList, $task->type, 'class=select-1');?>
          task->status;?>task->statusList, $task->status, 'class=select-1');?>
          task->pri;?>task->priList, $task->pri, 'class=select-1');?> +
          task->mailto;?>mailto, 'class="text-1"');?>
          +
          +
          + task->legendEffort;?> + + + + + + + + + + + + + + + + + +
          task->deadline;?>deadline, "class='text-1 date'");?>
          task->estimate;?>estimate, "class='text-1'");?>
          task->consumed;?>consumed, "class='text-1'");?>
          task->left;?>left, "class='text-1'");?>
          +
          +
          + task->legendLife;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->openedBy;?>openedBy];?>
          task->finishedBy;?>finishedBy, 'class="select-1"');?>
          task->finishedDate;?>finishedDate, 'class="text-1"');?>
          task->canceledBy;?>canceledBy, 'class="select-1"');?>
          task->canceledDate;?>canceledDate, 'class="text-1"');?>
          task->closedBy;?>closedBy, 'class="select-1"');?>
          task->closedReason;?>task->reasonList, $task->closedReason, 'class="select-1"');?>
          task->closedDate;?>closedDate, 'class="text-1"');?>
          +
          +
          +
          + diff --git a/module/task/view/export.html.php b/module/task/view/export.html.php index aa3d46e4d1..4ede69eed3 100755 --- a/module/task/view/export.html.php +++ b/module/task/view/export.html.php @@ -1,13 +1,13 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + diff --git a/module/task/view/finish.html.php b/module/task/view/finish.html.php index 1ab97dd691..3b8e99700a 100644 --- a/module/task/view/finish.html.php +++ b/module/task/view/finish.html.php @@ -1,31 +1,31 @@ - - * @package task - * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - -
          name;?>
          task->consumed;?>consumed, "class='text-3'");?>
          comment;?>
          goback, $this->session->taskList);?>
          - -
          - + + * @package task + * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + +
          name;?>
          task->consumed;?>consumed, "class='text-3'");?>
          comment;?>
          goback, $this->session->taskList);?>
          + +
          + diff --git a/module/task/view/import.html.php b/module/task/view/import.html.php index c5a9066c16..08bd2e5109 100644 --- a/module/task/view/import.html.php +++ b/module/task/view/import.html.php @@ -1,58 +1,58 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - assignedTo == $app->user->account ? 'style=color:red' : '';?> - - - - - - - - - - - - - - - -
          task->id;?>task->pri;?>task->name;?>task->assignedTo;?>task->estimate;?>task->consumed;?>task->left;?>task->type;?>task->status;?>task->story;?>actions;?>
          createLink('task', 'view', "task=$task->id"), sprintf('%03d', $task->id)); else printf('%03d', $task->id);?>pri;?>name;?>>assignedToRealName;?>estimate;?>consumed;?>left;?>task->typeList[$task->type];?>status;?> >task->statusList->{$task->status};?> - storyID) - { - if(common::hasPriv('story', 'view')) echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); - else echo $task->storyTitle; - } - ?> - -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + assignedTo == $app->user->account ? 'style=color:red' : '';?> + + + + + + + + + + + + + + + +
          task->id;?>task->pri;?>task->name;?>task->assignedTo;?>task->estimate;?>task->consumed;?>task->left;?>task->type;?>task->status;?>task->story;?>actions;?>
          createLink('task', 'view', "task=$task->id"), sprintf('%03d', $task->id)); else printf('%03d', $task->id);?>pri;?>name;?>>assignedToRealName;?>estimate;?>consumed;?>left;?>task->typeList[$task->type];?>status;?> >task->statusList->{$task->status};?> + storyID) + { + if(common::hasPriv('story', 'view')) echo html::a($this->createLink('story', 'view', "storyid=$task->storyID"), $task->storyTitle); + else echo $task->storyTitle; + } + ?> + +
          + diff --git a/module/task/view/report.html.php b/module/task/view/report.html.php index 5e2042ddff..d2d34dea6c 100644 --- a/module/task/view/report.html.php +++ b/module/task/view/report.html.php @@ -1,63 +1,63 @@ - - * @package project - * @version $Id: report.html.php 1594 2011-04-10 11:00:00Z wj $ - * @link http://www.zentao.net - */ -?> - -
          -
          report->common;?>
          -
          goback); ?>
          -
          - - - - - - - -
          -
          task->report->select;?>
          -
          -
          - task->report->charts, $checkedCharts)?> - - -

          - task->report->create);?> -
          -
          -
          - - - $chartContent):?> - - - - - -
          task->report->common;?>
          - - - - - - - $data):?> - - - - - - -
          report->item;?>report->value;?>report->percent;?>
          name;?>value;?>percent * 100) . '%';?>
          -
          -
          - - + + * @package project + * @version $Id: report.html.php 1594 2011-04-10 11:00:00Z wj $ + * @link http://www.zentao.net + */ +?> + +
          +
          report->common;?>
          +
          goback); ?>
          +
          + + + + + + + +
          +
          task->report->select;?>
          +
          +
          + task->report->charts, $checkedCharts)?> + + +

          + task->report->create);?> +
          +
          +
          + + + $chartContent):?> + + + + + +
          task->report->common;?>
          + + + + + + + $data):?> + + + + + + +
          report->item;?>report->value;?>report->percent;?>
          name;?>value;?>percent * 100) . '%';?>
          +
          +
          + + diff --git a/module/task/view/sendmail.html.php b/module/task/view/sendmail.html.php index ea61b10556..a29d8c6cd6 100644 --- a/module/task/view/sendmail.html.php +++ b/module/task/view/sendmail.html.php @@ -1,22 +1,22 @@ - - * @package task - * @version $Id: sendmail.html.php 867 2010-06-17 09:32:58Z yuren_@126.com $ - * @link http://www.zentao.net - */ -?> - - - - - - - -
          - TASK #id . "=>$task->assignedTo " . html::a(common::getSysURL() . $this->createLink('task', 'view', "taskID=$task->id"), $task->name);?> -
          + + * @package task + * @version $Id: sendmail.html.php 867 2010-06-17 09:32:58Z yuren_@126.com $ + * @link http://www.zentao.net + */ +?> + + + + + + + +
          + TASK #id . "=>$task->assignedTo " . html::a(common::getSysURL() . $this->createLink('task', 'view', "taskID=$task->id"), $task->name);?> +
          diff --git a/module/task/view/start.html.php b/module/task/view/start.html.php index ca03aad749..2786789be4 100644 --- a/module/task/view/start.html.php +++ b/module/task/view/start.html.php @@ -1,35 +1,35 @@ - - * @package task - * @version $Id: start.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - - - -
          name;?>
          task->consumed;?>consumed, "class='text-3'");?>
          task->left;?>left, "class='text-3'");?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package task + * @version $Id: start.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + + + +
          name;?>
          task->consumed;?>consumed, "class='text-3'");?>
          task->left;?>left, "class='text-3'");?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index f4c7f6dfdb..8386046ca8 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -1,182 +1,182 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -fromBug == 0):?> -
          '>TASK #id . $lang->colon . $task->name;?>
          - -
          '>TASK #id . $lang->colon . $task->name . '('. $lang->task->fromBug . $lang->colon . $task->fromBug . ')';?>
          - -
          - session->taskList != false ? $app->session->taskList : $this->createLink('project', 'browse', "projectID=$task->project"); - if(!$task->deleted) - { - //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'logEfforts', "taskID=$task->id", $lang->task->buttonLogEfforts))) echo $lang->task->buttonLogEfforts . ' '; - if(!(($task->status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; - if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; - if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; - if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' '; - if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; - if(!common::printLink('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $lang->task->assign)) echo $lang->task->assign . ' '; - if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; - if(common::hasPriv('task', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' '; - } - echo html::a($browseLink, $lang->goback); - ?> -
          -
          - - - - - - - -
          -
          - task->legendDesc;?> -
          desc;?>
          -
          - fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true'));?> - -
          - deleted) - { - if(!(($task->status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; - if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; - if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; - if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' '; - if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; - if(!common::printLink('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $lang->task->assign)) echo $lang->task->assign . ' '; - if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; - if(common::hasPriv('task', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' '; - } - echo html::a($browseLink, $lang->goback); - ?> -
          - -
          -
          - task->legendBasic;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->project;?>project", $project->name)) echo $project->name;?>
          task->story;?> - storyTitle and !common::printLink('story', 'view', "storyID=$task->story", $task->storyTitle)) echo $task->storyTitle; - if($task->needConfirm) - { - echo "({$lang->story->changed} "; - echo html::a($this->createLink('task', 'confirmStoryChange', "taskID=$task->id"), $lang->confirm, 'hiddenwin'); - echo ")"; - } - ?> -
          task->assignedTo;?>assignedToRealName . $lang->at . $task->assignedDate;?>
          task->type;?>task->typeList[$task->type];?>
          task->status;?>show($lang->task->statusList, $task->status);?>
          task->pri;?>show($lang->task->priList, $task->pri);?>
          task->mailto;?>mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
          -
          -
          - task->legendEffort;?> - - - - - - - - - - - - - - - - - -
          task->deadline;?> - deadline; - if(isset($task->delay)) printf($lang->task->delayWarning, $task->delay); - ?> -
          task->estimate;?>estimate . $lang->workingHour;?>
          task->consumed;?>consumed . $lang->workingHour;?>
          task->left;?>left . $lang->workingHour;?>
          -
          -
          - task->legendLife;?> - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->openedBy;?>openedBy) echo $users[$task->openedBy] . $lang->at . $task->openedDate;?>
          task->finishedBy;?>finishedBy) echo $users[$task->finishedBy] . $lang->at . $task->finishedDate;?>
          task->canceledBy;?>canceledBy) echo $users[$task->canceledBy] . $lang->at . $task->canceledDate;?>
          task->closedBy;?>closedBy) echo $users[$task->closedBy] . $lang->at . $task->closedDate;?>
          task->closedReason;?>task->reasonList[$task->closedReason];?>
          task->lastEdited;?>lastEditedBy) echo $users[$task->lastEditedBy] . $lang->at . $task->lastEditedDate;?>
          -
          -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +fromBug == 0):?> +
          '>TASK #id . $lang->colon . $task->name;?>
          + +
          '>TASK #id . $lang->colon . $task->name . '('. $lang->task->fromBug . $lang->colon . $task->fromBug . ')';?>
          + +
          + session->taskList != false ? $app->session->taskList : $this->createLink('project', 'browse', "projectID=$task->project"); + if(!$task->deleted) + { + //if(!($task->status != 'closed' and $task->status != 'cancel' and common::printLink('task', 'logEfforts', "taskID=$task->id", $lang->task->buttonLogEfforts))) echo $lang->task->buttonLogEfforts . ' '; + if(!(($task->status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; + if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; + if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; + if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' '; + if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; + if(!common::printLink('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $lang->task->assign)) echo $lang->task->assign . ' '; + if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; + if(common::hasPriv('task', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' '; + } + echo html::a($browseLink, $lang->goback); + ?> +
          +
          + + + + + + + +
          +
          + task->legendDesc;?> +
          desc;?>
          +
          + fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true'));?> + +
          + deleted) + { + if(!(($task->status == 'wait') and common::printLink('task', 'start', "taskID=$task->id", $lang->task->buttonStart))) echo $lang->task->buttonStart . ' '; + if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'finish', "taskID=$task->id", $lang->task->buttonDone))) echo $lang->task->buttonDone . ' '; + if(!(($task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'close', "taskID=$task->id", $lang->task->buttonClose))) echo $lang->task->buttonClose . ' '; + if(!(($task->status == 'wait' or $task->status == 'doing') and common::printLink('task', 'cancel', "taskID=$task->id", $lang->task->buttonCancel))) echo $lang->task->buttonCancel . ' '; + if(!(($task->status == 'closed' or $task->status == 'done' or $task->status == 'cancel') and common::printLink('task', 'activate', "taskID=$task->id", $lang->task->buttonActivate))) echo $lang->task->buttonActivate . ' '; + if(!common::printLink('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $lang->task->assign)) echo $lang->task->assign . ' '; + if(!common::printLink('task', 'edit', "taskID=$task->id", $lang->task->buttonEdit)) echo $lang->task->buttonEdit . ' '; + if(common::hasPriv('task', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + if(!common::printLink('task', 'delete',"projectID=$task->project&taskID=$task->id", $lang->task->buttonDelete, 'hiddenwin')) echo $lang->task->buttonDelete . ' '; + } + echo html::a($browseLink, $lang->goback); + ?> +
          + +
          +
          + task->legendBasic;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->project;?>project", $project->name)) echo $project->name;?>
          task->story;?> + storyTitle and !common::printLink('story', 'view', "storyID=$task->story", $task->storyTitle)) echo $task->storyTitle; + if($task->needConfirm) + { + echo "({$lang->story->changed} "; + echo html::a($this->createLink('task', 'confirmStoryChange', "taskID=$task->id"), $lang->confirm, 'hiddenwin'); + echo ")"; + } + ?> +
          task->assignedTo;?>assignedToRealName . $lang->at . $task->assignedDate;?>
          task->type;?>task->typeList[$task->type];?>
          task->status;?>show($lang->task->statusList, $task->status);?>
          task->pri;?>show($lang->task->priList, $task->pri);?>
          task->mailto;?>mailto)); foreach($mailto as $account) echo ' ' . $users[$account]; ?>
          +
          +
          + task->legendEffort;?> + + + + + + + + + + + + + + + + + +
          task->deadline;?> + deadline; + if(isset($task->delay)) printf($lang->task->delayWarning, $task->delay); + ?> +
          task->estimate;?>estimate . $lang->workingHour;?>
          task->consumed;?>consumed . $lang->workingHour;?>
          task->left;?>left . $lang->workingHour;?>
          +
          +
          + task->legendLife;?> + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->openedBy;?>openedBy) echo $users[$task->openedBy] . $lang->at . $task->openedDate;?>
          task->finishedBy;?>finishedBy) echo $users[$task->finishedBy] . $lang->at . $task->finishedDate;?>
          task->canceledBy;?>canceledBy) echo $users[$task->canceledBy] . $lang->at . $task->canceledDate;?>
          task->closedBy;?>closedBy) echo $users[$task->closedBy] . $lang->at . $task->closedDate;?>
          task->closedReason;?>task->reasonList[$task->closedReason];?>
          task->lastEdited;?>lastEditedBy) echo $users[$task->lastEditedBy] . $lang->at . $task->lastEditedDate;?>
          +
          +
          + diff --git a/module/testcase/control.php b/module/testcase/control.php index b03f074c90..462364e41a 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -1,545 +1,545 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -class testcase extends control -{ - private $products = array(); - - /** - * Construct function, load product, tree, user auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('product'); - $this->loadModel('tree'); - $this->loadModel('user'); - $this->view->products = $this->products = $this->product->getPairs(); - } - - /** - * Index page. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('testcase', 'browse')); - } - - /** - * Browse cases. - * - * @param int $productID - * @param string $browseType - * @param int $param - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Set browseType, productID, moduleID and queryID. */ - $browseType = strtolower($browseType); - $productID = $this->product->saveState($productID, $this->products); - $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Set menu, save session. */ - $this->testcase->setMenu($this->products, $productID); - $this->session->set('caseList', $this->app->getURI(true)); - $this->session->set('productID', $productID); - $this->session->set('moduleID', $moduleID); - $this->session->set('browseType', $browseType); - $this->session->set('orderBy', $orderBy); - - /* Load lang. */ - $this->app->loadLang('testtask'); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* By module or all cases. */ - if($browseType == 'bymodule' or $browseType == 'all') - { - $childModuleIds = $this->tree->getAllChildId($moduleID); - $this->view->cases = $this->testcase->getModuleCases($productID, $childModuleIds, $orderBy, $pager); - } - /* Cases need confirmed. */ - elseif($browseType == 'needconfirm') - { - $this->view->cases = $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_CASE)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') - ->where("t2.status = 'active'") - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t2.version > t1.storyVersion') - ->orderBy($orderBy) - ->fetchAll(); - } - /* By search. */ - elseif($browseType == 'bysearch') - { - if($queryID) - { - $query = $this->loadModel('search')->getQuery($queryID); - if($query) - { - $this->session->set('testcaseQuery', $query->sql); - $this->session->set('testcaseForm', $query->form); - } - else - { - $this->session->set('testcaseQuery', ' 1 = 1'); - } - } - else - { - if($this->session->testcaseQuery == false) $this->session->set('testcaseQuery', ' 1 = 1'); - } - - $caseQuery = str_replace("`product` = 'all'", '1', $this->session->testcaseQuery); // If product is all, change it to 1=1. - $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery) - ->andWhere('product')->eq($productID) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /* save session .*/ - $sql = $this->dao->get(); - $sql = explode('WHERE', $sql); - $sql = explode('ORDER', $sql[1]); - $this->session->set('testcaseReport', $sql[0]); - - /* Build the search form. */ - $this->config->testcase->search['params']['product']['values']= array($productID => $this->products[$productID], 'all' => $this->lang->testcase->allProduct); - $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case'); - $this->config->testcase->search['actionURL'] = $this->createLink('testcase', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); - $this->config->testcase->search['queryID'] = $queryID; - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->testcase->search); - - /* Assign. */ - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common; - $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testcase->common; - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createCaseLink')); - $this->view->moduleID = $moduleID; - $this->view->pager = $pager; - $this->view->users = $this->user->getPairs('noletter'); - $this->view->orderBy = $orderBy; - $this->view->browseType = $browseType; - $this->view->param = $param; - $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; - - $this->display(); - } - - /** - * Create a test case. - * - * @param int $productID - * @param int $moduleID - * @param string $from - * @param int $param - * @access public - * @return void - */ - public function create($productID, $moduleID = 0, $from = '', $param = 0, $storyID = 0) - { - $testcaseID = $from == 'testcase' ? $param : 0; - $bugID = $from == 'bug' ? $param : 0; - - $this->loadModel('story'); - if(!empty($_POST)) - { - $caseID = $this->testcase->create($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action'); - $this->action->create('case', $caseID, 'Opened'); - die(js::locate($this->createLink('testcase', 'browse', "productID=$_POST[product]&browseType=byModule¶m=$_POST[module]"), 'parent')); - } - if(empty($this->products)) $this->locate($this->createLink('product', 'create')); - - /* Set productID and currentModuleID. */ - $productID = $this->product->saveState($productID, $this->products); - $currentModuleID = (int)$moduleID; - - /* Set menu. */ - $this->testcase->setMenu($this->products, $productID); - - /* Init vars. */ - $type = 'feature'; - $stage = ''; - $pri = 0; - $title = ''; - $precondition = ''; - $keywords = ''; - $steps = array(); - - /* If testcaseID large than 0, use this testcase as template. */ - if($testcaseID > 0) - { - $testcase = $this->testcase->getById($testcaseID); - $productID = $testcase->product; - $type = $testcase->type ? $testcase->type : 'feature'; - $stage = $testcase->stage; - $pri = $testcase->pri; - $storyID = $testcase->story; - $title = $testcase->title; - $precondition = $testcase->precondition; - $keywords = $testcase->keywords; - $steps = $testcase->steps; - } - - /* If bugID large than 0, use this bug as template. */ - if($bugID > 0) - { - $bug = $this->loadModel('bug')->getById($bugID); - $type = $bug->type; - $pri = $bug->pri ? $bug->pri : $bug->severity; - $storyID = $bug->story; - $title = $bug->title; - $keywords = $bug->keywords; - $steps = $this->testcase->createStepsFromBug($bug->steps); - } - - /* Padding the steps to the default steps count. */ - if(count($steps) < $this->config->testcase->defaultSteps) - { - $paddingCount = $this->config->testcase->defaultSteps - count($steps); - $step->desc = ''; - $step->expect = ''; - for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step; - } - - $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->create; - $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $position[] = $this->lang->testcase->create; - - $users = $this->user->getPairs(); - $this->view->header = $header; - $this->view->position = $position; - $this->view->productID = $productID; - $this->view->users = $users; - $this->view->productName = $this->products[$productID]; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); - $this->view->currentModuleID = $currentModuleID; - $this->view->stories = $this->story->getProductStoryPairs($productID); - $this->view->type = $type; - $this->view->stage = $stage; - $this->view->pri = $pri; - $this->view->storyID = $storyID; - $this->view->title = $title; - $this->view->precondition = $precondition; - $this->view->keywords = $keywords; - $this->view->steps = $steps; - - $this->display(); - } - - - /** - * Create a batch test case. - * - * @param int $productID - * @param int $moduleID - * @param int $testcaseID - * @access public - * @return void - */ - public function batchCreate($productID, $moduleID = 0) - { - $this->loadModel('story'); - if(!empty($_POST)) - { - $caseID = $this->testcase->batchCreate($productID); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('testcase', 'browse', "productID=$_POST[product]&browseType=byModule¶m=$_POST[module]"), 'parent')); - } - if(empty($this->products)) $this->locate($this->createLink('product', 'create')); - - /* Set productID and currentModuleID. */ - $productID = $this->product->saveState($productID, $this->products); - $currentModuleID = (int)$moduleID; - - /* Set menu. */ - $this->testcase->setMenu($this->products, $productID); - - /* Init vars. */ - $type = 'feature'; - $title = ''; - - $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->batchCreate; - $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $position[] = $this->lang->testcase->batchCreate; - - $users = $this->user->getPairs(); - $this->view->header = $header; - $this->view->position = $position; - $this->view->productID = $productID; - $this->view->users = $users; - $this->view->productName = $this->products[$productID]; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); - $this->view->currentModuleID = $currentModuleID; - $this->view->stories = $this->story->getProductStoryPairs($productID); - $this->view->type = $type; - $this->view->title = $title; - - $this->display(); - } - - /** - * View a test case. - * - * @param int $caseID - * @param int $version - * @access public - * @return void - */ - public function view($caseID, $version = 0) - { - $case = $this->testcase->getById($caseID, $version); - if(!$case) die(js::error($this->lang->notFound) . js::locate('back')); - - $productID = $case->product; - $this->testcase->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->view; - $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testcase->view; - - $this->view->case = $case; - $this->view->productName = $this->products[$productID]; - $this->view->modulePath = $this->tree->getParents($case->module); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->actions = $this->loadModel('action')->getList('case', $caseID); - - $this->display(); - } - - /** - * Edit a case. - * - * @param int $caseID - * @access public - * @return void - */ - public function edit($caseID) - { - $this->loadModel('story'); - - if(!empty($_POST)) - { - $changes = $this->testcase->update($caseID); - if(dao::isError()) die(js::error(dao::getError())); - $files = $this->loadModel('file')->saveUpload('testcase', $caseID); - if($this->post->comment != '' or !empty($changes) or !empty($files)) - { - $this->loadModel('action'); - $action = !empty($changes) ? 'Edited' : 'Commented'; - $fileAction = ''; - if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; - $actionID = $this->action->create('case', $caseID, $action, $fileAction . $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent')); - } - - $case = $this->testcase->getById($caseID); - if(empty($case->steps)) - { - $step->desc = ''; - $step->expect = ''; - $case->steps[] = $step; - } - $productID = $case->product; - $currentModuleID = $case->module; - $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->edit; - $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $position[] = $this->lang->testcase->edit; - - /* Set menu. */ - $this->testcase->setMenu($this->products, $productID); - - $users = $this->user->getPairs(); - $this->view->header = $header; - $this->view->position = $position; - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); - $this->view->currentModuleID = $currentModuleID; - $this->view->users = $users; - $this->view->stories = $this->story->getProductStoryPairs($productID); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->case = $case; - $this->view->actions = $this->loadModel('action')->getList('case', $caseID); - - $this->display(); - } - - /** - * Delete a test case - * - * @param int $caseID - * @param string $confirm yes|noe - * @access public - * @return void - */ - public function delete($caseID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->testcase->confirmDelete, inlink('delete', "caseID=$caseID&confirm=yes"))); - } - else - { - $this->testcase->delete(TABLE_CASE, $caseID); - die(js::locate($this->session->caseList, 'parent')); - } - } - - /** - * Confirm story changes. - * - * @param int $caseID - * @access public - * @return void - */ - public function confirmStoryChange($caseID) - { - $case = $this->testcase->getById($caseID); - $this->dao->update(TABLE_CASE)->set('storyVersion')->eq($case->latestStoryVersion)->where('id')->eq($caseID)->exec(); - $this->loadModel('action')->create('case', $caseID, 'confirmed', '', $case->latestStoryVersion); - die(js::reload('parent')); - } - - /** - * export - * - * @param string $productID - * @param string $orderBy - * @access public - * @return void - */ - public function export($productID, $orderBy) - { - if($_POST) - { - $caseLang = $this->lang->testcase; - $caseConfig = $this->config->testcase; - - /* Create field lists. */ - $fields = explode(',', $caseConfig->exportFields); - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($caseLang->$fieldName) ? $caseLang->$fieldName : $fieldName; - unset($fields[$key]); - } - - /* Get cases. */ - $cases = $this->dao->select('*')->from(TABLE_CASE)->alias('t1')->where($this->session->testcaseReport)->orderBy($orderBy)->fetchAll('id'); - - /* Get users, products and projects. */ - $users = $this->loadModel('user')->getPairs('noletter'); - $products = $this->loadModel('product')->getPairs(); - - /* Get related objects id lists. */ - $relatedModuleIdList = array(); - $relatedStoryIdList = array(); - $relatedCaseIdList = array(); - - foreach($cases as $case) - { - $relatedModuleIdList[$case->module] = $case->module; - $relatedStoryIdList[$case->story] = $case->story; - $relatedCaseIdList[$case->linkCase] = $case->linkCase; - - /* Process link cases. */ - $linkCases = explode(',', $case->linkCase); - foreach($linkCases as $linkCaseID) - { - if($linkCaseID) $relatedCaseIdList[$linkCaseID] = trim($linkCaseID); - } - } - - /* Get related objects title or names. */ - $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); - $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); - $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); - $relatedSteps = $this->dao->select('`case`, version, `desc`, expect')->from(TABLE_CASESTEP)->where('`case`')->in(@array_keys($cases))->orderBy('version desc,id')->fetchGroup('case'); - - foreach($cases as $case) - { - $case->steps = ''; - if(isset($relatedSteps[$case->id])) - { - $i = 1; - foreach($relatedSteps[$case->id] as $step) - { - $case->steps .= $i . ":" . $step->desc . '
          ' . $caseLang->stepExpect . ':' . $step->expect . '
          '; - $i ++; - if($step->version != $case->version) break; - } - } - - if($this->post->fileType == 'csv') - { - $case->steps = str_replace('
          ', "\n", $case->steps); - $case->steps = str_replace('"', '""', $case->steps); - } - - /* fill some field with useful value. */ - if(isset($products[$case->product])) $case->product = $products[$case->product]; - if(isset($relatedModules[$case->module])) $case->module = $relatedModules[$case->module]; - if(isset($relatedStories[$case->story])) $case->story = $relatedStories[$case->story]; - - if(isset($caseLang->priList[$case->pri])) $case->pri = $caseLang->priList[$case->pri]; - if(isset($caseLang->typeList[$case->type])) $case->type = $caseLang->typeList[$case->type]; - if(isset($caseLang->stageList[$case->stage])) $case->stage = $caseLang->stageList[$case->stage]; - if(isset($caseLang->statusList[$case->status])) $case->status = $caseLang->statusList[$case->status]; - if(isset($users[$case->openedBy])) $case->openedBy = $users[$case->openedBy]; - if(isset($users[$case->lastEditedBy])) $case->lastEditedBy = $users[$case->lastEditedBy]; - - $case->openedDate = substr($case->openedDate, 0, 10); - $case->lastEditedDate = substr($case->lastEditedDate, 0, 10); - - if($case->linkCase) - { - $tmpLinkCases = array(); - $linkCaseIdList = explode(',', $case->linkCase); - foreach($linkCaseIdList as $linkCaseID) - { - $linkCaseID = trim($linkCaseID); - $tmpLinkCases[] = isset($relatedCases[$linkCaseID]) ? $relatedCases[$linkCaseID] : $linkCaseID; - } - $case->linkCase = join("; \n", $tmpLinkCases); - } - } - - $this->post->set('fields', $fields); - $this->post->set('rows', $cases); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +class testcase extends control +{ + private $products = array(); + + /** + * Construct function, load product, tree, user auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('product'); + $this->loadModel('tree'); + $this->loadModel('user'); + $this->view->products = $this->products = $this->product->getPairs(); + } + + /** + * Index page. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('testcase', 'browse')); + } + + /** + * Browse cases. + * + * @param int $productID + * @param string $browseType + * @param int $param + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($productID = 0, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Set browseType, productID, moduleID and queryID. */ + $browseType = strtolower($browseType); + $productID = $this->product->saveState($productID, $this->products); + $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Set menu, save session. */ + $this->testcase->setMenu($this->products, $productID); + $this->session->set('caseList', $this->app->getURI(true)); + $this->session->set('productID', $productID); + $this->session->set('moduleID', $moduleID); + $this->session->set('browseType', $browseType); + $this->session->set('orderBy', $orderBy); + + /* Load lang. */ + $this->app->loadLang('testtask'); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* By module or all cases. */ + if($browseType == 'bymodule' or $browseType == 'all') + { + $childModuleIds = $this->tree->getAllChildId($moduleID); + $this->view->cases = $this->testcase->getModuleCases($productID, $childModuleIds, $orderBy, $pager); + } + /* Cases need confirmed. */ + elseif($browseType == 'needconfirm') + { + $this->view->cases = $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_CASE)->alias('t1')->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where("t2.status = 'active'") + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.version > t1.storyVersion') + ->orderBy($orderBy) + ->fetchAll(); + } + /* By search. */ + elseif($browseType == 'bysearch') + { + if($queryID) + { + $query = $this->loadModel('search')->getQuery($queryID); + if($query) + { + $this->session->set('testcaseQuery', $query->sql); + $this->session->set('testcaseForm', $query->form); + } + else + { + $this->session->set('testcaseQuery', ' 1 = 1'); + } + } + else + { + if($this->session->testcaseQuery == false) $this->session->set('testcaseQuery', ' 1 = 1'); + } + + $caseQuery = str_replace("`product` = 'all'", '1', $this->session->testcaseQuery); // If product is all, change it to 1=1. + $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery) + ->andWhere('product')->eq($productID) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /* save session .*/ + $sql = $this->dao->get(); + $sql = explode('WHERE', $sql); + $sql = explode('ORDER', $sql[1]); + $this->session->set('testcaseReport', $sql[0]); + + /* Build the search form. */ + $this->config->testcase->search['params']['product']['values']= array($productID => $this->products[$productID], 'all' => $this->lang->testcase->allProduct); + $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case'); + $this->config->testcase->search['actionURL'] = $this->createLink('testcase', 'browse', "productID=$productID&browseType=bySearch&queryID=myQueryID"); + $this->config->testcase->search['queryID'] = $queryID; + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->testcase->search); + + /* Assign. */ + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->common; + $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testcase->common; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleTree = $this->tree->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createCaseLink')); + $this->view->moduleID = $moduleID; + $this->view->pager = $pager; + $this->view->users = $this->user->getPairs('noletter'); + $this->view->orderBy = $orderBy; + $this->view->browseType = $browseType; + $this->view->param = $param; + $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; + + $this->display(); + } + + /** + * Create a test case. + * + * @param int $productID + * @param int $moduleID + * @param string $from + * @param int $param + * @access public + * @return void + */ + public function create($productID, $moduleID = 0, $from = '', $param = 0, $storyID = 0) + { + $testcaseID = $from == 'testcase' ? $param : 0; + $bugID = $from == 'bug' ? $param : 0; + + $this->loadModel('story'); + if(!empty($_POST)) + { + $caseID = $this->testcase->create($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action'); + $this->action->create('case', $caseID, 'Opened'); + die(js::locate($this->createLink('testcase', 'browse', "productID=$_POST[product]&browseType=byModule¶m=$_POST[module]"), 'parent')); + } + if(empty($this->products)) $this->locate($this->createLink('product', 'create')); + + /* Set productID and currentModuleID. */ + $productID = $this->product->saveState($productID, $this->products); + $currentModuleID = (int)$moduleID; + + /* Set menu. */ + $this->testcase->setMenu($this->products, $productID); + + /* Init vars. */ + $type = 'feature'; + $stage = ''; + $pri = 0; + $title = ''; + $precondition = ''; + $keywords = ''; + $steps = array(); + + /* If testcaseID large than 0, use this testcase as template. */ + if($testcaseID > 0) + { + $testcase = $this->testcase->getById($testcaseID); + $productID = $testcase->product; + $type = $testcase->type ? $testcase->type : 'feature'; + $stage = $testcase->stage; + $pri = $testcase->pri; + $storyID = $testcase->story; + $title = $testcase->title; + $precondition = $testcase->precondition; + $keywords = $testcase->keywords; + $steps = $testcase->steps; + } + + /* If bugID large than 0, use this bug as template. */ + if($bugID > 0) + { + $bug = $this->loadModel('bug')->getById($bugID); + $type = $bug->type; + $pri = $bug->pri ? $bug->pri : $bug->severity; + $storyID = $bug->story; + $title = $bug->title; + $keywords = $bug->keywords; + $steps = $this->testcase->createStepsFromBug($bug->steps); + } + + /* Padding the steps to the default steps count. */ + if(count($steps) < $this->config->testcase->defaultSteps) + { + $paddingCount = $this->config->testcase->defaultSteps - count($steps); + $step->desc = ''; + $step->expect = ''; + for($i = 1; $i <= $paddingCount; $i ++) $steps[] = $step; + } + + $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->create; + $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $position[] = $this->lang->testcase->create; + + $users = $this->user->getPairs(); + $this->view->header = $header; + $this->view->position = $position; + $this->view->productID = $productID; + $this->view->users = $users; + $this->view->productName = $this->products[$productID]; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); + $this->view->currentModuleID = $currentModuleID; + $this->view->stories = $this->story->getProductStoryPairs($productID); + $this->view->type = $type; + $this->view->stage = $stage; + $this->view->pri = $pri; + $this->view->storyID = $storyID; + $this->view->title = $title; + $this->view->precondition = $precondition; + $this->view->keywords = $keywords; + $this->view->steps = $steps; + + $this->display(); + } + + + /** + * Create a batch test case. + * + * @param int $productID + * @param int $moduleID + * @param int $testcaseID + * @access public + * @return void + */ + public function batchCreate($productID, $moduleID = 0) + { + $this->loadModel('story'); + if(!empty($_POST)) + { + $caseID = $this->testcase->batchCreate($productID); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('testcase', 'browse', "productID=$_POST[product]&browseType=byModule¶m=$_POST[module]"), 'parent')); + } + if(empty($this->products)) $this->locate($this->createLink('product', 'create')); + + /* Set productID and currentModuleID. */ + $productID = $this->product->saveState($productID, $this->products); + $currentModuleID = (int)$moduleID; + + /* Set menu. */ + $this->testcase->setMenu($this->products, $productID); + + /* Init vars. */ + $type = 'feature'; + $title = ''; + + $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->batchCreate; + $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $position[] = $this->lang->testcase->batchCreate; + + $users = $this->user->getPairs(); + $this->view->header = $header; + $this->view->position = $position; + $this->view->productID = $productID; + $this->view->users = $users; + $this->view->productName = $this->products[$productID]; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); + $this->view->currentModuleID = $currentModuleID; + $this->view->stories = $this->story->getProductStoryPairs($productID); + $this->view->type = $type; + $this->view->title = $title; + + $this->display(); + } + + /** + * View a test case. + * + * @param int $caseID + * @param int $version + * @access public + * @return void + */ + public function view($caseID, $version = 0) + { + $case = $this->testcase->getById($caseID, $version); + if(!$case) die(js::error($this->lang->notFound) . js::locate('back')); + + $productID = $case->product; + $this->testcase->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->view; + $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testcase->view; + + $this->view->case = $case; + $this->view->productName = $this->products[$productID]; + $this->view->modulePath = $this->tree->getParents($case->module); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->actions = $this->loadModel('action')->getList('case', $caseID); + + $this->display(); + } + + /** + * Edit a case. + * + * @param int $caseID + * @access public + * @return void + */ + public function edit($caseID) + { + $this->loadModel('story'); + + if(!empty($_POST)) + { + $changes = $this->testcase->update($caseID); + if(dao::isError()) die(js::error(dao::getError())); + $files = $this->loadModel('file')->saveUpload('testcase', $caseID); + if($this->post->comment != '' or !empty($changes) or !empty($files)) + { + $this->loadModel('action'); + $action = !empty($changes) ? 'Edited' : 'Commented'; + $fileAction = ''; + if(!empty($files)) $fileAction = $this->lang->addFiles . join(',', $files) . "\n"; + $actionID = $this->action->create('case', $caseID, $action, $fileAction . $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('testcase', 'view', "caseID=$caseID"), 'parent')); + } + + $case = $this->testcase->getById($caseID); + if(empty($case->steps)) + { + $step->desc = ''; + $step->expect = ''; + $case->steps[] = $step; + } + $productID = $case->product; + $currentModuleID = $case->module; + $header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testcase->edit; + $position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $position[] = $this->lang->testcase->edit; + + /* Set menu. */ + $this->testcase->setMenu($this->products, $productID); + + $users = $this->user->getPairs(); + $this->view->header = $header; + $this->view->position = $position; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); + $this->view->currentModuleID = $currentModuleID; + $this->view->users = $users; + $this->view->stories = $this->story->getProductStoryPairs($productID); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->case = $case; + $this->view->actions = $this->loadModel('action')->getList('case', $caseID); + + $this->display(); + } + + /** + * Delete a test case + * + * @param int $caseID + * @param string $confirm yes|noe + * @access public + * @return void + */ + public function delete($caseID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->testcase->confirmDelete, inlink('delete', "caseID=$caseID&confirm=yes"))); + } + else + { + $this->testcase->delete(TABLE_CASE, $caseID); + die(js::locate($this->session->caseList, 'parent')); + } + } + + /** + * Confirm story changes. + * + * @param int $caseID + * @access public + * @return void + */ + public function confirmStoryChange($caseID) + { + $case = $this->testcase->getById($caseID); + $this->dao->update(TABLE_CASE)->set('storyVersion')->eq($case->latestStoryVersion)->where('id')->eq($caseID)->exec(); + $this->loadModel('action')->create('case', $caseID, 'confirmed', '', $case->latestStoryVersion); + die(js::reload('parent')); + } + + /** + * export + * + * @param string $productID + * @param string $orderBy + * @access public + * @return void + */ + public function export($productID, $orderBy) + { + if($_POST) + { + $caseLang = $this->lang->testcase; + $caseConfig = $this->config->testcase; + + /* Create field lists. */ + $fields = explode(',', $caseConfig->exportFields); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($caseLang->$fieldName) ? $caseLang->$fieldName : $fieldName; + unset($fields[$key]); + } + + /* Get cases. */ + $cases = $this->dao->select('*')->from(TABLE_CASE)->alias('t1')->where($this->session->testcaseReport)->orderBy($orderBy)->fetchAll('id'); + + /* Get users, products and projects. */ + $users = $this->loadModel('user')->getPairs('noletter'); + $products = $this->loadModel('product')->getPairs(); + + /* Get related objects id lists. */ + $relatedModuleIdList = array(); + $relatedStoryIdList = array(); + $relatedCaseIdList = array(); + + foreach($cases as $case) + { + $relatedModuleIdList[$case->module] = $case->module; + $relatedStoryIdList[$case->story] = $case->story; + $relatedCaseIdList[$case->linkCase] = $case->linkCase; + + /* Process link cases. */ + $linkCases = explode(',', $case->linkCase); + foreach($linkCases as $linkCaseID) + { + if($linkCaseID) $relatedCaseIdList[$linkCaseID] = trim($linkCaseID); + } + } + + /* Get related objects title or names. */ + $relatedModules = $this->dao->select('id, name')->from(TABLE_MODULE)->where('id')->in($relatedModuleIdList)->fetchPairs(); + $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); + $relatedCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('id')->in($relatedCaseIdList)->fetchPairs(); + $relatedSteps = $this->dao->select('`case`, version, `desc`, expect')->from(TABLE_CASESTEP)->where('`case`')->in(@array_keys($cases))->orderBy('version desc,id')->fetchGroup('case'); + + foreach($cases as $case) + { + $case->steps = ''; + if(isset($relatedSteps[$case->id])) + { + $i = 1; + foreach($relatedSteps[$case->id] as $step) + { + $case->steps .= $i . ":" . $step->desc . '
          ' . $caseLang->stepExpect . ':' . $step->expect . '
          '; + $i ++; + if($step->version != $case->version) break; + } + } + + if($this->post->fileType == 'csv') + { + $case->steps = str_replace('
          ', "\n", $case->steps); + $case->steps = str_replace('"', '""', $case->steps); + } + + /* fill some field with useful value. */ + if(isset($products[$case->product])) $case->product = $products[$case->product]; + if(isset($relatedModules[$case->module])) $case->module = $relatedModules[$case->module]; + if(isset($relatedStories[$case->story])) $case->story = $relatedStories[$case->story]; + + if(isset($caseLang->priList[$case->pri])) $case->pri = $caseLang->priList[$case->pri]; + if(isset($caseLang->typeList[$case->type])) $case->type = $caseLang->typeList[$case->type]; + if(isset($caseLang->stageList[$case->stage])) $case->stage = $caseLang->stageList[$case->stage]; + if(isset($caseLang->statusList[$case->status])) $case->status = $caseLang->statusList[$case->status]; + if(isset($users[$case->openedBy])) $case->openedBy = $users[$case->openedBy]; + if(isset($users[$case->lastEditedBy])) $case->lastEditedBy = $users[$case->lastEditedBy]; + + $case->openedDate = substr($case->openedDate, 0, 10); + $case->lastEditedDate = substr($case->lastEditedDate, 0, 10); + + if($case->linkCase) + { + $tmpLinkCases = array(); + $linkCaseIdList = explode(',', $case->linkCase); + foreach($linkCaseIdList as $linkCaseID) + { + $linkCaseID = trim($linkCaseID); + $tmpLinkCases[] = isset($relatedCases[$linkCaseID]) ? $relatedCases[$linkCaseID] : $linkCaseID; + } + $case->linkCase = join("; \n", $tmpLinkCases); + } + } + + $this->post->set('fields', $fields); + $this->post->set('rows', $cases); + $this->fetch('file', 'export2' . $this->post->fileType, $_POST); + } + + $this->display(); + } +} diff --git a/module/testcase/lang/en.php b/module/testcase/lang/en.php index e1547cfb24..a4d77294b6 100644 --- a/module/testcase/lang/en.php +++ b/module/testcase/lang/en.php @@ -1,135 +1,135 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->testcase->id = 'ID'; -$lang->testcase->product = 'Product'; -$lang->testcase->module = 'Module'; -$lang->testcase->story = 'Story'; -$lang->testcase->storyVersion = 'Story version'; -$lang->testcase->title = 'Title'; -$lang->testcase->precondition = 'precondition'; -$lang->testcase->pri = 'Priority'; -$lang->testcase->type = 'Type'; -$lang->testcase->status = 'Status'; -$lang->testcase->steps = 'Steps'; -$lang->testcase->frequency = 'Frequency'; -$lang->testcase->order = 'Order'; -$lang->testcase->openedBy = 'Opened by '; -$lang->testcase->openedDate = 'Opened date'; -$lang->testcase->lastEditedBy = 'Last edited by'; -$lang->testcase->lastEditedDate = 'Last edited date'; -$lang->testcase->version = 'Version'; -$lang->testcase->result = 'Result'; -$lang->testcase->real = 'Real'; -$lang->testcase->keywords = 'Keywords'; -$lang->testcase->files = 'Files'; -$lang->testcase->howRun = 'How run'; -$lang->testcase->scriptedBy = 'Scripted by'; -$lang->testcase->scriptedDate = 'Scripted date'; -$lang->testcase->scriptedStatus = 'Scripted status'; -$lang->testcase->scriptedLocation = 'Script location'; -$lang->testcase->linkCase = 'Related cases'; -$lang->testcase->stage = 'Stage'; -$lang->testcase->lastEditedByAB = 'Last edited by'; -$lang->testcase->lastEditedDateAB = 'Last edited date'; -$lang->testcase->allProduct = 'All product'; -$lang->case = $lang->testcase; // For dao checking using. Because 'case' is a php keywords, so the module name is testcase, table name is still case. - -$lang->testcase->stepID = 'ID'; -$lang->testcase->stepDesc = 'Step'; -$lang->testcase->stepExpect = 'Expect'; - -$lang->testcase->common = 'Case'; -$lang->testcase->index = "Index"; -$lang->testcase->create = "Create"; -$lang->testcase->batchCreate = "Batch create"; -$lang->testcase->delete = "Delete"; -$lang->testcase->view = "Info"; -$lang->testcase->edit = "Edit"; -$lang->testcase->delete = "Delete"; -$lang->testcase->browse = "Browse"; -$lang->testcase->export = "Export"; -$lang->testcase->confirmStoryChange = 'Confirm story change'; - -$lang->testcase->deleteStep = 'Delete'; -$lang->testcase->insertBefore = 'Insert before'; -$lang->testcase->insertAfter = 'Insert after'; - -$lang->testcase->selectProduct = 'Select product'; -$lang->testcase->byModule = 'By module'; -$lang->testcase->assignToMe = 'Cases to me'; -$lang->testcase->openedByMe = 'My Opened cases'; -$lang->testcase->allCases = 'All case'; -$lang->testcase->needConfirm = 'Story changed'; -$lang->testcase->moduleCases = 'By module'; -$lang->testcase->bySearch = 'By search'; -$lang->testcase->doneByMe = 'My runed cases'; - -$lang->testcase->lblProductAndModule = 'Product & module'; -$lang->testcase->lblTypeAndPri = 'Type & priority'; -$lang->testcase->lblSystemBrowserAndHardware = 'OS & browser'; -$lang->testcase->lblAssignAndMail = 'Assigned & mailto'; -$lang->testcase->lblStory = 'Story'; -$lang->testcase->lblLastEdited = 'Last edited'; - -$lang->testcase->legendRelated = 'Related info'; -$lang->testcase->legendBasicInfo = 'Basic info'; -$lang->testcase->legendMailto = 'Mailto'; -$lang->testcase->legendAttatch = 'Files'; -$lang->testcase->legendLinkBugs = 'Bug'; -$lang->testcase->legendOpenAndEdit = 'Open & edit'; -$lang->testcase->legendStoryAndTask = 'Story'; -$lang->testcase->legendCases = 'Related cases'; -$lang->testcase->legendSteps = 'Steps'; -$lang->testcase->legendAction = 'Action'; -$lang->testcase->legendHistory = 'History'; -$lang->testcase->legendComment = 'Comment'; -$lang->testcase->legendProduct = 'Product & module'; -$lang->testcase->legendVersion = 'Versions'; - -$lang->testcase->confirmDelete = 'Are you sure to delete this case?'; -$lang->testcase->same = 'The same as above'; -$lang->testcase->notes = '(Notes: the type and title must be written, otherwise it is no use)'; - -$lang->testcase->priList[3] = 3; -$lang->testcase->priList[1] = 1; -$lang->testcase->priList[2] = 2; -$lang->testcase->priList[4] = 4; - -/* Define the types. */ -$lang->testcase->typeList[''] = ''; -$lang->testcase->typeList['feature'] = 'Feature'; -$lang->testcase->typeList['performance'] = 'Performance'; -$lang->testcase->typeList['config'] = 'Config'; -$lang->testcase->typeList['install'] = 'Install'; -$lang->testcase->typeList['security'] = 'Security'; -$lang->testcase->typeList['other'] = 'Other'; - -$lang->testcase->stageList[''] = ''; -$lang->testcase->stageList['unittest'] = 'Unit testing'; -$lang->testcase->stageList['feature'] = 'Feature testing'; -$lang->testcase->stageList['intergrate'] = 'Integrate testing'; -$lang->testcase->stageList['system'] = 'System testing'; -$lang->testcase->stageList['smoke'] = 'Smoking testing'; -$lang->testcase->stageList['bvt'] = 'BVT testing'; - -$lang->testcase->statusList[''] = ''; -$lang->testcase->statusList['normal'] = 'Normal'; -$lang->testcase->statusList['blocked'] = 'Blocked'; -$lang->testcase->statusList['investigate'] = 'Investigate'; - -$lang->testcase->resultList['n/a'] = 'N/A'; -$lang->testcase->resultList['pass'] = 'Pass'; -$lang->testcase->resultList['fail'] = 'Fail'; -$lang->testcase->resultList['blocked'] = 'Blocked'; - -$lang->testcase->buttonEdit = 'Edit'; -$lang->testcase->buttonToList = 'Back'; + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->testcase->id = 'ID'; +$lang->testcase->product = 'Product'; +$lang->testcase->module = 'Module'; +$lang->testcase->story = 'Story'; +$lang->testcase->storyVersion = 'Story version'; +$lang->testcase->title = 'Title'; +$lang->testcase->precondition = 'precondition'; +$lang->testcase->pri = 'Priority'; +$lang->testcase->type = 'Type'; +$lang->testcase->status = 'Status'; +$lang->testcase->steps = 'Steps'; +$lang->testcase->frequency = 'Frequency'; +$lang->testcase->order = 'Order'; +$lang->testcase->openedBy = 'Opened by '; +$lang->testcase->openedDate = 'Opened date'; +$lang->testcase->lastEditedBy = 'Last edited by'; +$lang->testcase->lastEditedDate = 'Last edited date'; +$lang->testcase->version = 'Version'; +$lang->testcase->result = 'Result'; +$lang->testcase->real = 'Real'; +$lang->testcase->keywords = 'Keywords'; +$lang->testcase->files = 'Files'; +$lang->testcase->howRun = 'How run'; +$lang->testcase->scriptedBy = 'Scripted by'; +$lang->testcase->scriptedDate = 'Scripted date'; +$lang->testcase->scriptedStatus = 'Scripted status'; +$lang->testcase->scriptedLocation = 'Script location'; +$lang->testcase->linkCase = 'Related cases'; +$lang->testcase->stage = 'Stage'; +$lang->testcase->lastEditedByAB = 'Last edited by'; +$lang->testcase->lastEditedDateAB = 'Last edited date'; +$lang->testcase->allProduct = 'All product'; +$lang->case = $lang->testcase; // For dao checking using. Because 'case' is a php keywords, so the module name is testcase, table name is still case. + +$lang->testcase->stepID = 'ID'; +$lang->testcase->stepDesc = 'Step'; +$lang->testcase->stepExpect = 'Expect'; + +$lang->testcase->common = 'Case'; +$lang->testcase->index = "Index"; +$lang->testcase->create = "Create"; +$lang->testcase->batchCreate = "Batch create"; +$lang->testcase->delete = "Delete"; +$lang->testcase->view = "Info"; +$lang->testcase->edit = "Edit"; +$lang->testcase->delete = "Delete"; +$lang->testcase->browse = "Browse"; +$lang->testcase->export = "Export"; +$lang->testcase->confirmStoryChange = 'Confirm story change'; + +$lang->testcase->deleteStep = 'Delete'; +$lang->testcase->insertBefore = 'Insert before'; +$lang->testcase->insertAfter = 'Insert after'; + +$lang->testcase->selectProduct = 'Select product'; +$lang->testcase->byModule = 'By module'; +$lang->testcase->assignToMe = 'Cases to me'; +$lang->testcase->openedByMe = 'My Opened cases'; +$lang->testcase->allCases = 'All case'; +$lang->testcase->needConfirm = 'Story changed'; +$lang->testcase->moduleCases = 'By module'; +$lang->testcase->bySearch = 'By search'; +$lang->testcase->doneByMe = 'My runed cases'; + +$lang->testcase->lblProductAndModule = 'Product & module'; +$lang->testcase->lblTypeAndPri = 'Type & priority'; +$lang->testcase->lblSystemBrowserAndHardware = 'OS & browser'; +$lang->testcase->lblAssignAndMail = 'Assigned & mailto'; +$lang->testcase->lblStory = 'Story'; +$lang->testcase->lblLastEdited = 'Last edited'; + +$lang->testcase->legendRelated = 'Related info'; +$lang->testcase->legendBasicInfo = 'Basic info'; +$lang->testcase->legendMailto = 'Mailto'; +$lang->testcase->legendAttatch = 'Files'; +$lang->testcase->legendLinkBugs = 'Bug'; +$lang->testcase->legendOpenAndEdit = 'Open & edit'; +$lang->testcase->legendStoryAndTask = 'Story'; +$lang->testcase->legendCases = 'Related cases'; +$lang->testcase->legendSteps = 'Steps'; +$lang->testcase->legendAction = 'Action'; +$lang->testcase->legendHistory = 'History'; +$lang->testcase->legendComment = 'Comment'; +$lang->testcase->legendProduct = 'Product & module'; +$lang->testcase->legendVersion = 'Versions'; + +$lang->testcase->confirmDelete = 'Are you sure to delete this case?'; +$lang->testcase->same = 'The same as above'; +$lang->testcase->notes = '(Notes: the type and title must be written, otherwise it is no use)'; + +$lang->testcase->priList[3] = 3; +$lang->testcase->priList[1] = 1; +$lang->testcase->priList[2] = 2; +$lang->testcase->priList[4] = 4; + +/* Define the types. */ +$lang->testcase->typeList[''] = ''; +$lang->testcase->typeList['feature'] = 'Feature'; +$lang->testcase->typeList['performance'] = 'Performance'; +$lang->testcase->typeList['config'] = 'Config'; +$lang->testcase->typeList['install'] = 'Install'; +$lang->testcase->typeList['security'] = 'Security'; +$lang->testcase->typeList['other'] = 'Other'; + +$lang->testcase->stageList[''] = ''; +$lang->testcase->stageList['unittest'] = 'Unit testing'; +$lang->testcase->stageList['feature'] = 'Feature testing'; +$lang->testcase->stageList['intergrate'] = 'Integrate testing'; +$lang->testcase->stageList['system'] = 'System testing'; +$lang->testcase->stageList['smoke'] = 'Smoking testing'; +$lang->testcase->stageList['bvt'] = 'BVT testing'; + +$lang->testcase->statusList[''] = ''; +$lang->testcase->statusList['normal'] = 'Normal'; +$lang->testcase->statusList['blocked'] = 'Blocked'; +$lang->testcase->statusList['investigate'] = 'Investigate'; + +$lang->testcase->resultList['n/a'] = 'N/A'; +$lang->testcase->resultList['pass'] = 'Pass'; +$lang->testcase->resultList['fail'] = 'Fail'; +$lang->testcase->resultList['blocked'] = 'Blocked'; + +$lang->testcase->buttonEdit = 'Edit'; +$lang->testcase->buttonToList = 'Back'; diff --git a/module/testcase/lang/zh-cn.php b/module/testcase/lang/zh-cn.php index 1dd304c652..5e15dae06f 100644 --- a/module/testcase/lang/zh-cn.php +++ b/module/testcase/lang/zh-cn.php @@ -1,135 +1,135 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->testcase->id = '用例编号'; -$lang->testcase->product = '所属产品'; -$lang->testcase->module = '所属模块'; -$lang->testcase->story = '相关需求'; -$lang->testcase->storyVersion = '需求版本'; -$lang->testcase->title = '用例标题'; -$lang->testcase->precondition = '前置条件'; -$lang->testcase->pri = '优先级'; -$lang->testcase->type = '用例类型'; -$lang->testcase->status = '用例状态'; -$lang->testcase->steps = '用例步骤'; -$lang->testcase->frequency = '执行频率'; -$lang->testcase->order = '排序'; -$lang->testcase->openedBy = '由谁创建 '; -$lang->testcase->openedDate = '创建日期'; -$lang->testcase->lastEditedBy = '最后修改者'; -$lang->testcase->lastEditedDate = '最后修改日期'; -$lang->testcase->version = '用例版本'; -$lang->testcase->result = '测试结果'; -$lang->testcase->real = '实际情况'; -$lang->testcase->keywords = '关键词'; -$lang->testcase->files = '附件'; -$lang->testcase->howRun = '执行方式'; -$lang->testcase->scriptedBy = '由谁编写'; -$lang->testcase->scriptedDate = '编写日期'; -$lang->testcase->scriptedStatus = '脚本状态'; -$lang->testcase->scriptedLocation = '脚本位置'; -$lang->testcase->linkCase = '相关用例'; -$lang->testcase->stage = '适用阶段'; -$lang->testcase->lastEditedByAB = '修改者'; -$lang->testcase->lastEditedDateAB = '修改日期'; -$lang->testcase->allProduct = '所有产品'; -$lang->case = $lang->testcase; // 用于DAO检查时使用。因为case是系统关键字,所以无法定义该模块为case,只能使用testcase,但表还是使用的case。 - -$lang->testcase->stepID = '编号'; -$lang->testcase->stepDesc = '步骤'; -$lang->testcase->stepExpect = '预期'; - -$lang->testcase->common = '用例管理'; -$lang->testcase->index = "用例管理首页"; -$lang->testcase->create = "创建用例"; -$lang->testcase->batchCreate = "批量添加"; -$lang->testcase->delete = "删除用例"; -$lang->testcase->view = "用例详情"; -$lang->testcase->edit = "编辑用例"; -$lang->testcase->delete = "删除用例"; -$lang->testcase->browse = "用例列表"; -$lang->testcase->export = "导出数据"; -$lang->testcase->confirmStoryChange = '确认需求变动'; - -$lang->testcase->deleteStep = '删除'; -$lang->testcase->insertBefore = '之前添加'; -$lang->testcase->insertAfter = '之后添加'; - -$lang->testcase->selectProduct = '请选择产品'; -$lang->testcase->byModule = '按模块'; -$lang->testcase->assignToMe = '指派给我的用例'; -$lang->testcase->openedByMe = '由我创建的用例'; -$lang->testcase->allCases = '所有Case'; -$lang->testcase->needConfirm = '需求有变动的用例'; -$lang->testcase->moduleCases = '按模块浏览'; -$lang->testcase->bySearch = '搜索'; -$lang->testcase->doneByMe = '我完成的用例'; - -$lang->testcase->lblProductAndModule = '产品模块'; -$lang->testcase->lblTypeAndPri = '类型&优先级'; -$lang->testcase->lblSystemBrowserAndHardware = '系统::浏览器'; -$lang->testcase->lblAssignAndMail = '指派给::抄送给'; -$lang->testcase->lblStory = '相关需求'; -$lang->testcase->lblLastEdited = '最后编辑'; - -$lang->testcase->legendRelated = '相关信息'; -$lang->testcase->legendBasicInfo = '基本信息'; -$lang->testcase->legendMailto = '抄送给'; -$lang->testcase->legendAttatch = '附件'; -$lang->testcase->legendLinkBugs = '相关Bug'; -$lang->testcase->legendOpenAndEdit = '创建编辑'; -$lang->testcase->legendStoryAndTask = '需求::任务'; -$lang->testcase->legendCases = '相关用例'; -$lang->testcase->legendSteps = '用例步骤'; -$lang->testcase->legendAction = '操作'; -$lang->testcase->legendHistory = '历史记录'; -$lang->testcase->legendComment = '备注'; -$lang->testcase->legendProduct = '产品模块'; -$lang->testcase->legendVersion = '版本历史'; - -$lang->testcase->confirmDelete = '您确认要删除该测试用例吗?'; -$lang->testcase->same = '同上'; -$lang->testcase->notes = '(注:“用例类型”和“用例标题”必须填写,否则此行无效)'; - -$lang->testcase->priList[3] = 3; -$lang->testcase->priList[1] = 1; -$lang->testcase->priList[2] = 2; -$lang->testcase->priList[4] = 4; - -/* Define the types. */ -$lang->testcase->typeList[''] = ''; -$lang->testcase->typeList['feature'] = '功能测试'; -$lang->testcase->typeList['performance'] = '性能测试'; -$lang->testcase->typeList['config'] = '配置相关'; -$lang->testcase->typeList['install'] = '安装部署'; -$lang->testcase->typeList['security'] = '安全相关'; -$lang->testcase->typeList['other'] = '其他'; - -$lang->testcase->stageList[''] = ''; -$lang->testcase->stageList['unittest'] = '单元测试阶段'; -$lang->testcase->stageList['feature'] = '功能测试阶段'; -$lang->testcase->stageList['intergrate'] = '集成测试阶段'; -$lang->testcase->stageList['system'] = '系统测试阶段'; -$lang->testcase->stageList['smoke'] = '冒烟测试阶段'; -$lang->testcase->stageList['bvt'] = '版本验证阶段'; - -$lang->testcase->statusList[''] = ''; -$lang->testcase->statusList['normal'] = '正常'; -$lang->testcase->statusList['blocked'] = '被阻塞'; -$lang->testcase->statusList['investigate'] = '研究中'; - -$lang->testcase->resultList['n/a'] = 'N/A'; -$lang->testcase->resultList['pass'] = '通过'; -$lang->testcase->resultList['fail'] = '失败'; -$lang->testcase->resultList['blocked'] = '阻塞'; - -$lang->testcase->buttonEdit = '编辑'; -$lang->testcase->buttonToList = '返回'; + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->testcase->id = '用例编号'; +$lang->testcase->product = '所属产品'; +$lang->testcase->module = '所属模块'; +$lang->testcase->story = '相关需求'; +$lang->testcase->storyVersion = '需求版本'; +$lang->testcase->title = '用例标题'; +$lang->testcase->precondition = '前置条件'; +$lang->testcase->pri = '优先级'; +$lang->testcase->type = '用例类型'; +$lang->testcase->status = '用例状态'; +$lang->testcase->steps = '用例步骤'; +$lang->testcase->frequency = '执行频率'; +$lang->testcase->order = '排序'; +$lang->testcase->openedBy = '由谁创建 '; +$lang->testcase->openedDate = '创建日期'; +$lang->testcase->lastEditedBy = '最后修改者'; +$lang->testcase->lastEditedDate = '最后修改日期'; +$lang->testcase->version = '用例版本'; +$lang->testcase->result = '测试结果'; +$lang->testcase->real = '实际情况'; +$lang->testcase->keywords = '关键词'; +$lang->testcase->files = '附件'; +$lang->testcase->howRun = '执行方式'; +$lang->testcase->scriptedBy = '由谁编写'; +$lang->testcase->scriptedDate = '编写日期'; +$lang->testcase->scriptedStatus = '脚本状态'; +$lang->testcase->scriptedLocation = '脚本位置'; +$lang->testcase->linkCase = '相关用例'; +$lang->testcase->stage = '适用阶段'; +$lang->testcase->lastEditedByAB = '修改者'; +$lang->testcase->lastEditedDateAB = '修改日期'; +$lang->testcase->allProduct = '所有产品'; +$lang->case = $lang->testcase; // 用于DAO检查时使用。因为case是系统关键字,所以无法定义该模块为case,只能使用testcase,但表还是使用的case。 + +$lang->testcase->stepID = '编号'; +$lang->testcase->stepDesc = '步骤'; +$lang->testcase->stepExpect = '预期'; + +$lang->testcase->common = '用例管理'; +$lang->testcase->index = "用例管理首页"; +$lang->testcase->create = "创建用例"; +$lang->testcase->batchCreate = "批量添加"; +$lang->testcase->delete = "删除用例"; +$lang->testcase->view = "用例详情"; +$lang->testcase->edit = "编辑用例"; +$lang->testcase->delete = "删除用例"; +$lang->testcase->browse = "用例列表"; +$lang->testcase->export = "导出数据"; +$lang->testcase->confirmStoryChange = '确认需求变动'; + +$lang->testcase->deleteStep = '删除'; +$lang->testcase->insertBefore = '之前添加'; +$lang->testcase->insertAfter = '之后添加'; + +$lang->testcase->selectProduct = '请选择产品'; +$lang->testcase->byModule = '按模块'; +$lang->testcase->assignToMe = '指派给我的用例'; +$lang->testcase->openedByMe = '由我创建的用例'; +$lang->testcase->allCases = '所有Case'; +$lang->testcase->needConfirm = '需求有变动的用例'; +$lang->testcase->moduleCases = '按模块浏览'; +$lang->testcase->bySearch = '搜索'; +$lang->testcase->doneByMe = '我完成的用例'; + +$lang->testcase->lblProductAndModule = '产品模块'; +$lang->testcase->lblTypeAndPri = '类型&优先级'; +$lang->testcase->lblSystemBrowserAndHardware = '系统::浏览器'; +$lang->testcase->lblAssignAndMail = '指派给::抄送给'; +$lang->testcase->lblStory = '相关需求'; +$lang->testcase->lblLastEdited = '最后编辑'; + +$lang->testcase->legendRelated = '相关信息'; +$lang->testcase->legendBasicInfo = '基本信息'; +$lang->testcase->legendMailto = '抄送给'; +$lang->testcase->legendAttatch = '附件'; +$lang->testcase->legendLinkBugs = '相关Bug'; +$lang->testcase->legendOpenAndEdit = '创建编辑'; +$lang->testcase->legendStoryAndTask = '需求::任务'; +$lang->testcase->legendCases = '相关用例'; +$lang->testcase->legendSteps = '用例步骤'; +$lang->testcase->legendAction = '操作'; +$lang->testcase->legendHistory = '历史记录'; +$lang->testcase->legendComment = '备注'; +$lang->testcase->legendProduct = '产品模块'; +$lang->testcase->legendVersion = '版本历史'; + +$lang->testcase->confirmDelete = '您确认要删除该测试用例吗?'; +$lang->testcase->same = '同上'; +$lang->testcase->notes = '(注:“用例类型”和“用例标题”必须填写,否则此行无效)'; + +$lang->testcase->priList[3] = 3; +$lang->testcase->priList[1] = 1; +$lang->testcase->priList[2] = 2; +$lang->testcase->priList[4] = 4; + +/* Define the types. */ +$lang->testcase->typeList[''] = ''; +$lang->testcase->typeList['feature'] = '功能测试'; +$lang->testcase->typeList['performance'] = '性能测试'; +$lang->testcase->typeList['config'] = '配置相关'; +$lang->testcase->typeList['install'] = '安装部署'; +$lang->testcase->typeList['security'] = '安全相关'; +$lang->testcase->typeList['other'] = '其他'; + +$lang->testcase->stageList[''] = ''; +$lang->testcase->stageList['unittest'] = '单元测试阶段'; +$lang->testcase->stageList['feature'] = '功能测试阶段'; +$lang->testcase->stageList['intergrate'] = '集成测试阶段'; +$lang->testcase->stageList['system'] = '系统测试阶段'; +$lang->testcase->stageList['smoke'] = '冒烟测试阶段'; +$lang->testcase->stageList['bvt'] = '版本验证阶段'; + +$lang->testcase->statusList[''] = ''; +$lang->testcase->statusList['normal'] = '正常'; +$lang->testcase->statusList['blocked'] = '被阻塞'; +$lang->testcase->statusList['investigate'] = '研究中'; + +$lang->testcase->resultList['n/a'] = 'N/A'; +$lang->testcase->resultList['pass'] = '通过'; +$lang->testcase->resultList['fail'] = '失败'; +$lang->testcase->resultList['blocked'] = '阻塞'; + +$lang->testcase->buttonEdit = '编辑'; +$lang->testcase->buttonToList = '返回'; diff --git a/module/testcase/lang/zh-tw.php b/module/testcase/lang/zh-tw.php index 95144c220d..b3609e5dc4 100644 --- a/module/testcase/lang/zh-tw.php +++ b/module/testcase/lang/zh-tw.php @@ -1,135 +1,135 @@ - - * @package testcase - * @version $Id: zh-tw.php 2285 2011-10-29 10:33:45Z wwccss $ - * @link http://www.zentao.net - */ -$lang->testcase->id = '用例編號'; -$lang->testcase->product = '所屬產品'; -$lang->testcase->module = '所屬模組'; -$lang->testcase->story = '相關需求'; -$lang->testcase->storyVersion = '需求版本'; -$lang->testcase->title = '用例標題'; -$lang->testcase->precondition = '前置條件'; -$lang->testcase->pri = '優先順序'; -$lang->testcase->type = '用例類型'; -$lang->testcase->status = '用例狀態'; -$lang->testcase->steps = '用例步驟'; -$lang->testcase->frequency = '執行頻率'; -$lang->testcase->order = '排序'; -$lang->testcase->openedBy = '由誰創建 '; -$lang->testcase->openedDate = '創建日期'; -$lang->testcase->lastEditedBy = '最後修改者'; -$lang->testcase->lastEditedDate = '最後修改日期'; -$lang->testcase->version = '用例版本'; -$lang->testcase->result = '測試結果'; -$lang->testcase->real = '實際情況'; -$lang->testcase->keywords = '關鍵詞'; -$lang->testcase->files = '附件'; -$lang->testcase->howRun = '執行方式'; -$lang->testcase->scriptedBy = '由誰編寫'; -$lang->testcase->scriptedDate = '編寫日期'; -$lang->testcase->scriptedStatus = '腳本狀態'; -$lang->testcase->scriptedLocation = '腳本位置'; -$lang->testcase->linkCase = '相關用例'; -$lang->testcase->stage = '適用階段'; -$lang->testcase->lastEditedByAB = '修改者'; -$lang->testcase->lastEditedDateAB = '修改日期'; -$lang->testcase->allProduct = '所有產品'; -$lang->case = $lang->testcase; // 用於DAO檢查時使用。因為case是系統關鍵字,所以無法定義該模組為case,只能使用testcase,但表還是使用的case。 - -$lang->testcase->stepID = '編號'; -$lang->testcase->stepDesc = '步驟'; -$lang->testcase->stepExpect = '預期'; - -$lang->testcase->common = '用例管理'; -$lang->testcase->index = "用例管理首頁"; -$lang->testcase->create = "創建用例"; -$lang->testcase->batchCreate = "批量添加"; -$lang->testcase->delete = "刪除用例"; -$lang->testcase->view = "用例詳情"; -$lang->testcase->edit = "編輯用例"; -$lang->testcase->delete = "刪除用例"; -$lang->testcase->browse = "用例列表"; -$lang->testcase->export = "導出數據"; -$lang->testcase->confirmStoryChange = '確認需求變動'; - -$lang->testcase->deleteStep = '刪除'; -$lang->testcase->insertBefore = '之前添加'; -$lang->testcase->insertAfter = '之後添加'; - -$lang->testcase->selectProduct = '請選擇產品'; -$lang->testcase->byModule = '按模組'; -$lang->testcase->assignToMe = '指派給我的用例'; -$lang->testcase->openedByMe = '由我創建的用例'; -$lang->testcase->allCases = '所有Case'; -$lang->testcase->needConfirm = '需求有變動的用例'; -$lang->testcase->moduleCases = '按模組瀏覽'; -$lang->testcase->bySearch = '搜索'; -$lang->testcase->doneByMe = '我完成的用例'; - -$lang->testcase->lblProductAndModule = '產品模組'; -$lang->testcase->lblTypeAndPri = '類型&優先順序'; -$lang->testcase->lblSystemBrowserAndHardware = '系統::瀏覽器'; -$lang->testcase->lblAssignAndMail = '指派給::抄送給'; -$lang->testcase->lblStory = '相關需求'; -$lang->testcase->lblLastEdited = '最後編輯'; - -$lang->testcase->legendRelated = '相關信息'; -$lang->testcase->legendBasicInfo = '基本信息'; -$lang->testcase->legendMailto = '抄送給'; -$lang->testcase->legendAttatch = '附件'; -$lang->testcase->legendLinkBugs = '相關Bug'; -$lang->testcase->legendOpenAndEdit = '創建編輯'; -$lang->testcase->legendStoryAndTask = '需求::任務'; -$lang->testcase->legendCases = '相關用例'; -$lang->testcase->legendSteps = '用例步驟'; -$lang->testcase->legendAction = '操作'; -$lang->testcase->legendHistory = '歷史記錄'; -$lang->testcase->legendComment = '備註'; -$lang->testcase->legendProduct = '產品模組'; -$lang->testcase->legendVersion = '版本歷史'; - -$lang->testcase->confirmDelete = '您確認要刪除該測試用例嗎?'; -$lang->testcase->same = '同上'; -$lang->testcase->notes = '(註:“用例類型”和“用例標題”必須填寫,否則此行無效)'; - -$lang->testcase->priList[3] = 3; -$lang->testcase->priList[1] = 1; -$lang->testcase->priList[2] = 2; -$lang->testcase->priList[4] = 4; - -/* Define the types. */ -$lang->testcase->typeList[''] = ''; -$lang->testcase->typeList['feature'] = '功能測試'; -$lang->testcase->typeList['performance'] = '性能測試'; -$lang->testcase->typeList['config'] = '配置相關'; -$lang->testcase->typeList['install'] = '安裝部署'; -$lang->testcase->typeList['security'] = '安全相關'; -$lang->testcase->typeList['other'] = '其他'; - -$lang->testcase->stageList[''] = ''; -$lang->testcase->stageList['unittest'] = '單元測試階段'; -$lang->testcase->stageList['feature'] = '功能測試階段'; -$lang->testcase->stageList['intergrate'] = '整合測試階段'; -$lang->testcase->stageList['system'] = '系統測試階段'; -$lang->testcase->stageList['smoke'] = '冒煙測試階段'; -$lang->testcase->stageList['bvt'] = '版本驗證階段'; - -$lang->testcase->statusList[''] = ''; -$lang->testcase->statusList['normal'] = '正常'; -$lang->testcase->statusList['blocked'] = '被阻塞'; -$lang->testcase->statusList['investigate'] = '研究中'; - -$lang->testcase->resultList['n/a'] = 'N/A'; -$lang->testcase->resultList['pass'] = '通過'; -$lang->testcase->resultList['fail'] = '失敗'; -$lang->testcase->resultList['blocked'] = '阻塞'; - -$lang->testcase->buttonEdit = '編輯'; -$lang->testcase->buttonToList = '返回'; + + * @package testcase + * @version $Id: zh-tw.php 2285 2011-10-29 10:33:45Z wwccss $ + * @link http://www.zentao.net + */ +$lang->testcase->id = '用例編號'; +$lang->testcase->product = '所屬產品'; +$lang->testcase->module = '所屬模組'; +$lang->testcase->story = '相關需求'; +$lang->testcase->storyVersion = '需求版本'; +$lang->testcase->title = '用例標題'; +$lang->testcase->precondition = '前置條件'; +$lang->testcase->pri = '優先順序'; +$lang->testcase->type = '用例類型'; +$lang->testcase->status = '用例狀態'; +$lang->testcase->steps = '用例步驟'; +$lang->testcase->frequency = '執行頻率'; +$lang->testcase->order = '排序'; +$lang->testcase->openedBy = '由誰創建 '; +$lang->testcase->openedDate = '創建日期'; +$lang->testcase->lastEditedBy = '最後修改者'; +$lang->testcase->lastEditedDate = '最後修改日期'; +$lang->testcase->version = '用例版本'; +$lang->testcase->result = '測試結果'; +$lang->testcase->real = '實際情況'; +$lang->testcase->keywords = '關鍵詞'; +$lang->testcase->files = '附件'; +$lang->testcase->howRun = '執行方式'; +$lang->testcase->scriptedBy = '由誰編寫'; +$lang->testcase->scriptedDate = '編寫日期'; +$lang->testcase->scriptedStatus = '腳本狀態'; +$lang->testcase->scriptedLocation = '腳本位置'; +$lang->testcase->linkCase = '相關用例'; +$lang->testcase->stage = '適用階段'; +$lang->testcase->lastEditedByAB = '修改者'; +$lang->testcase->lastEditedDateAB = '修改日期'; +$lang->testcase->allProduct = '所有產品'; +$lang->case = $lang->testcase; // 用於DAO檢查時使用。因為case是系統關鍵字,所以無法定義該模組為case,只能使用testcase,但表還是使用的case。 + +$lang->testcase->stepID = '編號'; +$lang->testcase->stepDesc = '步驟'; +$lang->testcase->stepExpect = '預期'; + +$lang->testcase->common = '用例管理'; +$lang->testcase->index = "用例管理首頁"; +$lang->testcase->create = "創建用例"; +$lang->testcase->batchCreate = "批量添加"; +$lang->testcase->delete = "刪除用例"; +$lang->testcase->view = "用例詳情"; +$lang->testcase->edit = "編輯用例"; +$lang->testcase->delete = "刪除用例"; +$lang->testcase->browse = "用例列表"; +$lang->testcase->export = "導出數據"; +$lang->testcase->confirmStoryChange = '確認需求變動'; + +$lang->testcase->deleteStep = '刪除'; +$lang->testcase->insertBefore = '之前添加'; +$lang->testcase->insertAfter = '之後添加'; + +$lang->testcase->selectProduct = '請選擇產品'; +$lang->testcase->byModule = '按模組'; +$lang->testcase->assignToMe = '指派給我的用例'; +$lang->testcase->openedByMe = '由我創建的用例'; +$lang->testcase->allCases = '所有Case'; +$lang->testcase->needConfirm = '需求有變動的用例'; +$lang->testcase->moduleCases = '按模組瀏覽'; +$lang->testcase->bySearch = '搜索'; +$lang->testcase->doneByMe = '我完成的用例'; + +$lang->testcase->lblProductAndModule = '產品模組'; +$lang->testcase->lblTypeAndPri = '類型&優先順序'; +$lang->testcase->lblSystemBrowserAndHardware = '系統::瀏覽器'; +$lang->testcase->lblAssignAndMail = '指派給::抄送給'; +$lang->testcase->lblStory = '相關需求'; +$lang->testcase->lblLastEdited = '最後編輯'; + +$lang->testcase->legendRelated = '相關信息'; +$lang->testcase->legendBasicInfo = '基本信息'; +$lang->testcase->legendMailto = '抄送給'; +$lang->testcase->legendAttatch = '附件'; +$lang->testcase->legendLinkBugs = '相關Bug'; +$lang->testcase->legendOpenAndEdit = '創建編輯'; +$lang->testcase->legendStoryAndTask = '需求::任務'; +$lang->testcase->legendCases = '相關用例'; +$lang->testcase->legendSteps = '用例步驟'; +$lang->testcase->legendAction = '操作'; +$lang->testcase->legendHistory = '歷史記錄'; +$lang->testcase->legendComment = '備註'; +$lang->testcase->legendProduct = '產品模組'; +$lang->testcase->legendVersion = '版本歷史'; + +$lang->testcase->confirmDelete = '您確認要刪除該測試用例嗎?'; +$lang->testcase->same = '同上'; +$lang->testcase->notes = '(註:“用例類型”和“用例標題”必須填寫,否則此行無效)'; + +$lang->testcase->priList[3] = 3; +$lang->testcase->priList[1] = 1; +$lang->testcase->priList[2] = 2; +$lang->testcase->priList[4] = 4; + +/* Define the types. */ +$lang->testcase->typeList[''] = ''; +$lang->testcase->typeList['feature'] = '功能測試'; +$lang->testcase->typeList['performance'] = '性能測試'; +$lang->testcase->typeList['config'] = '配置相關'; +$lang->testcase->typeList['install'] = '安裝部署'; +$lang->testcase->typeList['security'] = '安全相關'; +$lang->testcase->typeList['other'] = '其他'; + +$lang->testcase->stageList[''] = ''; +$lang->testcase->stageList['unittest'] = '單元測試階段'; +$lang->testcase->stageList['feature'] = '功能測試階段'; +$lang->testcase->stageList['intergrate'] = '整合測試階段'; +$lang->testcase->stageList['system'] = '系統測試階段'; +$lang->testcase->stageList['smoke'] = '冒煙測試階段'; +$lang->testcase->stageList['bvt'] = '版本驗證階段'; + +$lang->testcase->statusList[''] = ''; +$lang->testcase->statusList['normal'] = '正常'; +$lang->testcase->statusList['blocked'] = '被阻塞'; +$lang->testcase->statusList['investigate'] = '研究中'; + +$lang->testcase->resultList['n/a'] = 'N/A'; +$lang->testcase->resultList['pass'] = '通過'; +$lang->testcase->resultList['fail'] = '失敗'; +$lang->testcase->resultList['blocked'] = '阻塞'; + +$lang->testcase->buttonEdit = '編輯'; +$lang->testcase->buttonToList = '返回'; diff --git a/module/testcase/model.php b/module/testcase/model.php index 546c26211c..de0867cf99 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -1,301 +1,301 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> -loadModel('product')->setMenu($products, $productID); - $selectHtml = $this->product->select($products, $productID, 'testcase', 'browse'); - foreach($this->lang->testcase->menu as $key => $menu) - { - $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow : $productID; - common::setMenuVars($this->lang->testcase->menu, $key, $replace); - } - } - - /** - * Create a case. - * - * @param int $bugID - * @access public - * @return void - */ - function create($bugID) - { - $now = helper::now(); - $case = fixer::input('post') - ->add('openedBy', $this->app->user->account) - ->add('openedDate', $now) - ->add('status', 'normal') - ->add('version', 1) - ->add('fromBug', $bugID) - ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - ->remove('steps,expects,files,labels') - ->setDefault('story', 0) - ->specialChars('title') - ->join('stage', ',') - ->get(); - $this->dao->insert(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->create->requiredFields, 'notempty')->exec(); - if(!$this->dao->isError()) - { - $caseID = $this->dao->lastInsertID(); - $this->loadModel('file')->saveUpload('testcase', $caseID); - foreach($this->post->steps as $stepID => $stepDesc) - { - if(empty($stepDesc)) continue; - $step->case = $caseID; - $step->version = 1; - $step->desc = htmlspecialchars($stepDesc); - $step->expect = htmlspecialchars($this->post->expects[$stepID]); - $this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec(); - } - return $caseID; - } - } - - /** - * Create a batch case. - * - * @access public - * @return void - */ - function batchCreate($productID) - { - $now = helper::now(); - $cases = fixer::input('post')->get(); - for($i = 0; $i < $this->config->testcase->batchCreate; $i++) - { - if($cases->type[$i] != '' and $cases->title[$i] != '') - { - $data[$i]->product = $productID; - $data[$i]->module = $cases->module[$i] == 'same' ? ($i == 0 ? 0 : $data[$i-1]->module) : $cases->module[$i]; - $data[$i]->type = $cases->type[$i] == 'same' ? ($i == 0 ? '' : $data[$i-1]->type) : $cases->type[$i]; - $data[$i]->story = $cases->story[$i] == 'same' ? ($i == 0 ? 0 : $data[$i-1]->story) : $cases->story[$i]; - $data[$i]->title = $cases->title[$i]; - $data[$i]->openedBy = $this->app->user->account; - $data[$i]->openedDate = $now; - $data[$i]->status = 'normal'; - $data[$i]->version = 1; - if($data[$i]->story != 0) $data[$i]->storyVersion = $this->loadModel('story')->getVersion($this->post->story); - - $this->dao->insert(TABLE_CASE)->data($data[$i]) - ->autoCheck() - ->batchCheck($this->config->testcase->create->requiredFields, 'notempty') - ->exec(); - - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - - $caseID = $this->dao->lastInsertID(); - $actionID = $this->loadModel('action')->create('case', $caseID, 'Opened'); - } - else - { - unset($cases->module[$i]); - unset($cases->type[$i]); - unset($cases->story[$i]); - unset($cases->title[$i]); - } - } - } - - /** - * Get cases of a module. - * - * @param int $productID - * @param int $moduleIds - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getModuleCases($productID, $moduleIds = 0, $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('*')->from(TABLE_CASE) - ->where('product')->eq((int)$productID) - ->beginIF($moduleIds)->andWhere('module')->in($moduleIds)->fi() - ->andWhere('deleted')->eq('0') - ->orderBy($orderBy)->page($pager)->fetchAll(); - } - - /** - * Get case info by ID. - * - * @param int $caseID - * @param int $version - * @access public - * @return object|bool - */ - public function getById($caseID, $version = 0) - { - $case = $this->dao->findById($caseID)->from(TABLE_CASE)->fetch(); - if(!$case) return false; - foreach($case as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $case->$key = ''; - if($case->story) - { - $story = $this->dao->findById($case->story)->from(TABLE_STORY)->fields('title, status, version')->fetch(); - $case->storyTitle = $story->title; - $case->storyStatus = $story->status; - $case->latestStoryVersion = $story->version; - } - if($case->linkCase) $case->linkCaseTitles = $this->dao->select('id,title')->from(TABLE_CASE)->where('id')->in($case->linkCase)->fetchPairs(); - if($version == 0) $version = $case->version; - $case->steps = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->eq($caseID)->andWhere('version')->eq($version)->fetchAll(); - $case->files = $this->loadModel('file')->getByObject('testcase', $caseID); - $case->currentVersion = $version ? $version : $case->version; - return $case; - } - - /** - * Update a case. - * - * @param int $caseID - * @access public - * @return void - */ - public function update($caseID) - { - $oldCase = $this->getById($caseID); - $now = helper::now(); - $stepChanged = false; - $steps = array(); - - //---------------- Judge steps changed or not.-------------------- */ - - /* Remove the empty setps in post. */ - foreach($this->post->steps as $key => $desc) - { - $desc = trim($desc); - if(!empty($desc)) $steps[] = array('desc' => $desc, 'expect' => trim($this->post->expects[$key])); - } - - /* If step count changed, case changed. */ - if(count($oldCase->steps) != count($steps)) - { - $stepChanged = true; - } - else - { - /* Compare every step. */ - foreach($oldCase->steps as $key => $oldStep) - { - if(trim($oldStep->desc) != trim($steps[$key]['desc']) or trim($oldStep->expect) != $steps[$key]['expect']) - { - $stepChanged = true; - break; - } - } - } - $version = $stepChanged ? $oldCase->version + 1 : $oldCase->version; - - $case = fixer::input('post') - ->add('lastEditedBy', $this->app->user->account) - ->add('lastEditedDate', $now) - ->add('version', $version) - ->setIF($this->post->story != false and $this->post->story != $oldCase->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) - ->setDefault('story', 0) - ->specialChars('title') - ->join('stage', ',') - ->remove('comment,steps,expects,files,labels') - ->get(); - $this->dao->update(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->edit->requiredFields, 'notempty')->where('id')->eq((int)$caseID)->exec(); - if(!$this->dao->isError()) - { - if($stepChanged) - { - foreach($this->post->steps as $stepID => $stepDesc) - { - if(empty($stepDesc)) continue; - $step->case = $caseID; - $step->version = $version; - $step->desc = htmlspecialchars($stepDesc); - $step->expect = htmlspecialchars($this->post->expects[$stepID]); - $this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec(); - } - } - - /* Join the steps to diff. */ - if($stepChanged) - { - $oldCase->steps = $this->joinStep($oldCase->steps); - $case->steps = $this->joinStep($this->getById($caseID, $version)->steps); - } - else - { - unset($oldCase->steps); - } - return common::createChanges($oldCase, $case); - } - } - - /** - * Join steps to a string, thus can diff them. - * - * @param array $steps - * @access private - * @return string - */ - private function joinStep($steps) - { - $retrun = ''; - foreach($steps as $step) $return .= $step->desc . ' EXPECT:' . $step->expect . "\n"; - return $return; - } - - /** - * Create case steps from a bug's step. - * - * @param string $steps - * @access public - * @return array - */ - function createStepsFromBug($steps) - { - $steps = strip_tags($steps); - $caseSteps = array((object)array('desc' => $steps, 'expect' => '')); // the default steps before parse. - $lblStep = strip_tags($this->lang->bug->tplStep); - $lblResult = strip_tags($this->lang->bug->tplResult); - $lblExpect = strip_tags($this->lang->bug->tplExpect); - $lblStepPos = strpos($steps, $lblStep); - $lblResultPos = strpos($steps, $lblResult); - $lblExpectPos = strpos($steps, $lblExpect); - - if($lblStepPos === false or $lblResultPos === false or $lblExpectPos === false) return $caseSteps; - - $caseSteps = substr($steps, $lblStepPos + strlen($lblStep), $lblResultPos - strlen($lblStep)); - $caseExpect = substr($steps, $lblExpectPos + strlen($lblExpect)); - $caseSteps = trim($caseSteps); - $caseExpect = trim($caseExpect); - - $caseSteps = explode("\n", trim($caseSteps)); - $stepCount = count($caseSteps); - foreach($caseSteps as $key => $caseStep) - { - $expect = $key + 1 == $stepCount ? $caseExpect : ''; - $caseSteps[$key] = (object)array('desc' => trim($caseStep), 'expect' => $expect); - } - return $caseSteps; - } -} + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('product')->setMenu($products, $productID); + $selectHtml = $this->product->select($products, $productID, 'testcase', 'browse'); + foreach($this->lang->testcase->menu as $key => $menu) + { + $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow : $productID; + common::setMenuVars($this->lang->testcase->menu, $key, $replace); + } + } + + /** + * Create a case. + * + * @param int $bugID + * @access public + * @return void + */ + function create($bugID) + { + $now = helper::now(); + $case = fixer::input('post') + ->add('openedBy', $this->app->user->account) + ->add('openedDate', $now) + ->add('status', 'normal') + ->add('version', 1) + ->add('fromBug', $bugID) + ->setIF($this->post->story != false, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + ->remove('steps,expects,files,labels') + ->setDefault('story', 0) + ->specialChars('title') + ->join('stage', ',') + ->get(); + $this->dao->insert(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->create->requiredFields, 'notempty')->exec(); + if(!$this->dao->isError()) + { + $caseID = $this->dao->lastInsertID(); + $this->loadModel('file')->saveUpload('testcase', $caseID); + foreach($this->post->steps as $stepID => $stepDesc) + { + if(empty($stepDesc)) continue; + $step->case = $caseID; + $step->version = 1; + $step->desc = htmlspecialchars($stepDesc); + $step->expect = htmlspecialchars($this->post->expects[$stepID]); + $this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec(); + } + return $caseID; + } + } + + /** + * Create a batch case. + * + * @access public + * @return void + */ + function batchCreate($productID) + { + $now = helper::now(); + $cases = fixer::input('post')->get(); + for($i = 0; $i < $this->config->testcase->batchCreate; $i++) + { + if($cases->type[$i] != '' and $cases->title[$i] != '') + { + $data[$i]->product = $productID; + $data[$i]->module = $cases->module[$i] == 'same' ? ($i == 0 ? 0 : $data[$i-1]->module) : $cases->module[$i]; + $data[$i]->type = $cases->type[$i] == 'same' ? ($i == 0 ? '' : $data[$i-1]->type) : $cases->type[$i]; + $data[$i]->story = $cases->story[$i] == 'same' ? ($i == 0 ? 0 : $data[$i-1]->story) : $cases->story[$i]; + $data[$i]->title = $cases->title[$i]; + $data[$i]->openedBy = $this->app->user->account; + $data[$i]->openedDate = $now; + $data[$i]->status = 'normal'; + $data[$i]->version = 1; + if($data[$i]->story != 0) $data[$i]->storyVersion = $this->loadModel('story')->getVersion($this->post->story); + + $this->dao->insert(TABLE_CASE)->data($data[$i]) + ->autoCheck() + ->batchCheck($this->config->testcase->create->requiredFields, 'notempty') + ->exec(); + + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + + $caseID = $this->dao->lastInsertID(); + $actionID = $this->loadModel('action')->create('case', $caseID, 'Opened'); + } + else + { + unset($cases->module[$i]); + unset($cases->type[$i]); + unset($cases->story[$i]); + unset($cases->title[$i]); + } + } + } + + /** + * Get cases of a module. + * + * @param int $productID + * @param int $moduleIds + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getModuleCases($productID, $moduleIds = 0, $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('*')->from(TABLE_CASE) + ->where('product')->eq((int)$productID) + ->beginIF($moduleIds)->andWhere('module')->in($moduleIds)->fi() + ->andWhere('deleted')->eq('0') + ->orderBy($orderBy)->page($pager)->fetchAll(); + } + + /** + * Get case info by ID. + * + * @param int $caseID + * @param int $version + * @access public + * @return object|bool + */ + public function getById($caseID, $version = 0) + { + $case = $this->dao->findById($caseID)->from(TABLE_CASE)->fetch(); + if(!$case) return false; + foreach($case as $key => $value) if(strpos($key, 'Date') !== false and !(int)substr($value, 0, 4)) $case->$key = ''; + if($case->story) + { + $story = $this->dao->findById($case->story)->from(TABLE_STORY)->fields('title, status, version')->fetch(); + $case->storyTitle = $story->title; + $case->storyStatus = $story->status; + $case->latestStoryVersion = $story->version; + } + if($case->linkCase) $case->linkCaseTitles = $this->dao->select('id,title')->from(TABLE_CASE)->where('id')->in($case->linkCase)->fetchPairs(); + if($version == 0) $version = $case->version; + $case->steps = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->eq($caseID)->andWhere('version')->eq($version)->fetchAll(); + $case->files = $this->loadModel('file')->getByObject('testcase', $caseID); + $case->currentVersion = $version ? $version : $case->version; + return $case; + } + + /** + * Update a case. + * + * @param int $caseID + * @access public + * @return void + */ + public function update($caseID) + { + $oldCase = $this->getById($caseID); + $now = helper::now(); + $stepChanged = false; + $steps = array(); + + //---------------- Judge steps changed or not.-------------------- */ + + /* Remove the empty setps in post. */ + foreach($this->post->steps as $key => $desc) + { + $desc = trim($desc); + if(!empty($desc)) $steps[] = array('desc' => $desc, 'expect' => trim($this->post->expects[$key])); + } + + /* If step count changed, case changed. */ + if(count($oldCase->steps) != count($steps)) + { + $stepChanged = true; + } + else + { + /* Compare every step. */ + foreach($oldCase->steps as $key => $oldStep) + { + if(trim($oldStep->desc) != trim($steps[$key]['desc']) or trim($oldStep->expect) != $steps[$key]['expect']) + { + $stepChanged = true; + break; + } + } + } + $version = $stepChanged ? $oldCase->version + 1 : $oldCase->version; + + $case = fixer::input('post') + ->add('lastEditedBy', $this->app->user->account) + ->add('lastEditedDate', $now) + ->add('version', $version) + ->setIF($this->post->story != false and $this->post->story != $oldCase->story, 'storyVersion', $this->loadModel('story')->getVersion($this->post->story)) + ->setDefault('story', 0) + ->specialChars('title') + ->join('stage', ',') + ->remove('comment,steps,expects,files,labels') + ->get(); + $this->dao->update(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->edit->requiredFields, 'notempty')->where('id')->eq((int)$caseID)->exec(); + if(!$this->dao->isError()) + { + if($stepChanged) + { + foreach($this->post->steps as $stepID => $stepDesc) + { + if(empty($stepDesc)) continue; + $step->case = $caseID; + $step->version = $version; + $step->desc = htmlspecialchars($stepDesc); + $step->expect = htmlspecialchars($this->post->expects[$stepID]); + $this->dao->insert(TABLE_CASESTEP)->data($step)->autoCheck()->exec(); + } + } + + /* Join the steps to diff. */ + if($stepChanged) + { + $oldCase->steps = $this->joinStep($oldCase->steps); + $case->steps = $this->joinStep($this->getById($caseID, $version)->steps); + } + else + { + unset($oldCase->steps); + } + return common::createChanges($oldCase, $case); + } + } + + /** + * Join steps to a string, thus can diff them. + * + * @param array $steps + * @access private + * @return string + */ + private function joinStep($steps) + { + $retrun = ''; + foreach($steps as $step) $return .= $step->desc . ' EXPECT:' . $step->expect . "\n"; + return $return; + } + + /** + * Create case steps from a bug's step. + * + * @param string $steps + * @access public + * @return array + */ + function createStepsFromBug($steps) + { + $steps = strip_tags($steps); + $caseSteps = array((object)array('desc' => $steps, 'expect' => '')); // the default steps before parse. + $lblStep = strip_tags($this->lang->bug->tplStep); + $lblResult = strip_tags($this->lang->bug->tplResult); + $lblExpect = strip_tags($this->lang->bug->tplExpect); + $lblStepPos = strpos($steps, $lblStep); + $lblResultPos = strpos($steps, $lblResult); + $lblExpectPos = strpos($steps, $lblExpect); + + if($lblStepPos === false or $lblResultPos === false or $lblExpectPos === false) return $caseSteps; + + $caseSteps = substr($steps, $lblStepPos + strlen($lblStep), $lblResultPos - strlen($lblStep)); + $caseExpect = substr($steps, $lblExpectPos + strlen($lblExpect)); + $caseSteps = trim($caseSteps); + $caseExpect = trim($caseExpect); + + $caseSteps = explode("\n", trim($caseSteps)); + $stepCount = count($caseSteps); + foreach($caseSteps as $key => $caseStep) + { + $expect = $key + 1 == $stepCount ? $caseExpect : ''; + $caseSteps[$key] = (object)array('desc' => trim($caseStep), 'expect' => $expect); + } + return $caseSteps; + } +} diff --git a/module/testcase/view/batchcreate.html.php b/module/testcase/view/batchcreate.html.php index 7eb2418a4c..e8fd9ddf31 100644 --- a/module/testcase/view/batchcreate.html.php +++ b/module/testcase/view/batchcreate.html.php @@ -1,45 +1,45 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - testcase->batchCreate; $i++):?> - testcase->same; if($i != 0) $currentModuleID = 'same';?> - testcase->typeList['same'] = $lang->testcase->same; $type = ($i == 0 ? 'feature' : 'same');?> - testcase->same; $story = $i == 0 ? '' : 'same';?> - - - - - - - - - - - - -
          testcase->batchCreate;?>
          idAB;?>testcase->module;?>testcase->type;?>testcase->story;?>testcase->title;?>
          testcase->typeList, $type, "class=select-1"); echo "*";?>*";?>
          -
          testcase->notes;?>
          -
          -
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + testcase->batchCreate; $i++):?> + testcase->same; if($i != 0) $currentModuleID = 'same';?> + testcase->typeList['same'] = $lang->testcase->same; $type = ($i == 0 ? 'feature' : 'same');?> + testcase->same; $story = $i == 0 ? '' : 'same';?> + + + + + + + + + + + + +
          testcase->batchCreate;?>
          idAB;?>testcase->module;?>testcase->type;?>testcase->story;?>testcase->title;?>
          testcase->typeList, $type, "class=select-1"); echo "*";?>*";?>
          +
          testcase->notes;?>
          +
          +
          +
          + diff --git a/module/testcase/view/browse.html.php b/module/testcase/view/browse.html.php index 86cdc139f0..7d4aca1af1 100644 --- a/module/testcase/view/browse.html.php +++ b/module/testcase/view/browse.html.php @@ -1,106 +1,106 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          -
          - " . $lang->testcase->moduleCases . " "; - echo "" . html::a($this->createLink('testcase', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->testcase->allCases) . ""; - echo "" . html::a($this->createLink('testcase', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->testcase->needConfirm) . ""; - echo "{$lang->testcase->bySearch} "; - ?> -
          -
          - export, '', 'class="export"'); ?> - testcase->batchCreate); ?> - testcase->create); ?> -
          -
          -
          '>
          - - - - - - - -
          -
          -
          - -
          - tree->manage);?> -
          -
          -
          - recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - - - - - - - - - - id");?> - - - - - - - - - - - - - - - - - - - -
          idAB);?>priAB);?>testcase->title);?>testcase->story);?>actions;?> typeAB);?> openedByAB);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?>statusAB);?>actions;?>
          id));?>pri?>title);?>createLink('story', 'view', "storyID=$case->story"), $case->storyTitle, '_blank');?>id"), $lang->confirm, 'hiddenwin');?>testcase->typeList[$case->type];?>openedBy];?>lastRunner];?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?>testcase->statusList[$case->status];?> - product&moduleID=$case->module&from=testcase¶m=$case->id", $lang->copy); - common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); - common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); - common::printLink('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->version", $this->app->loadLang('testtask')->testtask->runCase, '', 'class="runcase"'); - common::printLink('testtask', 'results', "runID=0&caseID=$case->id", $lang->testtask->results, '', 'class="results"'); - if(!($case->lastRunResult == 'fail' and common::printLink('bug', 'create', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $lang->testtask->createBug))) echo $lang->testtask->createBug; - ?> -
          show();?>
          -
          - + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          +
          + " . $lang->testcase->moduleCases . " "; + echo "" . html::a($this->createLink('testcase', 'browse', "productid=$productID&browseType=all¶m=0&orderBy=$orderBy&recTotal=0&recPerPage=200"), $lang->testcase->allCases) . ""; + echo "" . html::a($this->createLink('testcase', 'browse', "productid=$productID&browseType=needconfirm¶m=0"), $lang->testcase->needConfirm) . ""; + echo "{$lang->testcase->bySearch} "; + ?> +
          +
          + export, '', 'class="export"'); ?> + testcase->batchCreate); ?> + testcase->create); ?> +
          +
          +
          '>
          + + + + + + + +
          +
          +
          + +
          + tree->manage);?> +
          +
          +
          + recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + + + + + + + + + + id");?> + + + + + + + + + + + + + + + + + + + +
          idAB);?>priAB);?>testcase->title);?>testcase->story);?>actions;?> typeAB);?> openedByAB);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?>statusAB);?>actions;?>
          id));?>pri?>title);?>createLink('story', 'view', "storyID=$case->story"), $case->storyTitle, '_blank');?>id"), $lang->confirm, 'hiddenwin');?>testcase->typeList[$case->type];?>openedBy];?>lastRunner];?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($case->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?>testcase->statusList[$case->status];?> + product&moduleID=$case->module&from=testcase¶m=$case->id", $lang->copy); + common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); + common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); + common::printLink('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->version", $this->app->loadLang('testtask')->testtask->runCase, '', 'class="runcase"'); + common::printLink('testtask', 'results', "runID=0&caseID=$case->id", $lang->testtask->results, '', 'class="results"'); + if(!($case->lastRunResult == 'fail' and common::printLink('bug', 'create', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $lang->testtask->createBug))) echo $lang->testtask->createBug; + ?> +
          show();?>
          +
          + diff --git a/module/testcase/view/create.html.php b/module/testcase/view/create.html.php index a7d917b341..5db36d6a2b 100644 --- a/module/testcase/view/create.html.php +++ b/module/testcase/view/create.html.php @@ -1,97 +1,97 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testcase->create;?>
          testcase->lblProductAndModule;?> - - -
          testcase->type;?>testcase->typeList, $type, 'class=select-3');?>
          testcase->stage;?>testcase->stageList, $stage, "class='select-3' multiple='multiple'");?>
          testcase->pri;?>testcase->priList, $pri, 'class=select-3');?>
          testcase->lblStory;?> - - - - - createLink('story', 'view', "storyID=$storyID"), $lang->preview, '', "class='iframe' id='preview'");?> - -
          testcase->title;?>
          testcase->precondition;?>
          testcase->steps;?> - - - - - - - - $step) - { - $stepID += 1; - echo ""; - echo ""; - echo ''; - echo ''; - echo ""; - echo ''; - } - ?> -
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>actions;?>
          $stepID' . html::textarea('steps[]', $step->desc, "rows='3' class='w-p100'") . '' . html::textarea('expects[]', $step->expect, "rows='3' class='w-p100'") . '"; - echo "
          "; - echo "
          "; - echo "
          "; - echo "
          -
          testcase->keywords;?>
          testcase->files;?>fetch('file', 'buildform');?>
          -
          - + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testcase->create;?>
          testcase->lblProductAndModule;?> + + +
          testcase->type;?>testcase->typeList, $type, 'class=select-3');?>
          testcase->stage;?>testcase->stageList, $stage, "class='select-3' multiple='multiple'");?>
          testcase->pri;?>testcase->priList, $pri, 'class=select-3');?>
          testcase->lblStory;?> + + + + + createLink('story', 'view', "storyID=$storyID"), $lang->preview, '', "class='iframe' id='preview'");?> + +
          testcase->title;?>
          testcase->precondition;?>
          testcase->steps;?> + + + + + + + + $step) + { + $stepID += 1; + echo ""; + echo ""; + echo ''; + echo ''; + echo ""; + echo ''; + } + ?> +
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>actions;?>
          $stepID' . html::textarea('steps[]', $step->desc, "rows='3' class='w-p100'") . '' . html::textarea('expects[]', $step->expect, "rows='3' class='w-p100'") . '"; + echo "
          "; + echo "
          "; + echo "
          "; + echo "
          +
          testcase->keywords;?>
          testcase->files;?>fetch('file', 'buildform');?>
          +
          + diff --git a/module/testcase/view/edit.html.php b/module/testcase/view/edit.html.php index 8f655b6b23..4ee8fb894f 100644 --- a/module/testcase/view/edit.html.php +++ b/module/testcase/view/edit.html.php @@ -1,132 +1,132 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          -
          - CASE #id . $lang->colon;?> - title, 'class=text-1');?> -
          -
          -
          - - - - - - - -
          - -
          - testcase->precondition;?> - precondition, "rows='4' class='w-p100'");?> -
          - - - - - - - steps as $stepID => $step) - { - $stepID += 1; - echo ""; - echo ""; - echo ''; - echo ''; - echo ""; - echo ''; - } - ?> -
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>actions;?>
          $stepID' . html::textarea('steps[]', $step->desc, "rows='3' class='w-p100'") . '' . html::textarea('expects[]', $step->expect, "rows='3' class='w-p100'") . '"; - echo "
          "; - echo "
          "; - echo "
          "; - echo "
          - -
          - testcase->legendComment;?> - -
          -
          - testcase->legendAttatch;?> - fetch('file', 'buildform', 'filecount=2');?> -
          - -
          - - "' /> -
          - - -
          -
          - testcase->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testcase->product;?>
          testcase->module;?>
          testcase->story;?>
          story, 'class=select-1');?>
          - -
          testcase->type;?>testcase->typeList, $case->type, 'class=select-1');?> -
          testcase->stage;?>testcase->stageList, $case->stage, "class='select-1' multiple='multiple'");?>
          testcase->pri;?>testcase->priList, $case->pri, 'class=select-1');?> -
          testcase->status;?>testcase->statusList, $case->status, 'class=select-1');?>
          testcase->keywords;?>keywords, 'class=text-1');?>
          testcase->linkCase;?>linkCase, 'class=text-1');?>
          -
          -
          - testcase->legendOpenAndEdit;?> - - - - - - - - -
          testcase->openedBy;?>openedBy . $lang->at . $case->openedDate;?>
          testcase->lblLastEdited;?>lastEditedBy) echo $case->lastEditedBy . $lang->at . $case->lastEditedDate;?>
          -
          -
          - + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          + CASE #id . $lang->colon;?> + title, 'class=text-1');?> +
          +
          +
          + + + + + + + +
          + +
          + testcase->precondition;?> + precondition, "rows='4' class='w-p100'");?> +
          + + + + + + + steps as $stepID => $step) + { + $stepID += 1; + echo ""; + echo ""; + echo ''; + echo ''; + echo ""; + echo ''; + } + ?> +
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>actions;?>
          $stepID' . html::textarea('steps[]', $step->desc, "rows='3' class='w-p100'") . '' . html::textarea('expects[]', $step->expect, "rows='3' class='w-p100'") . '"; + echo "
          "; + echo "
          "; + echo "
          "; + echo "
          + +
          + testcase->legendComment;?> + +
          +
          + testcase->legendAttatch;?> + fetch('file', 'buildform', 'filecount=2');?> +
          + +
          + + "' /> +
          + + +
          +
          + testcase->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testcase->product;?>
          testcase->module;?>
          testcase->story;?>
          story, 'class=select-1');?>
          + +
          testcase->type;?>testcase->typeList, $case->type, 'class=select-1');?> +
          testcase->stage;?>testcase->stageList, $case->stage, "class='select-1' multiple='multiple'");?>
          testcase->pri;?>testcase->priList, $case->pri, 'class=select-1');?> +
          testcase->status;?>testcase->statusList, $case->status, 'class=select-1');?>
          testcase->keywords;?>keywords, 'class=text-1');?>
          testcase->linkCase;?>linkCase, 'class=text-1');?>
          +
          +
          + testcase->legendOpenAndEdit;?> + + + + + + + + +
          testcase->openedBy;?>openedBy . $lang->at . $case->openedDate;?>
          testcase->lblLastEdited;?>lastEditedBy) echo $case->lastEditedBy . $lang->at . $case->lastEditedDate;?>
          +
          +
          + diff --git a/module/testcase/view/export.html.php b/module/testcase/view/export.html.php index c9ff952a3f..d6d1f976d9 100755 --- a/module/testcase/view/export.html.php +++ b/module/testcase/view/export.html.php @@ -1,13 +1,13 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +?> + diff --git a/module/testcase/view/index.html.php b/module/testcase/view/index.html.php index 855e0c54f8..53c3b719b1 100644 --- a/module/testcase/view/index.html.php +++ b/module/testcase/view/index.html.php @@ -1,16 +1,16 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          \ No newline at end of file diff --git a/module/testcase/view/view.html.php b/module/testcase/view/view.html.php index 82ef21cfa2..f1bd7a2d38 100644 --- a/module/testcase/view/view.html.php +++ b/module/testcase/view/view.html.php @@ -1,198 +1,198 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          deleted) echo "class='deleted'";?>> - CASE #id . $lang->colon . $case->title;?> -
          - session->caseList != false ? $app->session->caseList : $this->createLink('testcase', 'browse', "productID=$case->product"); - if(!$case->deleted) - { - common::printLink('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->currentVersion", $this->app->loadLang('testtask')->testtask->runCase, '', 'class="runcase"'); - common::printLink('testtask', 'results', "runID=0&caseID=$case->id&version=$case->version", $lang->testtask->results, '', 'class="results"'); - if($case->lastRunResult == 'fail') common::printLink('bug', 'create', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $lang->testtask->createBug); - if(common::hasPriv('testcase', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); - common::printLink('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", $lang->copy); - common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          -
          - - - - - - - -
          - -
          - testcase->precondition;?> - precondition;?> -
          - - - - - - steps as $stepID => $step) - { - $stepID += 1; - echo ""; - echo ""; - echo ""; - echo ""; - } - ?> -
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>
          $stepID" . nl2br($step->desc) . "" . nl2br($step->expect) . "
          - fetch('file', 'printFiles', array('files' => $case->files, 'fieldset' => 'true'));?> - -
          - deleted) - { - if(common::hasPriv('testcase', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; - common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); - common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - -
          -
          - testcase->legendBasicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testcase->product;?>product", $productName)) echo $productName;?>
          testcase->module;?> - $module) - { - if(!common::printLink('testcase', 'browse', "productID=$case->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; - if(isset($modulePath[$key + 1])) echo $lang->arrow; - } - ?> -
          testcase->story;?> - storyTitle)) echo html::a($this->createLink('story', 'view', "storyID=$case->story"), "#$case->story:$case->storyTitle"); - if($case->story and $case->storyStatus == 'active' and $case->latestStoryVersion > $case->storyVersion) - { - echo "({$lang->story->changed} "; - echo html::a($this->createLink('testcase', 'confirmStoryChange', "caseID=$case->id"), $lang->confirm, 'hiddenwin'); - echo ")"; - } - ?> -
          testcase->type;?>testcase->typeList[$case->type];?>
          testcase->stage;?> - stage) - { - $stags = explode(',', $case->stage); - foreach($stags as $stage) - { - isset($lang->testcase->stageList[$stage]) ? print($lang->testcase->stageList[$stage]) : print($stage); - echo "
          "; - } - } - ?> -
          testcase->pri;?>pri;?>
          testcase->status;?>testcase->statusList[$case->status];?>
          app->loadLang('testtask')->testtask->lastRunTime;?>lastRunDate)) echo $case->lastRunDate;?>
          app->loadLang('testtask')->testtask->lastRunResult;?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?>
          testcase->keywords;?>keywords;?>
          testcase->linkCase;?> - linkCaseTitles)) - { - foreach($case->linkCaseTitles as $linkCaseID => $linkCaseTitle) - { - echo html::a($this->createLink('testcase', 'view', "caseID=$linkCaseID"), "#$linkCaseID $linkCaseTitle", '_blank') . '
          '; - } - } - ?> -
          -
          - -
          - testcase->legendOpenAndEdit;?> - - - - - - - - - -
          testcase->openedBy;?>openedBy . $lang->at . $case->openedDate;?>
          testcase->lblLastEdited;?>lastEditedBy) echo $case->lastEditedBy . $lang->at . $case->lastEditedDate;?>
          -
          -
          - testcase->legendVersion;?> -
          - version; $i >= 1; $i --) echo html::a(inlink('view', "caseID=$case->id&version=$i"), '#' . $i) . ' ';?> -
          -
          -
          - + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          deleted) echo "class='deleted'";?>> + CASE #id . $lang->colon . $case->title;?> +
          + session->caseList != false ? $app->session->caseList : $this->createLink('testcase', 'browse', "productID=$case->product"); + if(!$case->deleted) + { + common::printLink('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->currentVersion", $this->app->loadLang('testtask')->testtask->runCase, '', 'class="runcase"'); + common::printLink('testtask', 'results', "runID=0&caseID=$case->id&version=$case->version", $lang->testtask->results, '', 'class="results"'); + if($case->lastRunResult == 'fail') common::printLink('bug', 'create', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $lang->testtask->createBug); + if(common::hasPriv('testcase', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); + common::printLink('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", $lang->copy); + common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          +
          + + + + + + + +
          + +
          + testcase->precondition;?> + precondition;?> +
          + + + + + + steps as $stepID => $step) + { + $stepID += 1; + echo ""; + echo ""; + echo ""; + echo ""; + } + ?> +
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>
          $stepID" . nl2br($step->desc) . "" . nl2br($step->expect) . "
          + fetch('file', 'printFiles', array('files' => $case->files, 'fieldset' => 'true'));?> + +
          + deleted) + { + if(common::hasPriv('testcase', 'edit')) echo html::a('#', $lang->comment, '', 'onclick=setComment()'). ' '; + common::printLink('testcase', 'edit', "caseID=$case->id", $lang->testcase->buttonEdit); + common::printLink('testcase', 'delete', "caseID=$case->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + +
          +
          + testcase->legendBasicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testcase->product;?>product", $productName)) echo $productName;?>
          testcase->module;?> + $module) + { + if(!common::printLink('testcase', 'browse', "productID=$case->product&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; + if(isset($modulePath[$key + 1])) echo $lang->arrow; + } + ?> +
          testcase->story;?> + storyTitle)) echo html::a($this->createLink('story', 'view', "storyID=$case->story"), "#$case->story:$case->storyTitle"); + if($case->story and $case->storyStatus == 'active' and $case->latestStoryVersion > $case->storyVersion) + { + echo "({$lang->story->changed} "; + echo html::a($this->createLink('testcase', 'confirmStoryChange', "caseID=$case->id"), $lang->confirm, 'hiddenwin'); + echo ")"; + } + ?> +
          testcase->type;?>testcase->typeList[$case->type];?>
          testcase->stage;?> + stage) + { + $stags = explode(',', $case->stage); + foreach($stags as $stage) + { + isset($lang->testcase->stageList[$stage]) ? print($lang->testcase->stageList[$stage]) : print($stage); + echo "
          "; + } + } + ?> +
          testcase->pri;?>pri;?>
          testcase->status;?>testcase->statusList[$case->status];?>
          app->loadLang('testtask')->testtask->lastRunTime;?>lastRunDate)) echo $case->lastRunDate;?>
          app->loadLang('testtask')->testtask->lastRunResult;?>lastRunResult) echo $lang->testcase->resultList[$case->lastRunResult];?>
          testcase->keywords;?>keywords;?>
          testcase->linkCase;?> + linkCaseTitles)) + { + foreach($case->linkCaseTitles as $linkCaseID => $linkCaseTitle) + { + echo html::a($this->createLink('testcase', 'view', "caseID=$linkCaseID"), "#$linkCaseID $linkCaseTitle", '_blank') . '
          '; + } + } + ?> +
          +
          + +
          + testcase->legendOpenAndEdit;?> + + + + + + + + + +
          testcase->openedBy;?>openedBy . $lang->at . $case->openedDate;?>
          testcase->lblLastEdited;?>lastEditedBy) echo $case->lastEditedBy . $lang->at . $case->lastEditedDate;?>
          +
          +
          + testcase->legendVersion;?> +
          + version; $i >= 1; $i --) echo html::a(inlink('view', "caseID=$case->id&version=$i"), '#' . $i) . ' ';?> +
          +
          +
          + diff --git a/module/testtask/control.php b/module/testtask/control.php index a228602c7c..9bd0cdac00 100644 --- a/module/testtask/control.php +++ b/module/testtask/control.php @@ -1,471 +1,471 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -class testtask extends control -{ - private $products = array(); - - /** - * Construct function, load product module, assign products to view auto. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('product'); - $this->view->products = $this->products = $this->product->getPairs(); - } - - /** - * Index page, header to browse. - * - * @access public - * @return void - */ - public function index() - { - $this->locate($this->createLink('testtask', 'browse')); - } - - /** - * Browse test tasks. - * - * @param int $productID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function browse($productID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $this->session->set('testtaskList', $this->app->getURI(true)); - - /* Set menu. */ - $productID = $this->product->saveState($productID, $this->products); - $this->testtask->setMenu($this->products, $productID); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->common; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->common; - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->pager = $pager; - $this->view->orderBy = $orderBy; - $this->view->tasks = $this->testtask->getProductTasks($productID); - $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); - - $this->display(); - } - - /** - * Create a test task. - * - * @param int $productID - * @access public - * @return void - */ - public function create($productID, $projectID = 0, $build = 0) - { - if(!empty($_POST)) - { - $taskID = $this->testtask->create(); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('testtask', $taskID, 'opened'); - die(js::locate($this->createLink('testtask', 'browse', "productID=$productID"), 'parent')); - } - - /* Create testtask from build of project.*/ - if($projectID != 0 and $build != 0) - { - $products = $this->dao->select('t2.id, t2.name') - ->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t1.project')->eq($projectID) - ->fetchPairs('id'); - - foreach($products as $key => $value) - { - $productID = $key; - break; - } - - $projects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetchPairs('id'); - $builds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->eq($build)->fetchPairs('id'); - } - - /* Create testtask from testtask of project.*/ - if($projectID != 0 and $build == 0) - { - $products = $this->dao->select('t2.id, t2.name') - ->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t1.project')->eq($projectID) - ->fetchPairs('id'); - - foreach($products as $key => $value) - { - $productID = $key; - break; - } - - $projects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetchPairs('id'); - $builds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('project')->eq($projectID)->fetchPairs('id'); - } - - /* Create testtask from testtask of test.*/ - if($projectID == 0) - { - $projects = $this->product->getProjectPairs($productID, $params = 'nodeleted'); - $builds = $this->loadModel('build')->getProductBuildPairs($productID); - } - - /* Set menu. */ - $productID = $this->product->saveState($productID, $this->products); - $this->testtask->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->create; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->create; - - if($projectID != 0) - { - $this->view->products = $products; - $this->view->projectID = $projectID; - } - $this->view->projects = $projects; - $this->view->productID = $productID; - $this->view->builds = $builds; - $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted'); - - $this->display(); - } - - /** - * View a test task. - * - * @param int $taskID - * @access public - * @return void - */ - public function view($taskID) - { - /* Get test task, and set menu. */ - $task = $this->testtask->getById($taskID); - if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); - $productID = $task->product; - $this->testtask->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->view; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->view; - - $this->view->productID = $productID; - $this->view->task = $task; - $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); - $this->view->actions = $this->loadModel('action')->getList('testtask', $taskID); - - $this->display(); - } - - /** - * Browse cases of a test task. - * - * @param int $taskID - * @param string $browseType bymodule|all|assignedtome - * @param int $param - * @access public - * @return void - */ - public function cases($taskID, $browseType = 'byModule', $param = 0) - { - /* Save the session. */ - $this->app->loadLang('testcase'); - $this->session->set('caseList', $this->app->getURI(true)); - - /* Set the browseType and moduleID. */ - $browseType = strtolower($browseType); - $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; - - /* Get task and product info, set menu. */ - $task = $this->testtask->getById($taskID); - if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); - $productID = $task->product; - $this->testtask->setMenu($this->products, $productID); - - if($browseType == 'bymodule' or $browseType == 'all') - { - $modules = ''; - if($moduleID) $modules = $this->loadModel('tree')->getAllChildID($moduleID); - $this->view->runs = $this->testtask->getRuns($taskID, $modules); - } - elseif($browseType == 'assignedtome') - { - $this->view->runs = $this->testtask->getUserRuns($taskID, $this->session->user->account); - } - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->cases; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->cases; - - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->task = $task; - $this->view->users = $this->loadModel('user')->getPairs('noclosed'); - $this->view->moduleTree = $this->loadModel('tree')->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createTestTaskLink'), $extra = $taskID); - $this->view->browseType = $browseType; - $this->view->taskID = $taskID; - $this->view->moduleID = $moduleID; - $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; - - $this->display(); - } - - /** - * Edit a test task. - * - * @param int $taskID - * @access public - * @return void - */ - public function edit($taskID) - { - if(!empty($_POST)) - { - $changes = $this->testtask->update($taskID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('testtask', $taskID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "taskID=$taskID"), 'parent')); - } - - /* Get task info. */ - $task = $this->testtask->getById($taskID); - $productID = $this->product->saveState($task->product, $this->products); - - /* Set menu. */ - $this->testtask->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->edit; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->edit; - - $this->view->task = $task; - $this->view->projects = $this->product->getProjectPairs($productID); - $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); - $this->view->users = $this->loadModel('user')->getPairs(); - - $this->display(); - } - - /** - * Delete a test task. - * - * @param int $taskID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($taskID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->testtask->confirmDelete, inlink('delete', "taskID=$taskID&confirm=yes"))); - } - else - { - $task = $this->testtask->getByID($taskID); - $this->testtask->delete(TABLE_TESTTASK, $taskID); - die(js::locate(inlink('browse', "product=$task->product"), 'parent')); - } - } - - /** - * Link cases to a test task. - * - * @param int $taskID - * @access public - * @return void - */ - public function linkCase($taskID, $param = 'all', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - if(!empty($_POST)) - { - $this->testtask->linkCase($taskID); - $this->locate(inlink('cases', "taskID=$taskID")); - } - - /* Save session. */ - $this->session->set('caseList', $this->app->getURI(true)); - - /* Get task and product id. */ - $task = $this->testtask->getById($taskID); - $productID = $this->product->saveState($task->product, $this->products); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* Build the search form. */ - $this->loadModel('testcase'); - $this->config->testcase->search['params']['product']['values']= array($productID => $this->products[$productID], 'all' => $this->lang->testcase->allProduct); - $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case'); - $this->config->testcase->search['actionURL'] = inlink('linkcase', "taskID=$taskID"); - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->testcase->search); - - /* Save session. */ - $this->testtask->setMenu($this->products, $productID); - - $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->linkCase; - $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testtask->linkCase; - - /* Get cases. */ - if($this->session->testcaseQuery == false) $this->session->set('testcaseQuery', ' 1 = 1'); - $query = str_replace("`product` = 'all'", '1', $this->session->testcaseQuery); // If search all product, replace product = all to 1=1 - $linkedCases = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs('case'); - if($param == 'all') - { - $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) - ->andWhere('product')->eq($productID) - ->andWhere('id')->notIN($linkedCases) - ->andWhere('deleted')->eq(0) - ->orderBy('id desc') - ->page($pager) - ->fetchAll(); - } - if($param == 'bystory') - { - $stories = $this->dao->select('stories')->from(TABLE_BUILD)->where('id')->eq($task->build)->fetch('stories'); - - $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) - ->andWhere('product')->eq($productID) - ->beginIF($linkedCases)->andWhere('id')->notIN($linkedCases)->fi() - ->andWhere('story')->in($stories) - ->andWhere('deleted')->eq(0) - ->orderBy('id desc') - ->page($pager) - ->fetchAll(); - } - if($param == 'bybug') - { - $bugs = $this->dao->select('bugs')->from(TABLE_BUILD)->where('id')->eq($task->build)->fetch('bugs'); - $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) - ->andWhere('product')->eq($productID) - ->beginIF($linkedCases)->andWhere('id')->notIN($linkedCases)->fi() - ->andWhere('fromBug')->in($bugs) - ->andWhere('deleted')->eq(0) - ->orderBy('id desc') - ->page($pager) - ->fetchAll(); - } - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->cases = $cases; - $this->view->taskID = $taskID; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * Remove a case from test task. - * - * @param int $rowID - * @access public - * @return void - */ - public function unlinkCase($rowID) - { - $this->dao->delete()->from(TABLE_TESTRUN)->where('id')->eq((int)$rowID)->exec(); - die(js::reload('parent')); - } - - /** - * Run case. - * - * @param int $runID - * @param String $extras others params, forexample, caseID=10, version=3 - * @access public - * @return void - */ - public function runCase($runID, $caseID = 0, $version = 0) - { - if(!empty($_POST)) - { - $this->testtask->createResult($runID); - if(dao::isError()) die(js::error(dao::getError())); - echo js::reload('parent'); - die(js::closeWindow()); - } - - if(!$caseID) $run = $this->testtask->getRunById($runID); - if($caseID) $run->case = $this->loadModel('testcase')->getById($caseID, $version); - - $this->view->run = $run; - - die($this->display()); - } - - /** - * View test results of a test run. - * - * @param int $runID - * @param int $caseID - * @access public - * @return void - */ - public function results($runID, $caseID = 0, $version = 0) - { - if($caseID) - { - $this->view->case = $this->loadModel('testcase')->getByID($caseID, $version); - $this->view->results = $this->testtask->getResults(0, $caseID); - } - else - { - $this->view->case = $this->testtask->getRunById($runID)->case; - $this->view->results = $this->testtask->getResults($runID); - } - $this->view->users = $this->loadModel('user')->getPairs('noclosed, noletter'); - - die($this->display()); - } - - /** - * Batch assign cases. - * - * @param int $taskID - * @access public - * @return void - */ - public function batchAssign($taskID) - { - $this->dao->update(TABLE_TESTRUN) - ->set('assignedTo')->eq($this->post->assignedTo) - ->where('task')->eq((int)$taskID) - ->andWhere('`case`')->in($this->post->cases) - ->exec(); - die(js::reload('parent')); - } -} + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +class testtask extends control +{ + private $products = array(); + + /** + * Construct function, load product module, assign products to view auto. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('product'); + $this->view->products = $this->products = $this->product->getPairs(); + } + + /** + * Index page, header to browse. + * + * @access public + * @return void + */ + public function index() + { + $this->locate($this->createLink('testtask', 'browse')); + } + + /** + * Browse test tasks. + * + * @param int $productID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function browse($productID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $this->session->set('testtaskList', $this->app->getURI(true)); + + /* Set menu. */ + $productID = $this->product->saveState($productID, $this->products); + $this->testtask->setMenu($this->products, $productID); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + $this->view->header->title = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->common; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->common; + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->pager = $pager; + $this->view->orderBy = $orderBy; + $this->view->tasks = $this->testtask->getProductTasks($productID); + $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); + + $this->display(); + } + + /** + * Create a test task. + * + * @param int $productID + * @access public + * @return void + */ + public function create($productID, $projectID = 0, $build = 0) + { + if(!empty($_POST)) + { + $taskID = $this->testtask->create(); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('testtask', $taskID, 'opened'); + die(js::locate($this->createLink('testtask', 'browse', "productID=$productID"), 'parent')); + } + + /* Create testtask from build of project.*/ + if($projectID != 0 and $build != 0) + { + $products = $this->dao->select('t2.id, t2.name') + ->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t1.project')->eq($projectID) + ->fetchPairs('id'); + + foreach($products as $key => $value) + { + $productID = $key; + break; + } + + $projects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetchPairs('id'); + $builds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('id')->eq($build)->fetchPairs('id'); + } + + /* Create testtask from testtask of project.*/ + if($projectID != 0 and $build == 0) + { + $products = $this->dao->select('t2.id, t2.name') + ->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t1.project')->eq($projectID) + ->fetchPairs('id'); + + foreach($products as $key => $value) + { + $productID = $key; + break; + } + + $projects = $this->dao->select('id, name')->from(TABLE_PROJECT)->where('id')->eq($projectID)->fetchPairs('id'); + $builds = $this->dao->select('id, name')->from(TABLE_BUILD)->where('project')->eq($projectID)->fetchPairs('id'); + } + + /* Create testtask from testtask of test.*/ + if($projectID == 0) + { + $projects = $this->product->getProjectPairs($productID, $params = 'nodeleted'); + $builds = $this->loadModel('build')->getProductBuildPairs($productID); + } + + /* Set menu. */ + $productID = $this->product->saveState($productID, $this->products); + $this->testtask->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->create; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->create; + + if($projectID != 0) + { + $this->view->products = $products; + $this->view->projectID = $projectID; + } + $this->view->projects = $projects; + $this->view->productID = $productID; + $this->view->builds = $builds; + $this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted'); + + $this->display(); + } + + /** + * View a test task. + * + * @param int $taskID + * @access public + * @return void + */ + public function view($taskID) + { + /* Get test task, and set menu. */ + $task = $this->testtask->getById($taskID); + if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); + $productID = $task->product; + $this->testtask->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->view; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->view; + + $this->view->productID = $productID; + $this->view->task = $task; + $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); + $this->view->actions = $this->loadModel('action')->getList('testtask', $taskID); + + $this->display(); + } + + /** + * Browse cases of a test task. + * + * @param int $taskID + * @param string $browseType bymodule|all|assignedtome + * @param int $param + * @access public + * @return void + */ + public function cases($taskID, $browseType = 'byModule', $param = 0) + { + /* Save the session. */ + $this->app->loadLang('testcase'); + $this->session->set('caseList', $this->app->getURI(true)); + + /* Set the browseType and moduleID. */ + $browseType = strtolower($browseType); + $moduleID = ($browseType == 'bymodule') ? (int)$param : 0; + + /* Get task and product info, set menu. */ + $task = $this->testtask->getById($taskID); + if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); + $productID = $task->product; + $this->testtask->setMenu($this->products, $productID); + + if($browseType == 'bymodule' or $browseType == 'all') + { + $modules = ''; + if($moduleID) $modules = $this->loadModel('tree')->getAllChildID($moduleID); + $this->view->runs = $this->testtask->getRuns($taskID, $modules); + } + elseif($browseType == 'assignedtome') + { + $this->view->runs = $this->testtask->getUserRuns($taskID, $this->session->user->account); + } + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->cases; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->cases; + + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->task = $task; + $this->view->users = $this->loadModel('user')->getPairs('noclosed'); + $this->view->moduleTree = $this->loadModel('tree')->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createTestTaskLink'), $extra = $taskID); + $this->view->browseType = $browseType; + $this->view->taskID = $taskID; + $this->view->moduleID = $moduleID; + $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; + + $this->display(); + } + + /** + * Edit a test task. + * + * @param int $taskID + * @access public + * @return void + */ + public function edit($taskID) + { + if(!empty($_POST)) + { + $changes = $this->testtask->update($taskID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('testtask', $taskID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "taskID=$taskID"), 'parent')); + } + + /* Get task info. */ + $task = $this->testtask->getById($taskID); + $productID = $this->product->saveState($task->product, $this->products); + + /* Set menu. */ + $this->testtask->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->edit; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->edit; + + $this->view->task = $task; + $this->view->projects = $this->product->getProjectPairs($productID); + $this->view->builds = $this->loadModel('build')->getProductBuildPairs($productID); + $this->view->users = $this->loadModel('user')->getPairs(); + + $this->display(); + } + + /** + * Delete a test task. + * + * @param int $taskID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($taskID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->testtask->confirmDelete, inlink('delete', "taskID=$taskID&confirm=yes"))); + } + else + { + $task = $this->testtask->getByID($taskID); + $this->testtask->delete(TABLE_TESTTASK, $taskID); + die(js::locate(inlink('browse', "product=$task->product"), 'parent')); + } + } + + /** + * Link cases to a test task. + * + * @param int $taskID + * @access public + * @return void + */ + public function linkCase($taskID, $param = 'all', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + if(!empty($_POST)) + { + $this->testtask->linkCase($taskID); + $this->locate(inlink('cases', "taskID=$taskID")); + } + + /* Save session. */ + $this->session->set('caseList', $this->app->getURI(true)); + + /* Get task and product id. */ + $task = $this->testtask->getById($taskID); + $productID = $this->product->saveState($task->product, $this->products); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* Build the search form. */ + $this->loadModel('testcase'); + $this->config->testcase->search['params']['product']['values']= array($productID => $this->products[$productID], 'all' => $this->lang->testcase->allProduct); + $this->config->testcase->search['params']['module']['values'] = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case'); + $this->config->testcase->search['actionURL'] = inlink('linkcase', "taskID=$taskID"); + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->testcase->search); + + /* Save session. */ + $this->testtask->setMenu($this->products, $productID); + + $this->view->header['title'] = $this->products[$productID] . $this->lang->colon . $this->lang->testtask->linkCase; + $this->view->position[] = html::a($this->createLink('testtask', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testtask->linkCase; + + /* Get cases. */ + if($this->session->testcaseQuery == false) $this->session->set('testcaseQuery', ' 1 = 1'); + $query = str_replace("`product` = 'all'", '1', $this->session->testcaseQuery); // If search all product, replace product = all to 1=1 + $linkedCases = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs('case'); + if($param == 'all') + { + $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) + ->andWhere('product')->eq($productID) + ->andWhere('id')->notIN($linkedCases) + ->andWhere('deleted')->eq(0) + ->orderBy('id desc') + ->page($pager) + ->fetchAll(); + } + if($param == 'bystory') + { + $stories = $this->dao->select('stories')->from(TABLE_BUILD)->where('id')->eq($task->build)->fetch('stories'); + + $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) + ->andWhere('product')->eq($productID) + ->beginIF($linkedCases)->andWhere('id')->notIN($linkedCases)->fi() + ->andWhere('story')->in($stories) + ->andWhere('deleted')->eq(0) + ->orderBy('id desc') + ->page($pager) + ->fetchAll(); + } + if($param == 'bybug') + { + $bugs = $this->dao->select('bugs')->from(TABLE_BUILD)->where('id')->eq($task->build)->fetch('bugs'); + $cases = $this->dao->select('*')->from(TABLE_CASE)->where($query) + ->andWhere('product')->eq($productID) + ->beginIF($linkedCases)->andWhere('id')->notIN($linkedCases)->fi() + ->andWhere('fromBug')->in($bugs) + ->andWhere('deleted')->eq(0) + ->orderBy('id desc') + ->page($pager) + ->fetchAll(); + } + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->cases = $cases; + $this->view->taskID = $taskID; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * Remove a case from test task. + * + * @param int $rowID + * @access public + * @return void + */ + public function unlinkCase($rowID) + { + $this->dao->delete()->from(TABLE_TESTRUN)->where('id')->eq((int)$rowID)->exec(); + die(js::reload('parent')); + } + + /** + * Run case. + * + * @param int $runID + * @param String $extras others params, forexample, caseID=10, version=3 + * @access public + * @return void + */ + public function runCase($runID, $caseID = 0, $version = 0) + { + if(!empty($_POST)) + { + $this->testtask->createResult($runID); + if(dao::isError()) die(js::error(dao::getError())); + echo js::reload('parent'); + die(js::closeWindow()); + } + + if(!$caseID) $run = $this->testtask->getRunById($runID); + if($caseID) $run->case = $this->loadModel('testcase')->getById($caseID, $version); + + $this->view->run = $run; + + die($this->display()); + } + + /** + * View test results of a test run. + * + * @param int $runID + * @param int $caseID + * @access public + * @return void + */ + public function results($runID, $caseID = 0, $version = 0) + { + if($caseID) + { + $this->view->case = $this->loadModel('testcase')->getByID($caseID, $version); + $this->view->results = $this->testtask->getResults(0, $caseID); + } + else + { + $this->view->case = $this->testtask->getRunById($runID)->case; + $this->view->results = $this->testtask->getResults($runID); + } + $this->view->users = $this->loadModel('user')->getPairs('noclosed, noletter'); + + die($this->display()); + } + + /** + * Batch assign cases. + * + * @param int $taskID + * @access public + * @return void + */ + public function batchAssign($taskID) + { + $this->dao->update(TABLE_TESTRUN) + ->set('assignedTo')->eq($this->post->assignedTo) + ->where('task')->eq((int)$taskID) + ->andWhere('`case`')->in($this->post->cases) + ->exec(); + die(js::reload('parent')); + } +} diff --git a/module/testtask/lang/en.php b/module/testtask/lang/en.php index e666a85e04..9ab0c1afdf 100644 --- a/module/testtask/lang/en.php +++ b/module/testtask/lang/en.php @@ -1,66 +1,66 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->testtask->index = "Index"; -$lang->testtask->create = "Create"; -$lang->testtask->delete = "Delete"; -$lang->testtask->view = "Info"; -$lang->testtask->edit = "Edit"; -$lang->testtask->browse = "Browse"; -$lang->testtask->linkCase = "Link case"; -$lang->testtask->linkCaseAB = "Link"; -$lang->testtask->unlinkCase = "Remove"; -$lang->testtask->batchAssign = "Batch Assign"; -$lang->testtask->runCase = "Run"; -$lang->testtask->results = "Result"; -$lang->testtask->createBug = "Create bug"; -$lang->testtask->assign = 'Assign'; -$lang->testtask->cases = 'Cases'; - -$lang->testtask->common = 'Test task'; -$lang->testtask->id = 'ID'; -$lang->testtask->product = 'Product'; -$lang->testtask->project = 'Project'; -$lang->testtask->build = 'Build'; -$lang->testtask->owner = 'Owner'; -$lang->testtask->name = 'Name'; -$lang->testtask->begin = 'Begin'; -$lang->testtask->end = 'End'; -$lang->testtask->desc = 'Desc'; -$lang->testtask->status = 'Status'; -$lang->testtask->assignedTo = 'Assigned to'; -$lang->testtask->linkVersion = 'Link(version)'; -$lang->testtask->lastRunAccount = "Run account"; -$lang->testtask->lastRunTime = 'Last run'; -$lang->testtask->lastRunResult = 'Last result'; - -$lang->testtask->statusList['wait'] = 'Waiting'; -$lang->testtask->statusList['doing'] = 'Doing'; -$lang->testtask->statusList['done'] = 'Done'; -$lang->testtask->statusList['blocked'] = 'Blocked'; - -$lang->testtask->unlinkedCases = 'Unlinked cases'; -$lang->testtask->linkedCases = 'Linked cases'; -$lang->testtask->linkByStory = 'Link by story'; -$lang->testtask->linkByBug = 'Link by bug'; -$lang->testtask->confirmDelete = 'Are you sure to delete this test task?'; -$lang->testtask->passAll = 'Pass all'; -$lang->testtask->pass = 'Pass'; -$lang->testtask->fail = 'Fail'; - -$lang->testtask->byModule = 'By module'; -$lang->testtask->assignedToMe = 'Assgined to me'; -$lang->testtask->allCases = 'All Cases'; - -$lang->testtask->lblCases = 'Case list'; -$lang->testtask->lblUnlinkCase = 'Remove case'; -$lang->testtask->lblRunCase = 'Run'; -$lang->testtask->lblResults = 'Result'; + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->testtask->index = "Index"; +$lang->testtask->create = "Create"; +$lang->testtask->delete = "Delete"; +$lang->testtask->view = "Info"; +$lang->testtask->edit = "Edit"; +$lang->testtask->browse = "Browse"; +$lang->testtask->linkCase = "Link case"; +$lang->testtask->linkCaseAB = "Link"; +$lang->testtask->unlinkCase = "Remove"; +$lang->testtask->batchAssign = "Batch Assign"; +$lang->testtask->runCase = "Run"; +$lang->testtask->results = "Result"; +$lang->testtask->createBug = "Create bug"; +$lang->testtask->assign = 'Assign'; +$lang->testtask->cases = 'Cases'; + +$lang->testtask->common = 'Test task'; +$lang->testtask->id = 'ID'; +$lang->testtask->product = 'Product'; +$lang->testtask->project = 'Project'; +$lang->testtask->build = 'Build'; +$lang->testtask->owner = 'Owner'; +$lang->testtask->name = 'Name'; +$lang->testtask->begin = 'Begin'; +$lang->testtask->end = 'End'; +$lang->testtask->desc = 'Desc'; +$lang->testtask->status = 'Status'; +$lang->testtask->assignedTo = 'Assigned to'; +$lang->testtask->linkVersion = 'Link(version)'; +$lang->testtask->lastRunAccount = "Run account"; +$lang->testtask->lastRunTime = 'Last run'; +$lang->testtask->lastRunResult = 'Last result'; + +$lang->testtask->statusList['wait'] = 'Waiting'; +$lang->testtask->statusList['doing'] = 'Doing'; +$lang->testtask->statusList['done'] = 'Done'; +$lang->testtask->statusList['blocked'] = 'Blocked'; + +$lang->testtask->unlinkedCases = 'Unlinked cases'; +$lang->testtask->linkedCases = 'Linked cases'; +$lang->testtask->linkByStory = 'Link by story'; +$lang->testtask->linkByBug = 'Link by bug'; +$lang->testtask->confirmDelete = 'Are you sure to delete this test task?'; +$lang->testtask->passAll = 'Pass all'; +$lang->testtask->pass = 'Pass'; +$lang->testtask->fail = 'Fail'; + +$lang->testtask->byModule = 'By module'; +$lang->testtask->assignedToMe = 'Assgined to me'; +$lang->testtask->allCases = 'All Cases'; + +$lang->testtask->lblCases = 'Case list'; +$lang->testtask->lblUnlinkCase = 'Remove case'; +$lang->testtask->lblRunCase = 'Run'; +$lang->testtask->lblResults = 'Result'; diff --git a/module/testtask/lang/zh-cn.php b/module/testtask/lang/zh-cn.php index d7fc334ceb..72f4496a3b 100644 --- a/module/testtask/lang/zh-cn.php +++ b/module/testtask/lang/zh-cn.php @@ -1,66 +1,66 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->testtask->index = "测试任务首页"; -$lang->testtask->create = "创建测试任务"; -$lang->testtask->delete = "删除测试任务"; -$lang->testtask->view = "测试任务详情"; -$lang->testtask->edit = "编辑测试任务"; -$lang->testtask->browse = "测试任务列表"; -$lang->testtask->linkCase = "关联用例"; -$lang->testtask->linkCaseAB = "关联"; -$lang->testtask->unlinkCase = "移除"; -$lang->testtask->batchAssign = "批量指派"; -$lang->testtask->runCase = "执行"; -$lang->testtask->results = "结果"; -$lang->testtask->createBug = "创建Bug"; -$lang->testtask->assign = '指派'; -$lang->testtask->cases = '用例'; - -$lang->testtask->common = '测试任务'; -$lang->testtask->id = '任务编号'; -$lang->testtask->product = '所属产品'; -$lang->testtask->project = '所属项目'; -$lang->testtask->build = 'Build'; -$lang->testtask->owner = '负责人'; -$lang->testtask->name = '任务名称'; -$lang->testtask->begin = '开始日期'; -$lang->testtask->end = '结束日期'; -$lang->testtask->desc = '任务描述'; -$lang->testtask->status = '当前状态'; -$lang->testtask->assignedTo = '指派给'; -$lang->testtask->linkVersion = '关联(版本)'; -$lang->testtask->lastRunAccount = '最后执行人'; -$lang->testtask->lastRunTime = '最后执行时间'; -$lang->testtask->lastRunResult = '最终结果'; - -$lang->testtask->statusList['wait'] = '未开始'; -$lang->testtask->statusList['doing'] = '进行中'; -$lang->testtask->statusList['done'] = '已完成'; -$lang->testtask->statusList['blocked'] = '被阻塞'; - -$lang->testtask->unlinkedCases = '未关联用例列表'; -$lang->testtask->linkedCases = '已关联用例列表'; -$lang->testtask->linkByStory = '按需求关联用例'; -$lang->testtask->linkByBug = '按Bug关联用例'; -$lang->testtask->confirmDelete = '您确认要删除该测试任务吗?'; -$lang->testtask->passAll = '全部通过'; -$lang->testtask->pass = '通过'; -$lang->testtask->fail = '失败'; - -$lang->testtask->byModule = '按模块'; -$lang->testtask->assignedToMe = '指派给我'; -$lang->testtask->allCases = '所有Case'; - -$lang->testtask->lblCases = '用例列表'; -$lang->testtask->lblUnlinkCase = '移除用例'; -$lang->testtask->lblRunCase = '执行用例'; -$lang->testtask->lblResults = '执行结果'; + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->testtask->index = "测试任务首页"; +$lang->testtask->create = "创建测试任务"; +$lang->testtask->delete = "删除测试任务"; +$lang->testtask->view = "测试任务详情"; +$lang->testtask->edit = "编辑测试任务"; +$lang->testtask->browse = "测试任务列表"; +$lang->testtask->linkCase = "关联用例"; +$lang->testtask->linkCaseAB = "关联"; +$lang->testtask->unlinkCase = "移除"; +$lang->testtask->batchAssign = "批量指派"; +$lang->testtask->runCase = "执行"; +$lang->testtask->results = "结果"; +$lang->testtask->createBug = "创建Bug"; +$lang->testtask->assign = '指派'; +$lang->testtask->cases = '用例'; + +$lang->testtask->common = '测试任务'; +$lang->testtask->id = '任务编号'; +$lang->testtask->product = '所属产品'; +$lang->testtask->project = '所属项目'; +$lang->testtask->build = 'Build'; +$lang->testtask->owner = '负责人'; +$lang->testtask->name = '任务名称'; +$lang->testtask->begin = '开始日期'; +$lang->testtask->end = '结束日期'; +$lang->testtask->desc = '任务描述'; +$lang->testtask->status = '当前状态'; +$lang->testtask->assignedTo = '指派给'; +$lang->testtask->linkVersion = '关联(版本)'; +$lang->testtask->lastRunAccount = '最后执行人'; +$lang->testtask->lastRunTime = '最后执行时间'; +$lang->testtask->lastRunResult = '最终结果'; + +$lang->testtask->statusList['wait'] = '未开始'; +$lang->testtask->statusList['doing'] = '进行中'; +$lang->testtask->statusList['done'] = '已完成'; +$lang->testtask->statusList['blocked'] = '被阻塞'; + +$lang->testtask->unlinkedCases = '未关联用例列表'; +$lang->testtask->linkedCases = '已关联用例列表'; +$lang->testtask->linkByStory = '按需求关联用例'; +$lang->testtask->linkByBug = '按Bug关联用例'; +$lang->testtask->confirmDelete = '您确认要删除该测试任务吗?'; +$lang->testtask->passAll = '全部通过'; +$lang->testtask->pass = '通过'; +$lang->testtask->fail = '失败'; + +$lang->testtask->byModule = '按模块'; +$lang->testtask->assignedToMe = '指派给我'; +$lang->testtask->allCases = '所有Case'; + +$lang->testtask->lblCases = '用例列表'; +$lang->testtask->lblUnlinkCase = '移除用例'; +$lang->testtask->lblRunCase = '执行用例'; +$lang->testtask->lblResults = '执行结果'; diff --git a/module/testtask/lang/zh-tw.php b/module/testtask/lang/zh-tw.php index de222e9423..48f06f1083 100644 --- a/module/testtask/lang/zh-tw.php +++ b/module/testtask/lang/zh-tw.php @@ -1,66 +1,66 @@ - - * @package testtask - * @version $Id: zh-tw.php 2497 2011-12-30 02:48:03Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->testtask->index = "測試任務首頁"; -$lang->testtask->create = "創建測試任務"; -$lang->testtask->delete = "刪除測試任務"; -$lang->testtask->view = "測試任務詳情"; -$lang->testtask->edit = "編輯測試任務"; -$lang->testtask->browse = "測試任務列表"; -$lang->testtask->linkCase = "關聯用例"; -$lang->testtask->linkCaseAB = "關聯"; -$lang->testtask->unlinkCase = "移除"; -$lang->testtask->batchAssign = "批量指派"; -$lang->testtask->runCase = "執行"; -$lang->testtask->results = "結果"; -$lang->testtask->createBug = "創建Bug"; -$lang->testtask->assign = '指派'; -$lang->testtask->cases = '用例'; - -$lang->testtask->common = '測試任務'; -$lang->testtask->id = '任務編號'; -$lang->testtask->product = '所屬產品'; -$lang->testtask->project = '所屬項目'; -$lang->testtask->build = 'Build'; -$lang->testtask->owner = '負責人'; -$lang->testtask->name = '任務名稱'; -$lang->testtask->begin = '開始日期'; -$lang->testtask->end = '結束日期'; -$lang->testtask->desc = '任務描述'; -$lang->testtask->status = '當前狀態'; -$lang->testtask->assignedTo = '指派給'; -$lang->testtask->linkVersion = '關聯(版本)'; -$lang->testtask->lastRunAccount = '最後執行人'; -$lang->testtask->lastRunTime = '最後執行時間'; -$lang->testtask->lastRunResult = '最終結果'; - -$lang->testtask->statusList['wait'] = '未開始'; -$lang->testtask->statusList['doing'] = '進行中'; -$lang->testtask->statusList['done'] = '已完成'; -$lang->testtask->statusList['blocked'] = '被阻塞'; - -$lang->testtask->unlinkedCases = '未關聯用例列表'; -$lang->testtask->linkedCases = '已關聯用例列表'; -$lang->testtask->linkByStory = '按需求關聯用例'; -$lang->testtask->linkByBug = '按Bug關聯用例'; -$lang->testtask->confirmDelete = '您確認要刪除該測試任務嗎?'; -$lang->testtask->passAll = '全部通過'; -$lang->testtask->pass = '通過'; -$lang->testtask->fail = '失敗'; - -$lang->testtask->byModule = '按模組'; -$lang->testtask->assignedToMe = '指派給我'; -$lang->testtask->allCases = '所有Case'; - -$lang->testtask->lblCases = '用例列表'; -$lang->testtask->lblUnlinkCase = '移除用例'; -$lang->testtask->lblRunCase = '執行用例'; -$lang->testtask->lblResults = '執行結果'; + + * @package testtask + * @version $Id: zh-tw.php 2497 2011-12-30 02:48:03Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->testtask->index = "測試任務首頁"; +$lang->testtask->create = "創建測試任務"; +$lang->testtask->delete = "刪除測試任務"; +$lang->testtask->view = "測試任務詳情"; +$lang->testtask->edit = "編輯測試任務"; +$lang->testtask->browse = "測試任務列表"; +$lang->testtask->linkCase = "關聯用例"; +$lang->testtask->linkCaseAB = "關聯"; +$lang->testtask->unlinkCase = "移除"; +$lang->testtask->batchAssign = "批量指派"; +$lang->testtask->runCase = "執行"; +$lang->testtask->results = "結果"; +$lang->testtask->createBug = "創建Bug"; +$lang->testtask->assign = '指派'; +$lang->testtask->cases = '用例'; + +$lang->testtask->common = '測試任務'; +$lang->testtask->id = '任務編號'; +$lang->testtask->product = '所屬產品'; +$lang->testtask->project = '所屬項目'; +$lang->testtask->build = 'Build'; +$lang->testtask->owner = '負責人'; +$lang->testtask->name = '任務名稱'; +$lang->testtask->begin = '開始日期'; +$lang->testtask->end = '結束日期'; +$lang->testtask->desc = '任務描述'; +$lang->testtask->status = '當前狀態'; +$lang->testtask->assignedTo = '指派給'; +$lang->testtask->linkVersion = '關聯(版本)'; +$lang->testtask->lastRunAccount = '最後執行人'; +$lang->testtask->lastRunTime = '最後執行時間'; +$lang->testtask->lastRunResult = '最終結果'; + +$lang->testtask->statusList['wait'] = '未開始'; +$lang->testtask->statusList['doing'] = '進行中'; +$lang->testtask->statusList['done'] = '已完成'; +$lang->testtask->statusList['blocked'] = '被阻塞'; + +$lang->testtask->unlinkedCases = '未關聯用例列表'; +$lang->testtask->linkedCases = '已關聯用例列表'; +$lang->testtask->linkByStory = '按需求關聯用例'; +$lang->testtask->linkByBug = '按Bug關聯用例'; +$lang->testtask->confirmDelete = '您確認要刪除該測試任務嗎?'; +$lang->testtask->passAll = '全部通過'; +$lang->testtask->pass = '通過'; +$lang->testtask->fail = '失敗'; + +$lang->testtask->byModule = '按模組'; +$lang->testtask->assignedToMe = '指派給我'; +$lang->testtask->allCases = '所有Case'; + +$lang->testtask->lblCases = '用例列表'; +$lang->testtask->lblUnlinkCase = '移除用例'; +$lang->testtask->lblRunCase = '執行用例'; +$lang->testtask->lblResults = '執行結果'; diff --git a/module/testtask/model.php b/module/testtask/model.php index 81652a2d03..c052c6a173 100644 --- a/module/testtask/model.php +++ b/module/testtask/model.php @@ -1,345 +1,345 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> -loadModel('product')->setMenu($products, $productID); - $selectHtml = $this->product->select($products, $productID, 'testtask', 'browse'); - foreach($this->lang->testtask->menu as $key => $value) - { - $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow: $productID; - common::setMenuVars($this->lang->testtask->menu, $key, $replace); - } - } - - /** - * Create a test task. - * - * @param int $productID - * @access public - * @return void - */ - function create() - { - $task = fixer::input('post') - ->stripTags('name') - ->get(); - $this->dao->insert(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck($this->config->testtask->create->requiredFields, 'notempty')->exec(); - if(!dao::isError()) return $this->dao->lastInsertID(); - } - - /** - * Get test tasks of a product. - * - * @param int $productID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getProductTasks($productID, $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName') - ->from(TABLE_TESTTASK)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') - ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') - ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') - ->where('t1.product')->eq((int)$productID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * Get test tasks of a project. - * - * @param int $projectID - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getProjectTasks($projectID, $orderBy = 'id_desc', $pager = null) - { - return $this->dao->select('t1.*, t2.name AS buildName') - ->from(TABLE_TESTTASK)->alias('t1') - ->leftJoin(TABLE_BUILD)->alias('t2')->on('t1.build = t2.id') - ->where('t1.project')->eq((int)$projectID) - ->andWhere('t1.deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * Get test task info by id. - * - * @param int $taskID - * @access public - * @return void - */ - public function getById($taskID) - { - $task = $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName') - ->from(TABLE_TESTTASK)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') - ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') - ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') - ->where('t1.id')->eq((int)$taskID)->fetch(); - $task->desc = $this->loadModel('file')->setImgSize($task->desc); - return $task; - } - - /** - * Get test tasks by user. - * - * @param string $account - * @access public - * @return array - */ - public function getByUser($account) - { - return $this->dao->select('t1.*, t2.name AS projectName, t3.name AS buildName') - ->from(TABLE_TESTTASK)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build = t3.id') - ->where('t1.deleted')->eq(0) - ->andWhere('t1.owner')->eq($account) - ->orderBy('id desc') - ->fetchAll(); - } - - /** - * Update a test task. - * - * @param int $taskID - * @access public - * @return void - */ - public function update($taskID) - { - $oldTask = $this->getById($taskID); - $task = fixer::input('post')->stripTags('name')->get(); - $this->dao->update(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck($this->config->testtask->edit->requiredFields, 'notempty')->where('id')->eq($taskID)->exec(); - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * Link cases. - * - * @param int $taskID - * @access public - * @return void - */ - public function linkCase($taskID) - { - if($this->post->cases == false) return; - foreach($this->post->cases as $caseID) - { - $row->task = $taskID; - $row->case = $caseID; - $row->version = $this->post->versions[$caseID]; - $row->assignedTo = ''; - $row->status = 'wait'; - $this->dao->replace(TABLE_TESTRUN)->data($row)->exec(); - } - } - - /** - * Get test runs of a test task. - * - * @param int $taskID - * @param int $moduleID - * @access public - * @return array - */ - public function getRuns($taskID, $moduleID) - { - return $this->dao->select('t2.*,t1.*')->from(TABLE_TESTRUN)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') - ->where('t1.task')->eq((int)$taskID) - ->beginIF($moduleID)->andWhere('t2.module')->in($moduleID)->fi() - ->fetchAll(); - } - - /** - * Get test runs of a user. - * - * @param int $taskID - * @param int $user - * @access public - * @return array - */ - public function getUserRuns($taskID, $user) - { - return $this->dao->select('t2.*,t1.*')->from(TABLE_TESTRUN)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') - ->where('t1.task')->eq((int)$taskID) - ->andWhere('t1.assignedTo')->eq($user) - ->fetchAll(); - } - - /** - * Get info of a test run. - * - * @param int $runID - * @access public - * @return void - */ - public function getRunById($runID) - { - $testRun = $this->dao->findById($runID)->from(TABLE_TESTRUN)->fetch(); - $testRun->case = $this->loadModel('testcase')->getById($testRun->case, $testRun->version); - return $testRun; - } - - /** - * Create test result - * - * @param int $runID - * @access public - * @return void - */ - public function createResult($runID = 0) - { - /* Compute the test result. - * - * 1. if there result in the post, use it. - * 2. if no result, set default is pass. - * 3. then check the steps to compute result. - * - * */ - $caseResult = $this->post->result ? $this->post->result : 'pass'; - if(isset($_POST['passall']) and $this->post->passall == false) - { - if($this->post->steps) - { - foreach($this->post->steps as $stepID => $stepResult) - { - if($stepResult != 'pass' and $stepResult != 'n/a') - { - $caseResult = $stepResult; - break; - } - } - } - } - - /* Create result of every step. */ - if($this->post->steps) - { - foreach($this->post->steps as $stepID =>$stepResult) - { - $step['result'] = $stepResult; - $step['real'] = $this->post->reals[$stepID]; - $stepResults[$stepID] = $step; - } - } - else - { - $stepResults = array(); - } - - /* Insert into testResult table. */ - $now = helper::now(); - $result = fixer::input('post') - ->add('run', $runID) - ->add('caseResult', $caseResult) - ->setForce('stepResults', serialize($stepResults)) - ->add('lastRunner', $this->app->user->account) - ->add('date', $now) - ->remove('steps,reals,passall,result') - ->get(); - $this->dao->insert(TABLE_TESTRESULT)->data($result)->autoCheck()->exec(); - $this->dao->update(TABLE_CASE)->set('lastRunner')->eq($this->app->user->account)->set('lastRunDate')->eq($now)->set('lastRunResult')->eq($caseResult)->where('id')->eq($this->post->case)->exec(); - - if($runID) - { - /* Update testRun's status. */ - if(!dao::isError()) - { - $runStatus = $caseResult == 'blocked' ? 'blocked' : 'done'; - $this->dao->update(TABLE_TESTRUN) - ->set('lastRunResult')->eq($caseResult) - ->set('status')->eq($runStatus) - ->set('lastRunner')->eq($this->app->user->account) - ->set('lastRunDate')->eq($now) - ->where('id')->eq($runID) - ->exec(); - } - } - } - - /** - * Get results by runID or caseID - * - * @param int $runID - * @param int $caseID - * @access public - * @return array - */ - public function getResults($runID, $caseID = 0) - { - if($caseID > 0) - { - $results = $this->dao->select('*')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('id desc')->fetchAll('id'); - } - else - { - $results = $this->dao->select('*')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->fetchAll('id'); - } - - if(!$results) return array(); - - $relatedVersions = array(); - foreach($results as $result) - { - $relatedVersions[] = $result->version; - $runCaseID = $result->case; - } - $relatedVersions = array_unique($relatedVersions); - - $relatedSteps = $this->dao->select('*')->from(TABLE_CASESTEP) - ->beginIF($caseID)->where('`case`')->eq($caseID)->fi() - ->beginIF($runID)->where('`case`')->eq($runCaseID)->fi() - ->andWhere('version')->in($relatedVersions) - ->fetchAll(); - - foreach($results as $resultID => $result) - { - $result->stepResults = unserialize($result->stepResults); - $results[$resultID] = $result; - - foreach($relatedSteps as $key => $step) - { - if($result->version == $step->version) - { - $result->stepResults[$step->id]['desc'] = $step->desc; - $result->stepResults[$step->id]['expect'] = $step->expect; - } - } - } - return $results; - } -} + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('product')->setMenu($products, $productID); + $selectHtml = $this->product->select($products, $productID, 'testtask', 'browse'); + foreach($this->lang->testtask->menu as $key => $value) + { + $replace = ($key == 'product') ? $selectHtml . $this->lang->arrow: $productID; + common::setMenuVars($this->lang->testtask->menu, $key, $replace); + } + } + + /** + * Create a test task. + * + * @param int $productID + * @access public + * @return void + */ + function create() + { + $task = fixer::input('post') + ->stripTags('name') + ->get(); + $this->dao->insert(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck($this->config->testtask->create->requiredFields, 'notempty')->exec(); + if(!dao::isError()) return $this->dao->lastInsertID(); + } + + /** + * Get test tasks of a product. + * + * @param int $productID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getProductTasks($productID, $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName') + ->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') + ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') + ->where('t1.product')->eq((int)$productID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * Get test tasks of a project. + * + * @param int $projectID + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getProjectTasks($projectID, $orderBy = 'id_desc', $pager = null) + { + return $this->dao->select('t1.*, t2.name AS buildName') + ->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_BUILD)->alias('t2')->on('t1.build = t2.id') + ->where('t1.project')->eq((int)$projectID) + ->andWhere('t1.deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * Get test task info by id. + * + * @param int $taskID + * @access public + * @return void + */ + public function getById($taskID) + { + $task = $this->dao->select('t1.*, t2.name AS productName, t3.name AS projectName, t4.name AS buildName') + ->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') + ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t1.project = t3.id') + ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') + ->where('t1.id')->eq((int)$taskID)->fetch(); + $task->desc = $this->loadModel('file')->setImgSize($task->desc); + return $task; + } + + /** + * Get test tasks by user. + * + * @param string $account + * @access public + * @return array + */ + public function getByUser($account) + { + return $this->dao->select('t1.*, t2.name AS projectName, t3.name AS buildName') + ->from(TABLE_TESTTASK)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build = t3.id') + ->where('t1.deleted')->eq(0) + ->andWhere('t1.owner')->eq($account) + ->orderBy('id desc') + ->fetchAll(); + } + + /** + * Update a test task. + * + * @param int $taskID + * @access public + * @return void + */ + public function update($taskID) + { + $oldTask = $this->getById($taskID); + $task = fixer::input('post')->stripTags('name')->get(); + $this->dao->update(TABLE_TESTTASK)->data($task)->autoCheck()->batchcheck($this->config->testtask->edit->requiredFields, 'notempty')->where('id')->eq($taskID)->exec(); + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * Link cases. + * + * @param int $taskID + * @access public + * @return void + */ + public function linkCase($taskID) + { + if($this->post->cases == false) return; + foreach($this->post->cases as $caseID) + { + $row->task = $taskID; + $row->case = $caseID; + $row->version = $this->post->versions[$caseID]; + $row->assignedTo = ''; + $row->status = 'wait'; + $this->dao->replace(TABLE_TESTRUN)->data($row)->exec(); + } + } + + /** + * Get test runs of a test task. + * + * @param int $taskID + * @param int $moduleID + * @access public + * @return array + */ + public function getRuns($taskID, $moduleID) + { + return $this->dao->select('t2.*,t1.*')->from(TABLE_TESTRUN)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->where('t1.task')->eq((int)$taskID) + ->beginIF($moduleID)->andWhere('t2.module')->in($moduleID)->fi() + ->fetchAll(); + } + + /** + * Get test runs of a user. + * + * @param int $taskID + * @param int $user + * @access public + * @return array + */ + public function getUserRuns($taskID, $user) + { + return $this->dao->select('t2.*,t1.*')->from(TABLE_TESTRUN)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->where('t1.task')->eq((int)$taskID) + ->andWhere('t1.assignedTo')->eq($user) + ->fetchAll(); + } + + /** + * Get info of a test run. + * + * @param int $runID + * @access public + * @return void + */ + public function getRunById($runID) + { + $testRun = $this->dao->findById($runID)->from(TABLE_TESTRUN)->fetch(); + $testRun->case = $this->loadModel('testcase')->getById($testRun->case, $testRun->version); + return $testRun; + } + + /** + * Create test result + * + * @param int $runID + * @access public + * @return void + */ + public function createResult($runID = 0) + { + /* Compute the test result. + * + * 1. if there result in the post, use it. + * 2. if no result, set default is pass. + * 3. then check the steps to compute result. + * + * */ + $caseResult = $this->post->result ? $this->post->result : 'pass'; + if(isset($_POST['passall']) and $this->post->passall == false) + { + if($this->post->steps) + { + foreach($this->post->steps as $stepID => $stepResult) + { + if($stepResult != 'pass' and $stepResult != 'n/a') + { + $caseResult = $stepResult; + break; + } + } + } + } + + /* Create result of every step. */ + if($this->post->steps) + { + foreach($this->post->steps as $stepID =>$stepResult) + { + $step['result'] = $stepResult; + $step['real'] = $this->post->reals[$stepID]; + $stepResults[$stepID] = $step; + } + } + else + { + $stepResults = array(); + } + + /* Insert into testResult table. */ + $now = helper::now(); + $result = fixer::input('post') + ->add('run', $runID) + ->add('caseResult', $caseResult) + ->setForce('stepResults', serialize($stepResults)) + ->add('lastRunner', $this->app->user->account) + ->add('date', $now) + ->remove('steps,reals,passall,result') + ->get(); + $this->dao->insert(TABLE_TESTRESULT)->data($result)->autoCheck()->exec(); + $this->dao->update(TABLE_CASE)->set('lastRunner')->eq($this->app->user->account)->set('lastRunDate')->eq($now)->set('lastRunResult')->eq($caseResult)->where('id')->eq($this->post->case)->exec(); + + if($runID) + { + /* Update testRun's status. */ + if(!dao::isError()) + { + $runStatus = $caseResult == 'blocked' ? 'blocked' : 'done'; + $this->dao->update(TABLE_TESTRUN) + ->set('lastRunResult')->eq($caseResult) + ->set('status')->eq($runStatus) + ->set('lastRunner')->eq($this->app->user->account) + ->set('lastRunDate')->eq($now) + ->where('id')->eq($runID) + ->exec(); + } + } + } + + /** + * Get results by runID or caseID + * + * @param int $runID + * @param int $caseID + * @access public + * @return array + */ + public function getResults($runID, $caseID = 0) + { + if($caseID > 0) + { + $results = $this->dao->select('*')->from(TABLE_TESTRESULT)->where('`case`')->eq($caseID)->orderBy('id desc')->fetchAll('id'); + } + else + { + $results = $this->dao->select('*')->from(TABLE_TESTRESULT)->where('run')->eq($runID)->orderBy('id desc')->fetchAll('id'); + } + + if(!$results) return array(); + + $relatedVersions = array(); + foreach($results as $result) + { + $relatedVersions[] = $result->version; + $runCaseID = $result->case; + } + $relatedVersions = array_unique($relatedVersions); + + $relatedSteps = $this->dao->select('*')->from(TABLE_CASESTEP) + ->beginIF($caseID)->where('`case`')->eq($caseID)->fi() + ->beginIF($runID)->where('`case`')->eq($runCaseID)->fi() + ->andWhere('version')->in($relatedVersions) + ->fetchAll(); + + foreach($results as $resultID => $result) + { + $result->stepResults = unserialize($result->stepResults); + $results[$resultID] = $result; + + foreach($relatedSteps as $key => $step) + { + if($result->version == $step->version) + { + $result->stepResults[$step->id]['desc'] = $step->desc; + $result->stepResults[$step->id]['expect'] = $step->expect; + } + } + } + return $results; + } +} diff --git a/module/testtask/view/browse.html.php b/module/testtask/view/browse.html.php index 90f3f3de24..a383b9e5d8 100644 --- a/module/testtask/view/browse.html.php +++ b/module/testtask/view/browse.html.php @@ -1,56 +1,56 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          testtask->browse;?>
          -
          testtask->create);?>
          -
          idAB;?>testtask->name;?>testtask->project;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          id"), sprintf('%03d', $task->id));?>id"), $task->name);?>projectName?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>owner];?>begin?>end?>testtask->statusList[$task->status];?> - id", $lang->testtask->cases); - common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); - common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); - common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); - ?> -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          testtask->browse;?>
          +
          testtask->create);?>
          +
          idAB;?>testtask->name;?>testtask->project;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          id"), sprintf('%03d', $task->id));?>id"), $task->name);?>projectName?>build == 'trunk' ? print('Trunk') : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>owner];?>begin?>end?>testtask->statusList[$task->status];?> + id", $lang->testtask->cases); + common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); + common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); + common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); + ?> +
          + diff --git a/module/testtask/view/cases.html.php b/module/testtask/view/cases.html.php index d38e59bf39..adab7c5a9b 100644 --- a/module/testtask/view/cases.html.php +++ b/module/testtask/view/cases.html.php @@ -1,101 +1,101 @@ - - * @package case - * @version $Id: view.html.php 594 2010-03-27 13:44:07Z wwccss $ - * @link http://www.zentao.net - */ -?> - - - - - -
          -
          - " . $lang->testtask->byModule . " "; - echo "" . html::a($this->inlink('cases', "taskID=$taskID&browseType=all¶m=0"), $lang->testtask->allCases) . ""; - echo "" . html::a($this->inlink('cases', "taskID=$taskID&browseType=assignedtome¶m=0"), $lang->testtask->assignedToMe) . ""; - ?> -
          -
          - id", $lang->testtask->linkCase); - echo html::a($this->session->testtaskList, $lang->goback); - ?> -
          -
          - - - - - - - -
          -
          -
          -
          -
          id");?>' target='hiddenwin'> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB;?>priAB;?>testcase->title;?>testcase->type;?>testtask->assignedTo;?>testtask->lastRunAccount;?>testtask->lastRunTime;?>testtask->lastRunResult;?>statusAB;?>actions;?>
          case' /> "; printf('%03d', $run->case);?>pri?>createLink('testcase', 'view', "caseID=$run->case&version=$run->version"), $run->title, '_blank');?> - testcase->typeList[$run->type];?>assignedTo]; echo substr($assignedTo, strpos($assignedTo, ':') + 1);?>lastRunner]; echo substr($lastRunner, strpos($lastRunner, ':') + 1);?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($run->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$run->lastRunResult];?>testtask->statusList[$run->status];?> - id", $lang->testtask->runCase, '', 'class="iframe"'); - common::printLink('testtask', 'results', "id=$run->id", $lang->testtask->results, '', 'class="iframe"'); - common::printLink('testtask', 'unlinkcase', "id=$run->id", $lang->testtask->unlinkCase, 'hiddenwin'); - if($run->lastRunResult == 'fail') common::printLink('bug', 'create', "product=$productID&extra=projectID=$task->project,buildID=$task->build,caseID=$run->case,runID=$run->id", $lang->testtask->createBug); - ?> -
          - - - - - -
          " . $lang->selectAll;?> - testtask->assign); - ?> -
          -
          -
          - + + * @package case + * @version $Id: view.html.php 594 2010-03-27 13:44:07Z wwccss $ + * @link http://www.zentao.net + */ +?> + + + + + +
          +
          + " . $lang->testtask->byModule . " "; + echo "" . html::a($this->inlink('cases', "taskID=$taskID&browseType=all¶m=0"), $lang->testtask->allCases) . ""; + echo "" . html::a($this->inlink('cases', "taskID=$taskID&browseType=assignedtome¶m=0"), $lang->testtask->assignedToMe) . ""; + ?> +
          +
          + id", $lang->testtask->linkCase); + echo html::a($this->session->testtaskList, $lang->goback); + ?> +
          +
          + + + + + + + +
          +
          +
          +
          +
          id");?>' target='hiddenwin'> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB;?>priAB;?>testcase->title;?>testcase->type;?>testtask->assignedTo;?>testtask->lastRunAccount;?>testtask->lastRunTime;?>testtask->lastRunResult;?>statusAB;?>actions;?>
          case' /> "; printf('%03d', $run->case);?>pri?>createLink('testcase', 'view', "caseID=$run->case&version=$run->version"), $run->title, '_blank');?> + testcase->typeList[$run->type];?>assignedTo]; echo substr($assignedTo, strpos($assignedTo, ':') + 1);?>lastRunner]; echo substr($lastRunner, strpos($lastRunner, ':') + 1);?>lastRunDate)) echo date(DT_MONTHTIME1, strtotime($run->lastRunDate));?>lastRunResult) echo $lang->testcase->resultList[$run->lastRunResult];?>testtask->statusList[$run->status];?> + id", $lang->testtask->runCase, '', 'class="iframe"'); + common::printLink('testtask', 'results', "id=$run->id", $lang->testtask->results, '', 'class="iframe"'); + common::printLink('testtask', 'unlinkcase', "id=$run->id", $lang->testtask->unlinkCase, 'hiddenwin'); + if($run->lastRunResult == 'fail') common::printLink('bug', 'create', "product=$productID&extra=projectID=$task->project,buildID=$task->build,caseID=$run->case,runID=$run->id", $lang->testtask->createBug); + ?> +
          + + + + + +
          " . $lang->selectAll;?> + testtask->assign); + ?> +
          +
          +
          + diff --git a/module/testtask/view/create.html.php b/module/testtask/view/create.html.php index 68a84befd0..2b9379976b 100644 --- a/module/testtask/view/create.html.php +++ b/module/testtask/view/create.html.php @@ -1,67 +1,67 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testtask->create;?>
          testtask->product;?>
          testtask->project;?>
          testtask->build;?>
          testtask->owner;?>
          testtask->begin;?> -
          testtask->end;?> -
          testtask->status;?>testtask->statusList, '', "class='select-3'");?> -
          testtask->name;?> -
          testtask->desc;?> -
          -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testtask->create;?>
          testtask->product;?>
          testtask->project;?>
          testtask->build;?>
          testtask->owner;?>
          testtask->begin;?> +
          testtask->end;?> +
          testtask->status;?>testtask->statusList, '', "class='select-3'");?> +
          testtask->name;?> +
          testtask->desc;?> +
          +
          + diff --git a/module/testtask/view/edit.html.php b/module/testtask/view/edit.html.php index 1b2485fde5..758919d3c6 100644 --- a/module/testtask/view/edit.html.php +++ b/module/testtask/view/edit.html.php @@ -1,56 +1,56 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testtask->edit;?>
          testtask->project;?>project, 'class=select-3');?>
          testtask->build;?>build, 'class=select-3');?>
          testtask->owner;?>owner, 'class=select-3');?>
          testtask->begin;?>begin, "class='text-3 date'");?> -
          testtask->end;?>end, "class='text-3 date'");?> -
          testtask->status;?>testtask->statusList, $task->status, "class='select-3'");?> -
          testtask->name;?>name, "class='text-1'");?> -
          testtask->desc;?>desc), "rows=10 class='area-1'");?> -
          -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testtask->edit;?>
          testtask->project;?>project, 'class=select-3');?>
          testtask->build;?>build, 'class=select-3');?>
          testtask->owner;?>owner, 'class=select-3');?>
          testtask->begin;?>begin, "class='text-3 date'");?> +
          testtask->end;?>end, "class='text-3 date'");?> +
          testtask->status;?>testtask->statusList, $task->status, "class='select-3'");?> +
          testtask->name;?>name, "class='text-1'");?> +
          testtask->desc;?>desc), "rows=10 class='area-1'");?> +
          +
          + diff --git a/module/testtask/view/linkcase.html.php b/module/testtask/view/linkcase.html.php index 0d54350571..765f6d8dbd 100644 --- a/module/testtask/view/linkcase.html.php +++ b/module/testtask/view/linkcase.html.php @@ -1,68 +1,68 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          testtask->unlinkedCases;?>
          -
          session->testtaskList, $lang->goback);?>
          -
          createLink('testtask', 'linkcase', "taskID=$taskID¶m=bybug"), $lang->testtask->linkByBug);?>
          -
          createLink('testtask', 'linkcase', "taskID=$taskID¶m=bystory"), $lang->testtask->linkByStory);?>
          -
          idAB;?>priAB;?>testcase->title;?>testcase->type;?>openedByAB;?>statusAB;?>testtask->linkVersion;?>
          createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?> - title . ' ( '; - for($i = $case->version; $i >= 1; $i --) - { - echo html::a($this->createLink('testcase', 'view', "caseID=$case->id&version=$i"), "#$i", '_blank'); - } - echo ')'; - ?> - testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> - - id]", array_combine(range($case->version, 1), range($case->version, 1)), '', 'style=width:50px');?> -
          show();?>
          selectAll; echo html::submitButton();?>
          -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          testtask->unlinkedCases;?>
          +
          session->testtaskList, $lang->goback);?>
          +
          createLink('testtask', 'linkcase', "taskID=$taskID¶m=bybug"), $lang->testtask->linkByBug);?>
          +
          createLink('testtask', 'linkcase', "taskID=$taskID¶m=bystory"), $lang->testtask->linkByStory);?>
          +
          idAB;?>priAB;?>testcase->title;?>testcase->type;?>openedByAB;?>statusAB;?>testtask->linkVersion;?>
          createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?>pri?> + title . ' ( '; + for($i = $case->version; $i >= 1; $i --) + { + echo html::a($this->createLink('testcase', 'view', "caseID=$case->id&version=$i"), "#$i", '_blank'); + } + echo ')'; + ?> + testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?> + + id]", array_combine(range($case->version, 1), range($case->version, 1)), '', 'style=width:50px');?> +
          show();?>
          selectAll; echo html::submitButton();?>
          +
          + diff --git a/module/testtask/view/results.html.php b/module/testtask/view/results.html.php index ccd9090675..a6f9c8693f 100644 --- a/module/testtask/view/results.html.php +++ b/module/testtask/view/results.html.php @@ -1,49 +1,49 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -

          CASE#id. $lang->colon . $case->title;?>

          -
          - testcase->precondition;?> - precondition;?> -
          - - - - - - - - - - - stepResults as $key => $stepResult): - ?> - - - - - stepResults)):?> - - - - - - - - - -
          RESULT#id . ' ' . $result->date . ' ' . $users[$result->lastRunner] . ' ' . $lang->testtask->runCase . ':'. " " . $lang->testcase->resultList[$result->caseResult] . '';?>
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>testcase->result;?>testcase->real;?>
          a-center'>testcase->resultList[$stepResult['result']];?>
          - - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +

          CASE#id. $lang->colon . $case->title;?>

          +
          + testcase->precondition;?> + precondition;?> +
          + + + + + + + + + + + stepResults as $key => $stepResult): + ?> + + + + + stepResults)):?> + + + + + + + + + +
          RESULT#id . ' ' . $result->date . ' ' . $users[$result->lastRunner] . ' ' . $lang->testtask->runCase . ':'. " " . $lang->testcase->resultList[$result->caseResult] . '';?>
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>testcase->result;?>testcase->real;?>
          a-center'>testcase->resultList[$stepResult['result']];?>
          + + diff --git a/module/testtask/view/runcase.html.php b/module/testtask/view/runcase.html.php index fd8e2bacef..c1840add67 100644 --- a/module/testtask/view/runcase.html.php +++ b/module/testtask/view/runcase.html.php @@ -1,59 +1,59 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - case->steps as $key => $step):?> - expect ? 'pass' : 'n/a';?> - - - - - - - - - - - -
          CASE#case->id. $lang->colon . $run->case->title;?>
          testcase->precondition;?>
          case->precondition;?>
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>testcase->result;?>testcase->real;?>
          desc);?>expect);?>id]", $lang->testcase->resultList, $defaultResult);?>id]", '', "rows=3 class='area-1'");?>
          - case->steps)) - { - echo html::submitButton($lang->testtask->pass, "onclick=$('#result').val('pass')"); - echo html::submitButton($lang->testtask->fail, "onclick=$('#result').val('fail')"); - } - else - { - echo html::submitButton(); - echo html::submitButton($lang->testtask->passAll, "onclick=$('#passall').val(1)"); - } - echo html::hidden('case', $run->case->id); - echo html::hidden('version', $run->case->version); - if($run->case->steps) echo html::hidden('passall', 0); - if(!$run->case->steps) echo html::hidden('result', ''); - ?> -
          -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + case->steps as $key => $step):?> + expect ? 'pass' : 'n/a';?> + + + + + + + + + + + +
          CASE#case->id. $lang->colon . $run->case->title;?>
          testcase->precondition;?>
          case->precondition;?>
          testcase->stepID;?>testcase->stepDesc;?>testcase->stepExpect;?>testcase->result;?>testcase->real;?>
          desc);?>expect);?>id]", $lang->testcase->resultList, $defaultResult);?>id]", '', "rows=3 class='area-1'");?>
          + case->steps)) + { + echo html::submitButton($lang->testtask->pass, "onclick=$('#result').val('pass')"); + echo html::submitButton($lang->testtask->fail, "onclick=$('#result').val('fail')"); + } + else + { + echo html::submitButton(); + echo html::submitButton($lang->testtask->passAll, "onclick=$('#passall').val(1)"); + } + echo html::hidden('case', $run->case->id); + echo html::hidden('version', $run->case->version); + if($run->case->steps) echo html::hidden('passall', 0); + if(!$run->case->steps) echo html::hidden('result', ''); + ?> +
          +
          + diff --git a/module/testtask/view/view.html.php b/module/testtask/view/view.html.php index 89dfcf587a..223196e099 100644 --- a/module/testtask/view/view.html.php +++ b/module/testtask/view/view.html.php @@ -1,64 +1,64 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testtask->view;?>
          testtask->name;?>'>name;?> -
          testtask->project;?>projectName;?>
          testtask->build;?>buildName ? print($task->buildName) : print($task->build);?>
          testtask->owner;?>owner];?>
          testtask->begin;?>begin;?>
          testtask->end;?>end;?>
          testtask->status;?>testtask->statusList[$task->status];?>
          testtask->desc;?>desc;?>
          -
          - session->testtaskList ? $this->session->testtaskList : $this->createLink('testtask', 'browse', "productID=$task->product"); - if(!$task->deleted) - { - common::printLink('testtask', 'cases', "taskID=$task->id", $lang->testtask->cases); - common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); - common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); - common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - - + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testtask->view;?>
          testtask->name;?>'>name;?> +
          testtask->project;?>projectName;?>
          testtask->build;?>buildName ? print($task->buildName) : print($task->build);?>
          testtask->owner;?>owner];?>
          testtask->begin;?>begin;?>
          testtask->end;?>end;?>
          testtask->status;?>testtask->statusList[$task->status];?>
          testtask->desc;?>desc;?>
          +
          + session->testtaskList ? $this->session->testtaskList : $this->createLink('testtask', 'browse', "productID=$task->product"); + if(!$task->deleted) + { + common::printLink('testtask', 'cases', "taskID=$task->id", $lang->testtask->cases); + common::printLink('testtask', 'linkcase', "taskID=$task->id", $lang->testtask->linkCaseAB); + common::printLink('testtask', 'edit', "taskID=$task->id", $lang->edit); + common::printLink('testtask', 'delete', "taskID=$task->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + + diff --git a/module/todo/control.php b/module/todo/control.php index b0978b8977..a3d175f076 100644 --- a/module/todo/control.php +++ b/module/todo/control.php @@ -1,252 +1,252 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -class todo extends control -{ - /** - * Construct function, load model of task, bug, my. - * - * @access public - * @return voidzentaoms\www - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('task'); - $this->loadModel('bug'); - $this->loadModel('my')->setMenu(); - } - - /** - * Create a todo. - * - * @param string|date $date - * @param string $account - * @access public - * @return void - */ - public function create($date = 'today', $account = '') - { - if($date == 'today') $date = $this->todo->today(); - if($account == '') $account = $this->app->user->account; - if(!empty($_POST)) - { - $todoID = $this->todo->create($date, $account); - if(dao::isError()) die(js::error(dao::getError())); - $this->loadModel('action')->create('todo', $todoID, 'opened'); - die(js::locate($this->createLink('my', 'todo', "date=$_POST[date]"), 'parent')); - } - - $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->create; - $position[] = $this->lang->todo->create; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->dates = $this->todo->buildDateList(0, $this->config->todo->dates->end); - $this->view->date = $date; - $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->time = $this->todo->now(); - $this->display(); - } - - /** - * Edit a todo. - * - * @param int $todoID - * @access public - * @return void - */ - public function edit($todoID) - { - if(!empty($_POST)) - { - $changes = $this->todo->update($todoID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('todo', $todoID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate(inlink('view', "todoID=$todoID"), 'parent')); - } - - /* Judge a private todo or not, If private, die. */ - $todo = $this->todo->getById($todoID); - if($todo->private and $this->app->user->account != $todo->account) die('private'); - - $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->edit; - $position[] = $this->lang->todo->edit; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->dates = $this->todo->buildDateList(); - $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->todo = $todo; - $this->display(); - } - - /** - * View a todo. - * - * @param int $todoID - * @param string $from my|company - * @access public - * @return void - */ - public function view($todoID, $from = 'company') - { - $todo = $this->todo->getById($todoID); - if(!$todo) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Save the session. */ - $this->session->set('taskList', $this->app->getURI(true)); - $this->session->set('bugList', $this->app->getURI(true)); - - /* Set menus. */ - $this->lang->todo->menu = $this->lang->user->menu; - $this->loadModel('user')->setMenu($this->user->getPairs(), $todo->account); - $this->lang->set('menugroup.todo', $from); - - $this->view->header->title = $this->lang->todo->view; - $this->view->position[] = $this->lang->todo->view; - $this->view->todo = $todo; - $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->actions = $this->loadModel('action')->getList('todo', $todoID); - $this->view->from = $from; - - $this->display(); - } - - /** - * Delete a todo. - * - * @param int $todoID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($todoID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID=$todoID&confirm=yes")); - exit; - } - else - { - $this->dao->delete()->from(TABLE_TODO)->where('id')->eq($todoID)->exec(); - $this->loadModel('action')->create('todo', $todoID, 'erased'); - die(js::locate($this->session->todoList, 'parent')); - } - } - - /** - * Mark status of a todo. - * - * @param int $todoID - * @param string $status wait|doing|done - * @access public - * @return void - */ - public function mark($todoID, $status) - { - $this->todo->mark($todoID, $status); - $todo = $this->todo->getById($todoID); - if($todo->status == 'done') - { - if($todo->type == 'bug' or $todo->type == 'task') - { - $confirmNote = 'confirm' . ucfirst($todo->type); - $confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue"); - $cancelURL = $this->server->HTTP_REFERER; - die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent')); - } - } - die(js::reload('parent')); - } - - /** - * Import selected todoes to today. - * - * @access public - * @return void - */ - public function import2Today() - { - $todos = $this->post->todos; - $today = $this->todo->today(); - $this->dao->update(TABLE_TODO)->set('date')->eq($today)->where('id')->in($todos)->exec(); - die(js::reload('parent')); - } - - /** - * Get data to export - * - * @param string $productID - * @param string $orderBy - * @access public - * @return void - */ - public function export($account, $orderBy) - { - if($_POST) - { - $todoLang = $this->lang->todo; - $todoConfig = $this->config->todo; - - /* Create field lists. */ - $fields = explode(',', $todoConfig->list->exportFields); - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($todoLang->$fieldName) ? $todoLang->$fieldName : $fieldName; - unset($fields[$key]); - } - unset($fields['idvalue']); - unset($fields['private']); - - /* Get bugs. */ - $todos = $this->dao->select('*')->from(TABLE_TODO)->where($this->session->todoReportCondition)->orderBy($orderBy)->fetchAll('id'); - - /* Get users, bugs, tasks and times. */ - $users = $this->loadModel('user')->getPairs('noletter'); - $bugs = $this->loadModel('bug')->getUserBugPairs($account); - $tasks = $this->loadModel('task')->getUserTaskPairs($account); - $times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - - foreach($todos as $todo) - { - /* fill some field with useful value. */ - if(isset($users[$todo->account])) $todo->account = $users[$todo->account]; - if(isset($times[$todo->begin])) $todo->begin = $times[$todo->begin]; - if(isset($times[$todo->end])) $todo->end = $times[$todo->end]; - if($todo->type == 'bug') $todo->name = isset($bugs[$todo->idvalue]) ? $bugs[$todo->idvalue] : ''; - if($todo->type == 'task') $todo->name = isset($tasks[$todo->idvalue]) ? $tasks[$todo->idvalue] : ''; - if(isset($todoLang->typeList->{$todo->type})) $todo->type = $todoLang->typeList->{$todo->type}; - if(isset($todoLang->priList[$todo->pri])) $todo->pri = $todoLang->priList[$todo->pri]; - if(isset($todoLang->statusList[$todo->status])) $todo->status = $todoLang->statusList[$todo->status]; - if($todo->private == 1) $todo->desc = $this->lang->todo->thisIsPrivate; - - /* drop some field that is not needed. */ - unset($todo->company); - unset($todo->idvalue); - unset($todo->private); - } - - $this->post->set('fields', $fields); - $this->post->set('rows', $todos); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +class todo extends control +{ + /** + * Construct function, load model of task, bug, my. + * + * @access public + * @return voidzentaoms\www + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('task'); + $this->loadModel('bug'); + $this->loadModel('my')->setMenu(); + } + + /** + * Create a todo. + * + * @param string|date $date + * @param string $account + * @access public + * @return void + */ + public function create($date = 'today', $account = '') + { + if($date == 'today') $date = $this->todo->today(); + if($account == '') $account = $this->app->user->account; + if(!empty($_POST)) + { + $todoID = $this->todo->create($date, $account); + if(dao::isError()) die(js::error(dao::getError())); + $this->loadModel('action')->create('todo', $todoID, 'opened'); + die(js::locate($this->createLink('my', 'todo', "date=$_POST[date]"), 'parent')); + } + + $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->create; + $position[] = $this->lang->todo->create; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->dates = $this->todo->buildDateList(0, $this->config->todo->dates->end); + $this->view->date = $date; + $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->time = $this->todo->now(); + $this->display(); + } + + /** + * Edit a todo. + * + * @param int $todoID + * @access public + * @return void + */ + public function edit($todoID) + { + if(!empty($_POST)) + { + $changes = $this->todo->update($todoID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('todo', $todoID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate(inlink('view', "todoID=$todoID"), 'parent')); + } + + /* Judge a private todo or not, If private, die. */ + $todo = $this->todo->getById($todoID); + if($todo->private and $this->app->user->account != $todo->account) die('private'); + + $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->edit; + $position[] = $this->lang->todo->edit; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->dates = $this->todo->buildDateList(); + $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->todo = $todo; + $this->display(); + } + + /** + * View a todo. + * + * @param int $todoID + * @param string $from my|company + * @access public + * @return void + */ + public function view($todoID, $from = 'company') + { + $todo = $this->todo->getById($todoID); + if(!$todo) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Save the session. */ + $this->session->set('taskList', $this->app->getURI(true)); + $this->session->set('bugList', $this->app->getURI(true)); + + /* Set menus. */ + $this->lang->todo->menu = $this->lang->user->menu; + $this->loadModel('user')->setMenu($this->user->getPairs(), $todo->account); + $this->lang->set('menugroup.todo', $from); + + $this->view->header->title = $this->lang->todo->view; + $this->view->position[] = $this->lang->todo->view; + $this->view->todo = $todo; + $this->view->times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->actions = $this->loadModel('action')->getList('todo', $todoID); + $this->view->from = $from; + + $this->display(); + } + + /** + * Delete a todo. + * + * @param int $todoID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($todoID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->todo->confirmDelete, $this->createLink('todo', 'delete', "todoID=$todoID&confirm=yes")); + exit; + } + else + { + $this->dao->delete()->from(TABLE_TODO)->where('id')->eq($todoID)->exec(); + $this->loadModel('action')->create('todo', $todoID, 'erased'); + die(js::locate($this->session->todoList, 'parent')); + } + } + + /** + * Mark status of a todo. + * + * @param int $todoID + * @param string $status wait|doing|done + * @access public + * @return void + */ + public function mark($todoID, $status) + { + $this->todo->mark($todoID, $status); + $todo = $this->todo->getById($todoID); + if($todo->status == 'done') + { + if($todo->type == 'bug' or $todo->type == 'task') + { + $confirmNote = 'confirm' . ucfirst($todo->type); + $confirmURL = $this->createLink($todo->type, 'view', "id=$todo->idvalue"); + $cancelURL = $this->server->HTTP_REFERER; + die(js::confirm(sprintf($this->lang->todo->$confirmNote, $todo->idvalue), $confirmURL, $cancelURL, 'parent', 'parent')); + } + } + die(js::reload('parent')); + } + + /** + * Import selected todoes to today. + * + * @access public + * @return void + */ + public function import2Today() + { + $todos = $this->post->todos; + $today = $this->todo->today(); + $this->dao->update(TABLE_TODO)->set('date')->eq($today)->where('id')->in($todos)->exec(); + die(js::reload('parent')); + } + + /** + * Get data to export + * + * @param string $productID + * @param string $orderBy + * @access public + * @return void + */ + public function export($account, $orderBy) + { + if($_POST) + { + $todoLang = $this->lang->todo; + $todoConfig = $this->config->todo; + + /* Create field lists. */ + $fields = explode(',', $todoConfig->list->exportFields); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($todoLang->$fieldName) ? $todoLang->$fieldName : $fieldName; + unset($fields[$key]); + } + unset($fields['idvalue']); + unset($fields['private']); + + /* Get bugs. */ + $todos = $this->dao->select('*')->from(TABLE_TODO)->where($this->session->todoReportCondition)->orderBy($orderBy)->fetchAll('id'); + + /* Get users, bugs, tasks and times. */ + $users = $this->loadModel('user')->getPairs('noletter'); + $bugs = $this->loadModel('bug')->getUserBugPairs($account); + $tasks = $this->loadModel('task')->getUserTaskPairs($account); + $times = $this->todo->buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + + foreach($todos as $todo) + { + /* fill some field with useful value. */ + if(isset($users[$todo->account])) $todo->account = $users[$todo->account]; + if(isset($times[$todo->begin])) $todo->begin = $times[$todo->begin]; + if(isset($times[$todo->end])) $todo->end = $times[$todo->end]; + if($todo->type == 'bug') $todo->name = isset($bugs[$todo->idvalue]) ? $bugs[$todo->idvalue] : ''; + if($todo->type == 'task') $todo->name = isset($tasks[$todo->idvalue]) ? $tasks[$todo->idvalue] : ''; + if(isset($todoLang->typeList->{$todo->type})) $todo->type = $todoLang->typeList->{$todo->type}; + if(isset($todoLang->priList[$todo->pri])) $todo->pri = $todoLang->priList[$todo->pri]; + if(isset($todoLang->statusList[$todo->status])) $todo->status = $todoLang->statusList[$todo->status]; + if($todo->private == 1) $todo->desc = $this->lang->todo->thisIsPrivate; + + /* drop some field that is not needed. */ + unset($todo->company); + unset($todo->idvalue); + unset($todo->private); + } + + $this->post->set('fields', $fields); + $this->post->set('rows', $todos); + $this->fetch('file', 'export2' . $this->post->fileType, $_POST); + } + + $this->display(); + } +} diff --git a/module/todo/lang/en.php b/module/todo/lang/en.php index 0893ba9fd1..14d925744c 100644 --- a/module/todo/lang/en.php +++ b/module/todo/lang/en.php @@ -1,78 +1,78 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "Index"; -$lang->todo->create = "Create"; -$lang->todo->edit = "Edit"; -$lang->todo->view = "Info"; -$lang->todo->viewAB = "Info"; -$lang->todo->markDone = "Undone"; -$lang->todo->markWait = "Done"; -$lang->todo->markDoing = "Done"; -$lang->todo->mark = "Change status"; -$lang->todo->export = "Export"; -$lang->todo->delete = "Delete"; -$lang->todo->browse = "Browse"; -$lang->todo->import2Today = "Import to today"; -$lang->todo->changeStatus = "Change"; - -$lang->todo->id = 'ID'; -$lang->todo->account = 'Owner'; -$lang->todo->date = 'Date'; -$lang->todo->begin = 'Begin time'; -$lang->todo->beginAB = 'Begin'; -$lang->todo->end = 'End time'; -$lang->todo->endAB = 'End'; -$lang->todo->beginAndEnd = 'Begin and End'; -$lang->todo->type = 'Type'; -$lang->todo->pri = 'Priority'; -$lang->todo->name = 'Name'; -$lang->todo->status = 'Status'; -$lang->todo->desc = 'Desc'; -$lang->todo->private = 'Private'; -$lang->todo->idvalue = 'Task or bug'; - -$lang->todo->week = '(l)'; // date function's param. -$lang->todo->today = 'Today'; -$lang->todo->weekDateList = ''; -$lang->todo->dayInFuture = 'Future'; -$lang->todo->confirmBug = 'This todo linked to bug #%s,chang it also?'; -$lang->todo->confirmTask = 'This todo linked to task #%s,chang it also?'; - -$lang->todo->statusList['wait'] = 'Waiting'; -$lang->todo->statusList['doing'] = 'Doing'; -$lang->todo->statusList['done'] = 'Done'; -//$lang->todo->statusList['cancel'] = '已取消'; -//$lang->todo->statusList['postpone'] = '已延期'; - -$lang->todo->priList[3] = '3'; -$lang->todo->priList[1] = '1'; -$lang->todo->priList[2] = '2'; -$lang->todo->priList[4] = '4'; - -$lang->todo->typeList->custom = 'Custom'; -$lang->todo->typeList->bug = 'Bug'; -$lang->todo->typeList->task = 'Task'; - -$lang->todo->confirmDelete = "Are you sure to delete this todo?"; -$lang->todo->successMarked = "Successfully changed status";; -$lang->todo->thisIsPrivate = 'This is a private todo。:)'; -$lang->todo->lblDisableDate = 'Set time lately'; - -$lang->todo->thisWeekTodos = 'This week'; -$lang->todo->lastWeekTodos = 'Last week'; -$lang->todo->futureTodos = 'Future'; -$lang->todo->allDaysTodos = 'All todo'; -$lang->todo->allUndone = 'Undone'; -$lang->todo->todayTodos = 'Today'; - -$lang->todo->action->marked = array('main' => '$date, Change status to $extra by $actor。', 'extra' => $lang->todo->statusList); + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->todo->common = 'TODO'; +$lang->todo->index = "Index"; +$lang->todo->create = "Create"; +$lang->todo->edit = "Edit"; +$lang->todo->view = "Info"; +$lang->todo->viewAB = "Info"; +$lang->todo->markDone = "Undone"; +$lang->todo->markWait = "Done"; +$lang->todo->markDoing = "Done"; +$lang->todo->mark = "Change status"; +$lang->todo->export = "Export"; +$lang->todo->delete = "Delete"; +$lang->todo->browse = "Browse"; +$lang->todo->import2Today = "Import to today"; +$lang->todo->changeStatus = "Change"; + +$lang->todo->id = 'ID'; +$lang->todo->account = 'Owner'; +$lang->todo->date = 'Date'; +$lang->todo->begin = 'Begin time'; +$lang->todo->beginAB = 'Begin'; +$lang->todo->end = 'End time'; +$lang->todo->endAB = 'End'; +$lang->todo->beginAndEnd = 'Begin and End'; +$lang->todo->type = 'Type'; +$lang->todo->pri = 'Priority'; +$lang->todo->name = 'Name'; +$lang->todo->status = 'Status'; +$lang->todo->desc = 'Desc'; +$lang->todo->private = 'Private'; +$lang->todo->idvalue = 'Task or bug'; + +$lang->todo->week = '(l)'; // date function's param. +$lang->todo->today = 'Today'; +$lang->todo->weekDateList = ''; +$lang->todo->dayInFuture = 'Future'; +$lang->todo->confirmBug = 'This todo linked to bug #%s,chang it also?'; +$lang->todo->confirmTask = 'This todo linked to task #%s,chang it also?'; + +$lang->todo->statusList['wait'] = 'Waiting'; +$lang->todo->statusList['doing'] = 'Doing'; +$lang->todo->statusList['done'] = 'Done'; +//$lang->todo->statusList['cancel'] = '已取消'; +//$lang->todo->statusList['postpone'] = '已延期'; + +$lang->todo->priList[3] = '3'; +$lang->todo->priList[1] = '1'; +$lang->todo->priList[2] = '2'; +$lang->todo->priList[4] = '4'; + +$lang->todo->typeList->custom = 'Custom'; +$lang->todo->typeList->bug = 'Bug'; +$lang->todo->typeList->task = 'Task'; + +$lang->todo->confirmDelete = "Are you sure to delete this todo?"; +$lang->todo->successMarked = "Successfully changed status";; +$lang->todo->thisIsPrivate = 'This is a private todo。:)'; +$lang->todo->lblDisableDate = 'Set time lately'; + +$lang->todo->thisWeekTodos = 'This week'; +$lang->todo->lastWeekTodos = 'Last week'; +$lang->todo->futureTodos = 'Future'; +$lang->todo->allDaysTodos = 'All todo'; +$lang->todo->allUndone = 'Undone'; +$lang->todo->todayTodos = 'Today'; + +$lang->todo->action->marked = array('main' => '$date, Change status to $extra by $actor。', 'extra' => $lang->todo->statusList); diff --git a/module/todo/lang/zh-cn.php b/module/todo/lang/zh-cn.php index 1a8c2a3bfc..9c784b23b9 100644 --- a/module/todo/lang/zh-cn.php +++ b/module/todo/lang/zh-cn.php @@ -1,78 +1,78 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "todo一览"; -$lang->todo->create = "新增TODO"; -$lang->todo->edit = "更新TODO"; -$lang->todo->view = "TODO详情"; -$lang->todo->viewAB = "详情"; -$lang->todo->markDone = "未完成"; -$lang->todo->markWait = "已完成"; -$lang->todo->markDoing = "已完成"; -$lang->todo->mark = "更改状态"; -$lang->todo->export = "导出"; -$lang->todo->delete = "删除TODO"; -$lang->todo->browse = "浏览TODO"; -$lang->todo->import2Today = "导入到今天"; -$lang->todo->changeStatus = "更改"; - -$lang->todo->id = '编号'; -$lang->todo->account = '所有者'; -$lang->todo->date = '日期'; -$lang->todo->begin = '开始时间'; -$lang->todo->beginAB = '开始'; -$lang->todo->end = '结束时间'; -$lang->todo->endAB = '结束'; -$lang->todo->beginAndEnd = '起止时间'; -$lang->todo->type = '类型'; -$lang->todo->pri = '优先级'; -$lang->todo->name = '名称'; -$lang->todo->status = '状态'; -$lang->todo->desc = '描述'; -$lang->todo->private = '私人事务'; -$lang->todo->idvalue = '任务或Bug'; - -$lang->todo->week = '星期'; -$lang->todo->today = '今天'; -$lang->todo->weekDateList = '一,二,三,四,五,六,天'; -$lang->todo->dayInFuture = '暂不指定'; -$lang->todo->confirmBug = '该Todo关联的是Bug #%s,需要修改它吗?'; -$lang->todo->confirmTask = '该Todo关联的是Task #%s,需要修改它吗?'; - -$lang->todo->statusList['wait'] = '未开始'; -$lang->todo->statusList['doing'] = '进行中'; -$lang->todo->statusList['done'] = '已完成'; -//$lang->todo->statusList['cancel'] = '已取消'; -//$lang->todo->statusList['postpone'] = '已延期'; - -$lang->todo->priList[3] = '一般'; -$lang->todo->priList[1] = '最高'; -$lang->todo->priList[2] = '较高'; -$lang->todo->priList[4] = '最低'; - -$lang->todo->typeList->custom = '自定义'; -$lang->todo->typeList->bug = 'Bug'; -$lang->todo->typeList->task = '项目任务'; - -$lang->todo->confirmDelete = "您确定要删除这个todo吗?"; -$lang->todo->successMarked = "成功切换状态!"; -$lang->todo->thisIsPrivate = '这是一条私人事务。:)'; -$lang->todo->lblDisableDate = '暂时不设定时间'; - -$lang->todo->thisWeekTodos = '本周计划'; -$lang->todo->lastWeekTodos = '上周总结'; -$lang->todo->futureTodos = '暂不指定'; -$lang->todo->allDaysTodos = '所有TODO'; -$lang->todo->allUndone = '之前未完'; -$lang->todo->todayTodos = '今日安排'; - -$lang->todo->action->marked = array('main' => '$date, 由 $actor 标记为$extra。', 'extra' => $lang->todo->statusList); + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->todo->common = 'TODO'; +$lang->todo->index = "todo一览"; +$lang->todo->create = "新增TODO"; +$lang->todo->edit = "更新TODO"; +$lang->todo->view = "TODO详情"; +$lang->todo->viewAB = "详情"; +$lang->todo->markDone = "未完成"; +$lang->todo->markWait = "已完成"; +$lang->todo->markDoing = "已完成"; +$lang->todo->mark = "更改状态"; +$lang->todo->export = "导出"; +$lang->todo->delete = "删除TODO"; +$lang->todo->browse = "浏览TODO"; +$lang->todo->import2Today = "导入到今天"; +$lang->todo->changeStatus = "更改"; + +$lang->todo->id = '编号'; +$lang->todo->account = '所有者'; +$lang->todo->date = '日期'; +$lang->todo->begin = '开始时间'; +$lang->todo->beginAB = '开始'; +$lang->todo->end = '结束时间'; +$lang->todo->endAB = '结束'; +$lang->todo->beginAndEnd = '起止时间'; +$lang->todo->type = '类型'; +$lang->todo->pri = '优先级'; +$lang->todo->name = '名称'; +$lang->todo->status = '状态'; +$lang->todo->desc = '描述'; +$lang->todo->private = '私人事务'; +$lang->todo->idvalue = '任务或Bug'; + +$lang->todo->week = '星期'; +$lang->todo->today = '今天'; +$lang->todo->weekDateList = '一,二,三,四,五,六,天'; +$lang->todo->dayInFuture = '暂不指定'; +$lang->todo->confirmBug = '该Todo关联的是Bug #%s,需要修改它吗?'; +$lang->todo->confirmTask = '该Todo关联的是Task #%s,需要修改它吗?'; + +$lang->todo->statusList['wait'] = '未开始'; +$lang->todo->statusList['doing'] = '进行中'; +$lang->todo->statusList['done'] = '已完成'; +//$lang->todo->statusList['cancel'] = '已取消'; +//$lang->todo->statusList['postpone'] = '已延期'; + +$lang->todo->priList[3] = '一般'; +$lang->todo->priList[1] = '最高'; +$lang->todo->priList[2] = '较高'; +$lang->todo->priList[4] = '最低'; + +$lang->todo->typeList->custom = '自定义'; +$lang->todo->typeList->bug = 'Bug'; +$lang->todo->typeList->task = '项目任务'; + +$lang->todo->confirmDelete = "您确定要删除这个todo吗?"; +$lang->todo->successMarked = "成功切换状态!"; +$lang->todo->thisIsPrivate = '这是一条私人事务。:)'; +$lang->todo->lblDisableDate = '暂时不设定时间'; + +$lang->todo->thisWeekTodos = '本周计划'; +$lang->todo->lastWeekTodos = '上周总结'; +$lang->todo->futureTodos = '暂不指定'; +$lang->todo->allDaysTodos = '所有TODO'; +$lang->todo->allUndone = '之前未完'; +$lang->todo->todayTodos = '今日安排'; + +$lang->todo->action->marked = array('main' => '$date, 由 $actor 标记为$extra。', 'extra' => $lang->todo->statusList); diff --git a/module/todo/lang/zh-tw.php b/module/todo/lang/zh-tw.php index 255f8f8d1b..452d75b33c 100644 --- a/module/todo/lang/zh-tw.php +++ b/module/todo/lang/zh-tw.php @@ -1,77 +1,77 @@ - - * @package todo - * @version $Id: zh-tw.php 2383 2011-12-01 07:17:55Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "todo一覽"; -$lang->todo->create = "新增TODO"; -$lang->todo->edit = "更新TODO"; -$lang->todo->view = "TODO詳情"; -$lang->todo->viewAB = "詳情"; -$lang->todo->markDone = "未完成"; -$lang->todo->markWait = "已完成"; -$lang->todo->markDoing = "已完成"; -$lang->todo->mark = "更改狀態"; -$lang->todo->export = "導出"; -$lang->todo->delete = "刪除TODO"; -$lang->todo->browse = "瀏覽TODO"; -$lang->todo->import2Today = "導入到今天"; -$lang->todo->changeStatus = "更改"; - -$lang->todo->id = '編號'; -$lang->todo->account = '所有者'; -$lang->todo->date = '日期'; -$lang->todo->begin = '開始時間'; -$lang->todo->beginAB = '開始'; -$lang->todo->end = '結束時間'; -$lang->todo->endAB = '結束'; -$lang->todo->beginAndEnd = '起止時間'; -$lang->todo->type = '類型'; -$lang->todo->pri = '優先順序'; -$lang->todo->name = '名稱'; -$lang->todo->status = '狀態'; -$lang->todo->desc = '描述'; -$lang->todo->private = '私人事務'; -$lang->todo->idvalue = '任務或Bug'; - -$lang->todo->week = '星期'; -$lang->todo->today = '今天'; -$lang->todo->weekDateList = '一,二,三,四,五,六,天'; -$lang->todo->dayInFeature = '暫不指定'; -$lang->todo->confirmBug = '該Todo關聯的是Bug #%s,需要修改它嗎?'; -$lang->todo->confirmTask = '該Todo關聯的是Task #%s,需要修改它嗎?'; - -$lang->todo->statusList['wait'] = '未開始'; -$lang->todo->statusList['doing'] = '進行中'; -$lang->todo->statusList['done'] = '已完成'; -//$lang->todo->statusList['cancel'] = '已取消'; -//$lang->todo->statusList['postpone'] = '已延期'; - -$lang->todo->priList[3] = '一般'; -$lang->todo->priList[1] = '最高'; -$lang->todo->priList[2] = '較高'; -$lang->todo->priList[4] = '最低'; - -$lang->todo->typeList->custom = '自定義'; -$lang->todo->typeList->bug = 'Bug'; -$lang->todo->typeList->task = '項目任務'; - -$lang->todo->confirmDelete = "您確定要刪除這個todo嗎?"; -$lang->todo->successMarked = "成功切換狀態!"; -$lang->todo->thisIsPrivate = '這是一條私人事務。:)'; -$lang->todo->lblDisableDate = '暫時不設定時間'; - -$lang->todo->thisWeekTodos = '本週計劃'; -$lang->todo->lastWeekTodos = '上周總結'; -$lang->todo->allDaysTodos = '所有TODO'; -$lang->todo->allUndone = '之前未完'; -$lang->todo->todayTodos = '今日安排'; - -$lang->todo->action->marked = array('main' => '$date, 由 $actor 標記為$extra。', 'extra' => $lang->todo->statusList); + + * @package todo + * @version $Id: zh-tw.php 2383 2011-12-01 07:17:55Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->todo->common = 'TODO'; +$lang->todo->index = "todo一覽"; +$lang->todo->create = "新增TODO"; +$lang->todo->edit = "更新TODO"; +$lang->todo->view = "TODO詳情"; +$lang->todo->viewAB = "詳情"; +$lang->todo->markDone = "未完成"; +$lang->todo->markWait = "已完成"; +$lang->todo->markDoing = "已完成"; +$lang->todo->mark = "更改狀態"; +$lang->todo->export = "導出"; +$lang->todo->delete = "刪除TODO"; +$lang->todo->browse = "瀏覽TODO"; +$lang->todo->import2Today = "導入到今天"; +$lang->todo->changeStatus = "更改"; + +$lang->todo->id = '編號'; +$lang->todo->account = '所有者'; +$lang->todo->date = '日期'; +$lang->todo->begin = '開始時間'; +$lang->todo->beginAB = '開始'; +$lang->todo->end = '結束時間'; +$lang->todo->endAB = '結束'; +$lang->todo->beginAndEnd = '起止時間'; +$lang->todo->type = '類型'; +$lang->todo->pri = '優先順序'; +$lang->todo->name = '名稱'; +$lang->todo->status = '狀態'; +$lang->todo->desc = '描述'; +$lang->todo->private = '私人事務'; +$lang->todo->idvalue = '任務或Bug'; + +$lang->todo->week = '星期'; +$lang->todo->today = '今天'; +$lang->todo->weekDateList = '一,二,三,四,五,六,天'; +$lang->todo->dayInFeature = '暫不指定'; +$lang->todo->confirmBug = '該Todo關聯的是Bug #%s,需要修改它嗎?'; +$lang->todo->confirmTask = '該Todo關聯的是Task #%s,需要修改它嗎?'; + +$lang->todo->statusList['wait'] = '未開始'; +$lang->todo->statusList['doing'] = '進行中'; +$lang->todo->statusList['done'] = '已完成'; +//$lang->todo->statusList['cancel'] = '已取消'; +//$lang->todo->statusList['postpone'] = '已延期'; + +$lang->todo->priList[3] = '一般'; +$lang->todo->priList[1] = '最高'; +$lang->todo->priList[2] = '較高'; +$lang->todo->priList[4] = '最低'; + +$lang->todo->typeList->custom = '自定義'; +$lang->todo->typeList->bug = 'Bug'; +$lang->todo->typeList->task = '項目任務'; + +$lang->todo->confirmDelete = "您確定要刪除這個todo嗎?"; +$lang->todo->successMarked = "成功切換狀態!"; +$lang->todo->thisIsPrivate = '這是一條私人事務。:)'; +$lang->todo->lblDisableDate = '暫時不設定時間'; + +$lang->todo->thisWeekTodos = '本週計劃'; +$lang->todo->lastWeekTodos = '上周總結'; +$lang->todo->allDaysTodos = '所有TODO'; +$lang->todo->allUndone = '之前未完'; +$lang->todo->todayTodos = '今日安排'; + +$lang->todo->action->marked = array('main' => '$date, 由 $actor 標記為$extra。', 'extra' => $lang->todo->statusList); diff --git a/module/todo/model.php b/module/todo/model.php index 5b58f7a5dd..34ce7a0de3 100644 --- a/module/todo/model.php +++ b/module/todo/model.php @@ -1,428 +1,428 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> -add('account', $this->app->user->account) - ->add('idvalue', 0) - ->specialChars('type,name') - ->cleanInt('date, pri, begin, end, private') - ->setIF($this->post->type != 'custom', 'name', '') - ->setIF($this->post->type == 'bug' and $this->post->bug, 'idvalue', $this->post->bug) - ->setIF($this->post->type == 'task' and $this->post->task, 'idvalue', $this->post->task) - ->setIF($this->post->begin == false, 'begin', '2400') - ->setIF($this->post->end == false, 'end', '2400') - ->remove('bug, task') - ->get(); - - $this->dao->insert(TABLE_TODO)->data($todo) - ->autoCheck() - ->checkIF($todo->type == 'custom', $this->config->todo->create->requiredFields, 'notempty') - ->checkIF($todo->type == 'bug' and $todo->idvalue == 0, 'idvalue', 'notempty') - ->checkIF($todo->type == 'task' and $todo->idvalue == 0, 'idvalue', 'notempty') - ->exec(); - return $this->dao->lastInsertID(); - } - - /** - * update a todo. - * - * @param int $todoID - * @access public - * @return void - */ - public function update($todoID) - { - $oldTodo = $this->getById($todoID); - if($oldTodo->type != 'custom') $oldTodo->name = ''; - $todo = fixer::input('post') - ->cleanInt('date, pri, begin, end, private') - ->specialChars('type,name') - ->setIF($this->post->type != 'custom', 'name', '') - ->setIF($this->post->begin == false, 'begin', '2400') - ->setIF($this->post->end == false, 'end', '2400') - ->setDefault('private', 0) - ->get(); - $this->dao->update(TABLE_TODO)->data($todo) - ->autoCheck() - ->checkIF($todo->type == 'custom', $this->config->todo->edit->requiredFields, 'notempty')->where('id')->eq($todoID) - ->exec(); - if(!dao::isError()) return common::createChanges($oldTodo, $todo); - } - - /** - * Change the status of a todo. - * - * @param string $todoID - * @param string $status - * @access public - * @return void - */ - public function mark($todoID, $status) - { - $status = ($status == 'done') ? 'wait' : 'done'; - $this->dao->update(TABLE_TODO)->set('status')->eq($status)->where('id')->eq((int)$todoID)->exec(); - $this->loadModel('action')->create('todo', $todoID, 'marked', '', $status); - return; - } - - /** - * Get info of a todo. - * - * @param int $todoID - * @access public - * @return object|bool - */ - public function getById($todoID) - { - $todo = $this->dao->findById((int)$todoID)->from(TABLE_TODO)->fetch(); - if(!$todo) return false; - $todo->desc = $this->loadModel('file')->setImgSize($todo->desc); - if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); - if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); - $todo->date = str_replace('-', '', $todo->date); - return $todo; - } - - /** - * Get todo list of a user. - * - * @param date $date - * @param string $account - * @param string $status all|today|thisweek|lastweek|before, or a date. - * @param int $limit - * @access public - * @return void - */ - public function getList($date = 'today', $account = '', $status = 'all', $limit = 0) - { - $todos = array(); - if($date == 'today') - { - $begin = $this->today(); - $end = $begin; - } - elseif($date == 'thisweek') - { - extract($this->getThisWeek()); - } - elseif($date == 'lastweek') - { - extract($this->getLastWeek()); - } - elseif($date == 'future') - { - $begin = '2030-01-01'; - $end = $begin; - } - elseif($date == 'all') - { - $begin = '1970-01-01'; - $end = '2109-01-01'; - } - elseif($date == 'before') - { - $begin = '1970-01-01'; - $end = $this->yesterday(); - } - else - { - $begin = $end = $date; - } - - if($account == '') $account = $this->app->user->account; - - $stmt = $this->dao->select('*')->from(TABLE_TODO) - ->where('account')->eq($account) - ->andWhere("date >= '$begin'") - ->andWhere("date <= '$end'") - ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() - ->beginIF($status == 'undone')->andWhere('status')->ne('done')->fi() - ->orderBy('date, status, begin') - ->beginIF($limit > 0)->limit($limit)->fi() - ->query(); - - /* Set session. */ - $sql = explode('WHERE', $this->dao->get()); - $sql = explode('ORDER', $sql[1]); - $this->session->set('todoReportCondition', $sql[0]); - - while($todo = $stmt->fetch()) - { - if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); - if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); - $todo->begin = $this->formatTime($todo->begin); - $todo->end = $this->formatTime($todo->end); - - /* If is private, change the title to private. */ - if($todo->private and $this->app->user->account != $todo->account) $todo->name = $this->lang->todo->thisIsPrivate; - $todos[] = $todo; - } - return $todos; - } - - /** - * Build date list, for selection use. - * - * @param int $before - * @param int $after - * @access public - * @return void - */ - public function buildDateList($before = 7, $after = 7) - { - $today = strtotime($this->today()); - $delta = 60 * 60 * 24; - $dates = array(); - $weekList = range(1, 7); - $weekDateList = explode(',', $this->lang->todo->weekDateList); - for($i = -1 * $before; $i <= $after; $i ++) - { - $time = $today + $i * $delta; - $label = date(DT_DATE1, $time); - if($i == 0) - { - $label .= " ({$this->lang->todo->today})"; - } - else - { - if($this->cookie->lang == 'zh-cn' or $this->cookie->lang == 'zh-tw') - { - $label .= str_replace($weekList, $weekDateList, date(" ({$this->lang->todo->week}N)", $time)); - } - else - { - $label .= date($this->lang->todo->week, $time); - } - } - $date = date(DT_DATE2, $time); - $dates[$date] = $label; - } - $dates[self::DAY_IN_FUTURE] = $this->lang->todo->dayInFuture; - return $dates; - } - - /** - * Build hour time list. - * - * @param int $begin - * @param int $end - * @param int $delta - * @access public - * @return array - */ - public function buildTimeList($begin, $end, $delta) - { - $times = array(); - for($hour = $begin; $hour <= $end; $hour ++) - { - for($minutes = 0; $minutes < 60; $minutes += $delta) - { - $time = sprintf('%02d%02d', $hour, $minutes); - $label = sprintf('%02d:%02d', $hour, $minutes); - $times[$time] = $label; - } - } - return $times; - } - - /** - * Get today. - * - * @access public - * @return date - */ - public function today() - { - return date(DT_DATE2, time()); - } - - /** - * Get yesterday - * - * @access public - * @return date - */ - public function yesterday() - { - return date(DT_DATE1, strtotime('yesterday')); - } - - /** - * Get tomorrow. - * - * @access public - * @return date - */ - public function tomorrow() - { - return date(DT_DATE1, strtotime('tomorrow')); - } - - /** - * Get the day before yesterday. - * - * @access public - * @return date - */ - public function twoDaysAgo() - { - return date(DT_DATE1, strtotime('-2 days')); - } - - /** - * Get now time period. - * - * @param int $delta - * @access public - * @return string the current time period, like 0915 - */ - public function now($delta = 10) - { - $range = range($delta, 60 - $delta, $delta); - $hour = date('H', time()); - $minute = date('i', time()); - - if($minute > 60 - $delta) - { - $hour += 1; - $minute = 00; - } - else - { - for($i = 0; $i < $delta; $i ++) - { - if(in_array($minute + $i, $range)) - { - $minute = $minute + $i; - break; - } - } - } - - return sprintf('%02d%02d', $hour, $minute); - } - - /** - * Format time 0915 to 09:15 - * - * @param string $time - * @access public - * @return string - */ - public function formatTime($time) - { - if(strlen($time) != 4 or $time == '2400') return ''; - return substr($time, 0, 2) . ':' . substr($time, 2, 2); - } - - /** - * Get the begin and end date of this week. - * - * @access public - * @return array - */ - public function getThisWeek() - { - $baseTime = $this->getMiddleOfThisWeek(); - $begin = date(DT_DATE1, strtotime('last monday', $baseTime)); - $end = date(DT_DATE1, strtotime('next sunday', $baseTime)); - return array('begin' => $begin, 'end' => $end); - } - - /** - * Get the begin and end date of last week. - * - * @access public - * @return array - */ - public function getLastWeek() - { - $baseTime = $this->getMiddleOfLastWeek(); - $begin = date(DT_DATE1, strtotime('last monday', $baseTime)); - $end = date(DT_DATE1, strtotime('next sunday', $baseTime)); - return array('begin' => $begin, 'end' => $end); - } - - /** - * Get the time at the middle of this week. - * - * If today in week is 1, move it one day in future. Else is 7, move it back one day. To keep the time geted in this week. - * - * @access private - * @return time - */ - private function getMiddleOfThisWeek() - { - $baseTime = time(); - $weekDay = date('N'); - if($weekDay == 1) $baseTime = time() + 86400; - if($weekDay == 7) $baseTime = time() - 86400; - return $baseTime; - } - - /** - * Get middle of last week - * - * @access private - * @return time - */ - private function getMiddleOfLastWeek() - { - $baseTime = time(); - $weekDay = date('N'); - $baseTime = time() - 86400 * 7; - if($weekDay == 1) $baseTime = time() - 86400 * 4; // Make sure is last thursday. - if($weekDay == 7) $baseTime = time() - 86400 * 10; // Make sure is last thursday. - return $baseTime; - } - - /** - * Get this month begin and end time - * - * @access public - * @return array - */ - public function getThisMonth() - { - $begin = date('Y-m'); - $end = date('Y-m', strtotime('next month')); - return array('begin' => $begin, 'end' => $end); - } - - /** - * Get last month begin and end time - * - * @access public - * @return array - */ - public function getLastMonth() - { - $begin = date('Y-m', strtotime('last month')); - $end = date('Y-m', strtotime('this month')); - return array('begin' => $begin, 'end' => $end); - } -} + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> +add('account', $this->app->user->account) + ->add('idvalue', 0) + ->specialChars('type,name') + ->cleanInt('date, pri, begin, end, private') + ->setIF($this->post->type != 'custom', 'name', '') + ->setIF($this->post->type == 'bug' and $this->post->bug, 'idvalue', $this->post->bug) + ->setIF($this->post->type == 'task' and $this->post->task, 'idvalue', $this->post->task) + ->setIF($this->post->begin == false, 'begin', '2400') + ->setIF($this->post->end == false, 'end', '2400') + ->remove('bug, task') + ->get(); + + $this->dao->insert(TABLE_TODO)->data($todo) + ->autoCheck() + ->checkIF($todo->type == 'custom', $this->config->todo->create->requiredFields, 'notempty') + ->checkIF($todo->type == 'bug' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($todo->type == 'task' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->exec(); + return $this->dao->lastInsertID(); + } + + /** + * update a todo. + * + * @param int $todoID + * @access public + * @return void + */ + public function update($todoID) + { + $oldTodo = $this->getById($todoID); + if($oldTodo->type != 'custom') $oldTodo->name = ''; + $todo = fixer::input('post') + ->cleanInt('date, pri, begin, end, private') + ->specialChars('type,name') + ->setIF($this->post->type != 'custom', 'name', '') + ->setIF($this->post->begin == false, 'begin', '2400') + ->setIF($this->post->end == false, 'end', '2400') + ->setDefault('private', 0) + ->get(); + $this->dao->update(TABLE_TODO)->data($todo) + ->autoCheck() + ->checkIF($todo->type == 'custom', $this->config->todo->edit->requiredFields, 'notempty')->where('id')->eq($todoID) + ->exec(); + if(!dao::isError()) return common::createChanges($oldTodo, $todo); + } + + /** + * Change the status of a todo. + * + * @param string $todoID + * @param string $status + * @access public + * @return void + */ + public function mark($todoID, $status) + { + $status = ($status == 'done') ? 'wait' : 'done'; + $this->dao->update(TABLE_TODO)->set('status')->eq($status)->where('id')->eq((int)$todoID)->exec(); + $this->loadModel('action')->create('todo', $todoID, 'marked', '', $status); + return; + } + + /** + * Get info of a todo. + * + * @param int $todoID + * @access public + * @return object|bool + */ + public function getById($todoID) + { + $todo = $this->dao->findById((int)$todoID)->from(TABLE_TODO)->fetch(); + if(!$todo) return false; + $todo->desc = $this->loadModel('file')->setImgSize($todo->desc); + if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); + if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); + $todo->date = str_replace('-', '', $todo->date); + return $todo; + } + + /** + * Get todo list of a user. + * + * @param date $date + * @param string $account + * @param string $status all|today|thisweek|lastweek|before, or a date. + * @param int $limit + * @access public + * @return void + */ + public function getList($date = 'today', $account = '', $status = 'all', $limit = 0) + { + $todos = array(); + if($date == 'today') + { + $begin = $this->today(); + $end = $begin; + } + elseif($date == 'thisweek') + { + extract($this->getThisWeek()); + } + elseif($date == 'lastweek') + { + extract($this->getLastWeek()); + } + elseif($date == 'future') + { + $begin = '2030-01-01'; + $end = $begin; + } + elseif($date == 'all') + { + $begin = '1970-01-01'; + $end = '2109-01-01'; + } + elseif($date == 'before') + { + $begin = '1970-01-01'; + $end = $this->yesterday(); + } + else + { + $begin = $end = $date; + } + + if($account == '') $account = $this->app->user->account; + + $stmt = $this->dao->select('*')->from(TABLE_TODO) + ->where('account')->eq($account) + ->andWhere("date >= '$begin'") + ->andWhere("date <= '$end'") + ->beginIF($status != 'all' and $status != 'undone')->andWhere('status')->in($status)->fi() + ->beginIF($status == 'undone')->andWhere('status')->ne('done')->fi() + ->orderBy('date, status, begin') + ->beginIF($limit > 0)->limit($limit)->fi() + ->query(); + + /* Set session. */ + $sql = explode('WHERE', $this->dao->get()); + $sql = explode('ORDER', $sql[1]); + $this->session->set('todoReportCondition', $sql[0]); + + while($todo = $stmt->fetch()) + { + if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); + if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); + $todo->begin = $this->formatTime($todo->begin); + $todo->end = $this->formatTime($todo->end); + + /* If is private, change the title to private. */ + if($todo->private and $this->app->user->account != $todo->account) $todo->name = $this->lang->todo->thisIsPrivate; + $todos[] = $todo; + } + return $todos; + } + + /** + * Build date list, for selection use. + * + * @param int $before + * @param int $after + * @access public + * @return void + */ + public function buildDateList($before = 7, $after = 7) + { + $today = strtotime($this->today()); + $delta = 60 * 60 * 24; + $dates = array(); + $weekList = range(1, 7); + $weekDateList = explode(',', $this->lang->todo->weekDateList); + for($i = -1 * $before; $i <= $after; $i ++) + { + $time = $today + $i * $delta; + $label = date(DT_DATE1, $time); + if($i == 0) + { + $label .= " ({$this->lang->todo->today})"; + } + else + { + if($this->cookie->lang == 'zh-cn' or $this->cookie->lang == 'zh-tw') + { + $label .= str_replace($weekList, $weekDateList, date(" ({$this->lang->todo->week}N)", $time)); + } + else + { + $label .= date($this->lang->todo->week, $time); + } + } + $date = date(DT_DATE2, $time); + $dates[$date] = $label; + } + $dates[self::DAY_IN_FUTURE] = $this->lang->todo->dayInFuture; + return $dates; + } + + /** + * Build hour time list. + * + * @param int $begin + * @param int $end + * @param int $delta + * @access public + * @return array + */ + public function buildTimeList($begin, $end, $delta) + { + $times = array(); + for($hour = $begin; $hour <= $end; $hour ++) + { + for($minutes = 0; $minutes < 60; $minutes += $delta) + { + $time = sprintf('%02d%02d', $hour, $minutes); + $label = sprintf('%02d:%02d', $hour, $minutes); + $times[$time] = $label; + } + } + return $times; + } + + /** + * Get today. + * + * @access public + * @return date + */ + public function today() + { + return date(DT_DATE2, time()); + } + + /** + * Get yesterday + * + * @access public + * @return date + */ + public function yesterday() + { + return date(DT_DATE1, strtotime('yesterday')); + } + + /** + * Get tomorrow. + * + * @access public + * @return date + */ + public function tomorrow() + { + return date(DT_DATE1, strtotime('tomorrow')); + } + + /** + * Get the day before yesterday. + * + * @access public + * @return date + */ + public function twoDaysAgo() + { + return date(DT_DATE1, strtotime('-2 days')); + } + + /** + * Get now time period. + * + * @param int $delta + * @access public + * @return string the current time period, like 0915 + */ + public function now($delta = 10) + { + $range = range($delta, 60 - $delta, $delta); + $hour = date('H', time()); + $minute = date('i', time()); + + if($minute > 60 - $delta) + { + $hour += 1; + $minute = 00; + } + else + { + for($i = 0; $i < $delta; $i ++) + { + if(in_array($minute + $i, $range)) + { + $minute = $minute + $i; + break; + } + } + } + + return sprintf('%02d%02d', $hour, $minute); + } + + /** + * Format time 0915 to 09:15 + * + * @param string $time + * @access public + * @return string + */ + public function formatTime($time) + { + if(strlen($time) != 4 or $time == '2400') return ''; + return substr($time, 0, 2) . ':' . substr($time, 2, 2); + } + + /** + * Get the begin and end date of this week. + * + * @access public + * @return array + */ + public function getThisWeek() + { + $baseTime = $this->getMiddleOfThisWeek(); + $begin = date(DT_DATE1, strtotime('last monday', $baseTime)); + $end = date(DT_DATE1, strtotime('next sunday', $baseTime)); + return array('begin' => $begin, 'end' => $end); + } + + /** + * Get the begin and end date of last week. + * + * @access public + * @return array + */ + public function getLastWeek() + { + $baseTime = $this->getMiddleOfLastWeek(); + $begin = date(DT_DATE1, strtotime('last monday', $baseTime)); + $end = date(DT_DATE1, strtotime('next sunday', $baseTime)); + return array('begin' => $begin, 'end' => $end); + } + + /** + * Get the time at the middle of this week. + * + * If today in week is 1, move it one day in future. Else is 7, move it back one day. To keep the time geted in this week. + * + * @access private + * @return time + */ + private function getMiddleOfThisWeek() + { + $baseTime = time(); + $weekDay = date('N'); + if($weekDay == 1) $baseTime = time() + 86400; + if($weekDay == 7) $baseTime = time() - 86400; + return $baseTime; + } + + /** + * Get middle of last week + * + * @access private + * @return time + */ + private function getMiddleOfLastWeek() + { + $baseTime = time(); + $weekDay = date('N'); + $baseTime = time() - 86400 * 7; + if($weekDay == 1) $baseTime = time() - 86400 * 4; // Make sure is last thursday. + if($weekDay == 7) $baseTime = time() - 86400 * 10; // Make sure is last thursday. + return $baseTime; + } + + /** + * Get this month begin and end time + * + * @access public + * @return array + */ + public function getThisMonth() + { + $begin = date('Y-m'); + $end = date('Y-m', strtotime('next month')); + return array('begin' => $begin, 'end' => $end); + } + + /** + * Get last month begin and end time + * + * @access public + * @return array + */ + public function getLastMonth() + { + $begin = date('Y-m', strtotime('last month')); + $end = date('Y-m', strtotime('this month')); + return array('begin' => $begin, 'end' => $end); + } +} diff --git a/module/todo/view/create.html.php b/module/todo/view/create.html.php index 03a33d67aa..da82852244 100644 --- a/module/todo/view/create.html.php +++ b/module/todo/view/create.html.php @@ -1,61 +1,61 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->create;?>
          todo->date;?>
          todo->type;?>todo->typeList, '', 'onchange=loadList(this.value); class=select-3');?> -
          todo->pri;?>todo->priList, '', 'class=select-3');?>
          todo->name;?>
          todo->desc;?> -
          todo->status;?>todo->statusList, '', 'class=select-3');?>
          todo->beginAndEnd;?> - - todo->lblDisableDate;?> -
          todo->private;?>
          - -
          -
          - - + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          todo->create;?>
          todo->date;?>
          todo->type;?>todo->typeList, '', 'onchange=loadList(this.value); class=select-3');?> +
          todo->pri;?>todo->priList, '', 'class=select-3');?>
          todo->name;?>
          todo->desc;?> +
          todo->status;?>todo->statusList, '', 'class=select-3');?>
          todo->beginAndEnd;?> + + todo->lblDisableDate;?> +
          todo->private;?>
          + +
          +
          + + diff --git a/module/todo/view/edit.html.php b/module/todo/view/edit.html.php index 277460c13b..1476feafd2 100644 --- a/module/todo/view/edit.html.php +++ b/module/todo/view/edit.html.php @@ -1,67 +1,67 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->edit;?>
          todo->date;?>date, 'class=select-3');?>
          todo->type;?>todo->typeList->{$todo->type};?>
          todo->pri;?>todo->priList, $todo->pri, 'class=select-3');?>
          todo->name;?>
          - type != 'custom' ? 'readonly' : ''; - echo html::input('name', $todo->name, "$readType class=text-1"); - ?> -
          -
          todo->desc;?>desc), "rows=8 class=area-1");?>
          todo->status;?>todo->statusList, $todo->status, 'class=select-3');?>
          todo->beginAndEnd;?> - begin, 'onchange=selectNext(); class=select-2') . html::select('end', $times, $todo->end, 'class=select-2');?> - begin == 2400) echo 'checked';?> >todo->lblDisableDate;?> -
          todo->private;?>private) echo 'checked';?>>
          - -
          -
          - - + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          todo->edit;?>
          todo->date;?>date, 'class=select-3');?>
          todo->type;?>todo->typeList->{$todo->type};?>
          todo->pri;?>todo->priList, $todo->pri, 'class=select-3');?>
          todo->name;?>
          + type != 'custom' ? 'readonly' : ''; + echo html::input('name', $todo->name, "$readType class=text-1"); + ?> +
          +
          todo->desc;?>desc), "rows=8 class=area-1");?>
          todo->status;?>todo->statusList, $todo->status, 'class=select-3');?>
          todo->beginAndEnd;?> + begin, 'onchange=selectNext(); class=select-2') . html::select('end', $times, $todo->end, 'class=select-2');?> + begin == 2400) echo 'checked';?> >todo->lblDisableDate;?> +
          todo->private;?>private) echo 'checked';?>>
          + +
          +
          + + diff --git a/module/todo/view/export.html.php b/module/todo/view/export.html.php index baf4ec75a1..5bc94f06fc 100755 --- a/module/todo/view/export.html.php +++ b/module/todo/view/export.html.php @@ -1,13 +1,13 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + diff --git a/module/todo/view/view.html.php b/module/todo/view/view.html.php index 207778ec3e..20e0f7c38e 100644 --- a/module/todo/view/view.html.php +++ b/module/todo/view/view.html.php @@ -1,87 +1,87 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -private or ($todo->private and $todo->account == $app->user->account)):?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->view;?>
          todo->account;?>account;?>
          todo->date;?>date == TODOModel::DAY_IN_FUTURE ? $lang->todo->dayInFuture : date(DT_DATE1, strtotime($todo->date)));?>
          todo->type;?>todo->typeList->{$todo->type};?>
          todo->pri;?>todo->priList[$todo->pri];?>
          todo->name;?> - type == 'bug') echo html::a($this->createLink('bug', 'view', "id={$todo->idvalue}"), $todo->name); - if($todo->type == 'task') echo html::a($this->createLink('task', 'view', "id={$todo->idvalue}"), $todo->name); - if($todo->type == 'custom') echo $todo->name; - ?> -
          todo->desc;?>desc;?>
          todo->status;?>todo->statusList[$todo->status];?>
          todo->beginAndEnd;?> - begin])) echo $times[$todo->begin]; - if(isset($times[$todo->end])) echo ' ~ ' . $times[$todo->end]; - ?> -
          -
          - session->todoList) - { - $browseLink = $this->session->todoList; - } - elseif($todo->account == $app->user->account) - { - $browseLink = $this->createLink('my', 'todo'); - } - else - { - $browseLink = $this->createLink('user', 'todo', "account=$todo->account"); - } - if($todo->account == $app->user->account) - { - common::printLink('todo', 'edit', "todoID=$todo->id", $lang->edit); - common::printLink('todo', 'delete', "todoID=$todo->id", $lang->delete, 'hiddenwin'); - } - echo html::a($browseLink, $lang->goback); - ?> -
          - - -todo->thisIsPrivate;?> - - + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +private or ($todo->private and $todo->account == $app->user->account)):?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          todo->view;?>
          todo->account;?>account;?>
          todo->date;?>date == TODOModel::DAY_IN_FUTURE ? $lang->todo->dayInFuture : date(DT_DATE1, strtotime($todo->date)));?>
          todo->type;?>todo->typeList->{$todo->type};?>
          todo->pri;?>todo->priList[$todo->pri];?>
          todo->name;?> + type == 'bug') echo html::a($this->createLink('bug', 'view', "id={$todo->idvalue}"), $todo->name); + if($todo->type == 'task') echo html::a($this->createLink('task', 'view', "id={$todo->idvalue}"), $todo->name); + if($todo->type == 'custom') echo $todo->name; + ?> +
          todo->desc;?>desc;?>
          todo->status;?>todo->statusList[$todo->status];?>
          todo->beginAndEnd;?> + begin])) echo $times[$todo->begin]; + if(isset($times[$todo->end])) echo ' ~ ' . $times[$todo->end]; + ?> +
          +
          + session->todoList) + { + $browseLink = $this->session->todoList; + } + elseif($todo->account == $app->user->account) + { + $browseLink = $this->createLink('my', 'todo'); + } + else + { + $browseLink = $this->createLink('user', 'todo', "account=$todo->account"); + } + if($todo->account == $app->user->account) + { + common::printLink('todo', 'edit', "todoID=$todo->id", $lang->edit); + common::printLink('todo', 'delete', "todoID=$todo->id", $lang->delete, 'hiddenwin'); + } + echo html::a($browseLink, $lang->goback); + ?> +
          + + +todo->thisIsPrivate;?> + + diff --git a/module/tree/control.php b/module/tree/control.php index c46b81a151..8db150cc6e 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -1,237 +1,237 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -class tree extends control -{ - const NEW_CHILD_COUNT = 5; - - /** - * Module browse. - * - * @param int $rootID - * @param string $viewType story|bug|case|doc - * @param int $currentModuleID - * @access public - * @return void - */ - public function browse($rootID, $viewType, $currentModuleID = 0) - { - /* According to the type, set the module root and modules. */ - if(strpos('story|bug|case', $viewType) !== false) - { - $product = $this->loadModel('product')->getById($rootID); - $this->view->root = $product; - $this->view->productModules = $this->tree->getOptionMenu($rootID, 'story'); - } - /* The viewType is doc. */ - elseif(strpos($viewType, 'doc') !== false) - { - $this->loadModel('doc'); - if($rootID == 'product' or $rootID == 'project') - { - $viewType = $rootID . 'doc'; - $lib->id = $rootID; - $lib->name = $this->lang->doc->systemLibs[$rootID]; - $this->view->root = $lib; - } - else - { - $viewType = 'customdoc'; - $lib = $this->loadModel('doc')->getLibById($rootID); - $this->view->root = $lib; - } - } - - if($viewType == 'story') - { - $this->lang->set('menugroup.tree', 'product'); - $this->product->setMenu($this->product->getPairs(), $rootID, 'story'); - $this->lang->tree->menu = $this->lang->product->menu; - - $products = $this->product->getPairs(); - unset($products[$rootID]); - $currentProduct = key($products); - - $this->view->allProduct = $products; - $this->view->currentProduct = $currentProduct; - $this->view->productModules = $this->tree->getOptionMenu($currentProduct, 'story'); - - $header['title'] = $this->lang->tree->manageProduct . $this->lang->colon . $product->name; - $position[] = html::a($this->createLink('product', 'browse', "product=$rootID"), $product->name); - $position[] = $this->lang->tree->manageProduct; - } - elseif($viewType == 'bug') - { - $this->loadModel('bug')->setMenu($this->product->getPairs(), $rootID); - $this->lang->tree->menu = $this->lang->bug->menu; - $this->lang->set('menugroup.tree', 'qa'); - - $header['title'] = $this->lang->tree->manageBug . $this->lang->colon . $product->name; - $position[] = html::a($this->createLink('bug', 'browse', "product=$rootID"), $product->name); - $position[] = $this->lang->tree->manageBug; - } - elseif($viewType == 'case') - { - $this->loadModel('testcase')->setMenu($this->product->getPairs(), $rootID); - $this->lang->tree->menu = $this->lang->testcase->menu; - $this->lang->set('menugroup.tree', 'qa'); - - $header['title'] = $this->lang->tree->manageCase . $this->lang->colon . $product->name; - $position[] = html::a($this->createLink('testcase', 'browse', "product=$rootID"), $product->name); - $position[] = $this->lang->tree->manageCase; - } - elseif(strpos($viewType, 'doc') !== false) - { - $this->doc->setMenu($this->doc->getLibs(), $rootID, 'doc'); - $this->lang->tree->menu = $this->lang->doc->menu; - $this->lang->set('menugroup.tree', 'doc'); - - $header['title'] = $this->lang->tree->manageCustomDoc . $this->lang->colon . $lib->name; - $position[] = html::a($this->createLink('doc', 'browse', "libID=$rootID"), $lib->name); - $position[] = $this->lang->tree->manageCustomDoc; - } - - $parentModules = $this->tree->getParents($currentModuleID); - $this->view->header = $header; - $this->view->position = $position; - $this->view->rootID = $rootID; - $this->view->viewType = $viewType; - $this->view->modules = $this->tree->getTreeMenu($rootID, $viewType, $rooteModuleID = 0, array('treeModel', 'createManageLink')); - $this->view->sons = $this->tree->getSons($rootID, $currentModuleID, $viewType); - $this->view->currentModuleID = $currentModuleID; - $this->view->parentModules = $parentModules; - $this->display(); - } - - /** - * Edit a module. - * - * @param int $moduleID - * @access public - * @return void - */ - public function edit($moduleID) - { - if(!empty($_POST)) - { - $this->tree->update($moduleID); - echo js::alert($this->lang->tree->successSave); - die(js::reload('parent')); - } - $module = $this->tree->getById($moduleID); - if($module->owner == null) - { - $module->owner = $this->loadModel('product')->getById($module->root)->QM; - } - $this->view->module = $module; - $this->view->optionMenu = $this->tree->getOptionMenu($this->view->module->root, $this->view->module->type); - $this->view->users = $this->loadModel('user')->getPairs('noclosed'); - - /* Remove self and childs from the $optionMenu. Because it's parent can't be self or childs. */ - $childs = $this->tree->getAllChildId($moduleID); - foreach($childs as $childModuleID) unset($this->view->optionMenu[$childModuleID]); - - die($this->display()); - } - - /** - * Update modules' orders. - * - * @access public - * @return void - */ - public function updateOrder() - { - if(!empty($_POST)) - { - $this->tree->updateOrder($_POST['orders']); - die(js::reload('parent')); - } - } - - /** - * Manage child modules. - * - * @param int $rootID - * @param string $viewType - * @access public - * @return void - */ - public function manageChild($rootID, $viewType) - { - if(!empty($_POST)) - { - $this->tree->manageChild($rootID, $viewType, $_POST['parentModuleID'], $_POST['modules']); - die(js::reload('parent')); - } - } - - /** - * Delete a module. - * - * @param int $rootID - * @param int $moduleID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($rootID, $moduleID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->tree->confirmDelete, $this->createLink('tree', 'delete', "rootID=$rootID&moduleID=$moduleID&confirm=yes")); - exit; - } - else - { - $this->tree->delete($moduleID); - die(js::reload('parent')); - } - } - - /** - * AJAX: Get the option menu of modules. - * - * @param int $rootID - * @param string $viewType - * @param int $rootModuleID - * @access public - * @return string the html select string. - */ - public function ajaxGetOptionMenu($rootID, $viewType = 'story', $rootModuleID = 0, $returnType = 'html') - { - - $this->view->productModules = $this->tree->getOptionMenu($rootID, 'story'); - $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID); - if($returnType == 'html') die( html::select("module", $optionMenu, '', 'onchange=setAssignedTo()')); - if($returnType == 'json') die(json_encode($optionMenu)); - } - - /** - * AJAX: get a module's son modules. - * - * @param int $moduleID - * @param int $rootID - * @access public - * @return string json_encoded modules. - */ - public function ajaxGetSonModules($moduleID, $rootID = 0) - { - if($moduleID) die(json_encode($this->dao->findByParent($moduleID)->from(TABLE_MODULE)->fetchPairs('id', 'name'))); - $modules = $this->dao->select('id, name')->from(TABLE_MODULE) - ->where('root')->eq($rootID) - ->andWhere('parent')->eq('0') - ->andWhere('type')->eq('story') - ->fetchPairs(); - foreach($modules as $key => $name) $modules[$key] = str_replace(" "," ","$name"); - die(json_encode($modules)); - } -} + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +class tree extends control +{ + const NEW_CHILD_COUNT = 5; + + /** + * Module browse. + * + * @param int $rootID + * @param string $viewType story|bug|case|doc + * @param int $currentModuleID + * @access public + * @return void + */ + public function browse($rootID, $viewType, $currentModuleID = 0) + { + /* According to the type, set the module root and modules. */ + if(strpos('story|bug|case', $viewType) !== false) + { + $product = $this->loadModel('product')->getById($rootID); + $this->view->root = $product; + $this->view->productModules = $this->tree->getOptionMenu($rootID, 'story'); + } + /* The viewType is doc. */ + elseif(strpos($viewType, 'doc') !== false) + { + $this->loadModel('doc'); + if($rootID == 'product' or $rootID == 'project') + { + $viewType = $rootID . 'doc'; + $lib->id = $rootID; + $lib->name = $this->lang->doc->systemLibs[$rootID]; + $this->view->root = $lib; + } + else + { + $viewType = 'customdoc'; + $lib = $this->loadModel('doc')->getLibById($rootID); + $this->view->root = $lib; + } + } + + if($viewType == 'story') + { + $this->lang->set('menugroup.tree', 'product'); + $this->product->setMenu($this->product->getPairs(), $rootID, 'story'); + $this->lang->tree->menu = $this->lang->product->menu; + + $products = $this->product->getPairs(); + unset($products[$rootID]); + $currentProduct = key($products); + + $this->view->allProduct = $products; + $this->view->currentProduct = $currentProduct; + $this->view->productModules = $this->tree->getOptionMenu($currentProduct, 'story'); + + $header['title'] = $this->lang->tree->manageProduct . $this->lang->colon . $product->name; + $position[] = html::a($this->createLink('product', 'browse', "product=$rootID"), $product->name); + $position[] = $this->lang->tree->manageProduct; + } + elseif($viewType == 'bug') + { + $this->loadModel('bug')->setMenu($this->product->getPairs(), $rootID); + $this->lang->tree->menu = $this->lang->bug->menu; + $this->lang->set('menugroup.tree', 'qa'); + + $header['title'] = $this->lang->tree->manageBug . $this->lang->colon . $product->name; + $position[] = html::a($this->createLink('bug', 'browse', "product=$rootID"), $product->name); + $position[] = $this->lang->tree->manageBug; + } + elseif($viewType == 'case') + { + $this->loadModel('testcase')->setMenu($this->product->getPairs(), $rootID); + $this->lang->tree->menu = $this->lang->testcase->menu; + $this->lang->set('menugroup.tree', 'qa'); + + $header['title'] = $this->lang->tree->manageCase . $this->lang->colon . $product->name; + $position[] = html::a($this->createLink('testcase', 'browse', "product=$rootID"), $product->name); + $position[] = $this->lang->tree->manageCase; + } + elseif(strpos($viewType, 'doc') !== false) + { + $this->doc->setMenu($this->doc->getLibs(), $rootID, 'doc'); + $this->lang->tree->menu = $this->lang->doc->menu; + $this->lang->set('menugroup.tree', 'doc'); + + $header['title'] = $this->lang->tree->manageCustomDoc . $this->lang->colon . $lib->name; + $position[] = html::a($this->createLink('doc', 'browse', "libID=$rootID"), $lib->name); + $position[] = $this->lang->tree->manageCustomDoc; + } + + $parentModules = $this->tree->getParents($currentModuleID); + $this->view->header = $header; + $this->view->position = $position; + $this->view->rootID = $rootID; + $this->view->viewType = $viewType; + $this->view->modules = $this->tree->getTreeMenu($rootID, $viewType, $rooteModuleID = 0, array('treeModel', 'createManageLink')); + $this->view->sons = $this->tree->getSons($rootID, $currentModuleID, $viewType); + $this->view->currentModuleID = $currentModuleID; + $this->view->parentModules = $parentModules; + $this->display(); + } + + /** + * Edit a module. + * + * @param int $moduleID + * @access public + * @return void + */ + public function edit($moduleID) + { + if(!empty($_POST)) + { + $this->tree->update($moduleID); + echo js::alert($this->lang->tree->successSave); + die(js::reload('parent')); + } + $module = $this->tree->getById($moduleID); + if($module->owner == null) + { + $module->owner = $this->loadModel('product')->getById($module->root)->QM; + } + $this->view->module = $module; + $this->view->optionMenu = $this->tree->getOptionMenu($this->view->module->root, $this->view->module->type); + $this->view->users = $this->loadModel('user')->getPairs('noclosed'); + + /* Remove self and childs from the $optionMenu. Because it's parent can't be self or childs. */ + $childs = $this->tree->getAllChildId($moduleID); + foreach($childs as $childModuleID) unset($this->view->optionMenu[$childModuleID]); + + die($this->display()); + } + + /** + * Update modules' orders. + * + * @access public + * @return void + */ + public function updateOrder() + { + if(!empty($_POST)) + { + $this->tree->updateOrder($_POST['orders']); + die(js::reload('parent')); + } + } + + /** + * Manage child modules. + * + * @param int $rootID + * @param string $viewType + * @access public + * @return void + */ + public function manageChild($rootID, $viewType) + { + if(!empty($_POST)) + { + $this->tree->manageChild($rootID, $viewType, $_POST['parentModuleID'], $_POST['modules']); + die(js::reload('parent')); + } + } + + /** + * Delete a module. + * + * @param int $rootID + * @param int $moduleID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($rootID, $moduleID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->tree->confirmDelete, $this->createLink('tree', 'delete', "rootID=$rootID&moduleID=$moduleID&confirm=yes")); + exit; + } + else + { + $this->tree->delete($moduleID); + die(js::reload('parent')); + } + } + + /** + * AJAX: Get the option menu of modules. + * + * @param int $rootID + * @param string $viewType + * @param int $rootModuleID + * @access public + * @return string the html select string. + */ + public function ajaxGetOptionMenu($rootID, $viewType = 'story', $rootModuleID = 0, $returnType = 'html') + { + + $this->view->productModules = $this->tree->getOptionMenu($rootID, 'story'); + $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID); + if($returnType == 'html') die( html::select("module", $optionMenu, '', 'onchange=setAssignedTo()')); + if($returnType == 'json') die(json_encode($optionMenu)); + } + + /** + * AJAX: get a module's son modules. + * + * @param int $moduleID + * @param int $rootID + * @access public + * @return string json_encoded modules. + */ + public function ajaxGetSonModules($moduleID, $rootID = 0) + { + if($moduleID) die(json_encode($this->dao->findByParent($moduleID)->from(TABLE_MODULE)->fetchPairs('id', 'name'))); + $modules = $this->dao->select('id, name')->from(TABLE_MODULE) + ->where('root')->eq($rootID) + ->andWhere('parent')->eq('0') + ->andWhere('type')->eq('story') + ->fetchPairs(); + foreach($modules as $key => $name) $modules[$key] = str_replace(" "," ","$name"); + die(json_encode($modules)); + } +} diff --git a/module/tree/lang/en.php b/module/tree/lang/en.php index 835573905f..5afbb34f4a 100644 --- a/module/tree/lang/en.php +++ b/module/tree/lang/en.php @@ -1,40 +1,40 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->tree->common = 'Module manage'; -$lang->tree->add = 'Add'; -$lang->tree->edit = 'Edit'; -$lang->tree->addChild = 'Add child'; -$lang->tree->delete = 'Delete'; -$lang->tree->browse = 'Module manage'; -$lang->tree->manage = 'Manage'; -$lang->tree->docManage = 'Type'; -$lang->tree->manageProduct = 'Mange product module'; -$lang->tree->manageProject = 'Manage project module'; -$lang->tree->manageBug = 'Manage bug module'; -$lang->tree->manageCase = 'Manage case module'; -$lang->tree->manageCustomDoc = 'Manage doc library type'; -$lang->tree->updateOrder = 'Update order'; -$lang->tree->manageChild = 'Manage child'; -$lang->tree->manageDocChild = 'Manage child type'; -$lang->tree->syncFromProduct = 'Copy from product module'; -$lang->tree->ajaxGetOptionMenu = 'API: Get select menu'; -$lang->tree->ajaxGetSonModules = 'API: Get son modules'; - -$lang->tree->confirmDelete = 'Are you sure to delete this module?'; -$lang->tree->successSave = 'Success saved'; - -$lang->tree->name = 'Name'; -$lang->tree->parent = 'Parent'; -$lang->tree->child = 'Child'; -$lang->tree->owner = 'Owner'; -$lang->tree->order = 'Order'; -$lang->tree->projectDoc = 'Project doc'; + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->tree->common = 'Module manage'; +$lang->tree->add = 'Add'; +$lang->tree->edit = 'Edit'; +$lang->tree->addChild = 'Add child'; +$lang->tree->delete = 'Delete'; +$lang->tree->browse = 'Module manage'; +$lang->tree->manage = 'Manage'; +$lang->tree->docManage = 'Type'; +$lang->tree->manageProduct = 'Mange product module'; +$lang->tree->manageProject = 'Manage project module'; +$lang->tree->manageBug = 'Manage bug module'; +$lang->tree->manageCase = 'Manage case module'; +$lang->tree->manageCustomDoc = 'Manage doc library type'; +$lang->tree->updateOrder = 'Update order'; +$lang->tree->manageChild = 'Manage child'; +$lang->tree->manageDocChild = 'Manage child type'; +$lang->tree->syncFromProduct = 'Copy from product module'; +$lang->tree->ajaxGetOptionMenu = 'API: Get select menu'; +$lang->tree->ajaxGetSonModules = 'API: Get son modules'; + +$lang->tree->confirmDelete = 'Are you sure to delete this module?'; +$lang->tree->successSave = 'Success saved'; + +$lang->tree->name = 'Name'; +$lang->tree->parent = 'Parent'; +$lang->tree->child = 'Child'; +$lang->tree->owner = 'Owner'; +$lang->tree->order = 'Order'; +$lang->tree->projectDoc = 'Project doc'; diff --git a/module/tree/lang/zh-cn.php b/module/tree/lang/zh-cn.php index 03d4c0e6fc..f8e34e59c2 100644 --- a/module/tree/lang/zh-cn.php +++ b/module/tree/lang/zh-cn.php @@ -1,40 +1,40 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->tree->common = '模块维护'; -$lang->tree->add = '添加'; -$lang->tree->edit = '编辑'; -$lang->tree->addChild = '添加子模块'; -$lang->tree->delete = '删除模块'; -$lang->tree->browse = '模块维护'; -$lang->tree->manage = '维护模块'; -$lang->tree->docManage = '分类'; -$lang->tree->manageProduct = '维护产品视图模块'; -$lang->tree->manageProject = '维护项目视图模块'; -$lang->tree->manageBug = '维护测试视图模块'; -$lang->tree->manageCase = '维护用例视图模块'; -$lang->tree->manageCustomDoc = '维护文档库分类'; -$lang->tree->updateOrder = '更新排序'; -$lang->tree->manageChild = '维护子模块'; -$lang->tree->manageDocChild = '维护分类'; -$lang->tree->syncFromProduct = '复制产品视图模块'; -$lang->tree->ajaxGetOptionMenu = '接口:获取下拉列表'; -$lang->tree->ajaxGetSonModules = '接口:获得子菜单列表'; - -$lang->tree->confirmDelete = '您确定删除该模块吗?'; -$lang->tree->successSave = '成功保存'; - -$lang->tree->name = '模块名称'; -$lang->tree->parent = '上级模块'; -$lang->tree->child = '子模块'; -$lang->tree->owner = '负责人'; -$lang->tree->order = '排序'; -$lang->tree->projectDoc = '项目文档'; + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->tree->common = '模块维护'; +$lang->tree->add = '添加'; +$lang->tree->edit = '编辑'; +$lang->tree->addChild = '添加子模块'; +$lang->tree->delete = '删除模块'; +$lang->tree->browse = '模块维护'; +$lang->tree->manage = '维护模块'; +$lang->tree->docManage = '分类'; +$lang->tree->manageProduct = '维护产品视图模块'; +$lang->tree->manageProject = '维护项目视图模块'; +$lang->tree->manageBug = '维护测试视图模块'; +$lang->tree->manageCase = '维护用例视图模块'; +$lang->tree->manageCustomDoc = '维护文档库分类'; +$lang->tree->updateOrder = '更新排序'; +$lang->tree->manageChild = '维护子模块'; +$lang->tree->manageDocChild = '维护分类'; +$lang->tree->syncFromProduct = '复制产品视图模块'; +$lang->tree->ajaxGetOptionMenu = '接口:获取下拉列表'; +$lang->tree->ajaxGetSonModules = '接口:获得子菜单列表'; + +$lang->tree->confirmDelete = '您确定删除该模块吗?'; +$lang->tree->successSave = '成功保存'; + +$lang->tree->name = '模块名称'; +$lang->tree->parent = '上级模块'; +$lang->tree->child = '子模块'; +$lang->tree->owner = '负责人'; +$lang->tree->order = '排序'; +$lang->tree->projectDoc = '项目文档'; diff --git a/module/tree/lang/zh-tw.php b/module/tree/lang/zh-tw.php index 8895f07c48..ccbcce80bb 100644 --- a/module/tree/lang/zh-tw.php +++ b/module/tree/lang/zh-tw.php @@ -1,38 +1,38 @@ - - * @package tree - * @version $Id: zh-tw.php 2007 2011-07-03 08:18:16Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->tree->common = '模組維護'; -$lang->tree->add = '添加'; -$lang->tree->edit = '編輯'; -$lang->tree->addChild = '添加子模組'; -$lang->tree->delete = '刪除模組'; -$lang->tree->browse = '模組維護'; -$lang->tree->manage = '維護模組'; -$lang->tree->manageProduct = '維護產品視圖模組'; -$lang->tree->manageProject = '維護項目視圖模組'; -$lang->tree->manageBug = '維護測試視圖模組'; -$lang->tree->manageCase = '維護用例視圖模組'; -$lang->tree->manageCustomDoc = '維護文檔庫模組'; -$lang->tree->updateOrder = '更新排序'; -$lang->tree->manageChild = '維護子模組'; -$lang->tree->syncFromProduct = '複製產品視圖模組'; -$lang->tree->ajaxGetOptionMenu = '介面:獲取下拉列表'; -$lang->tree->ajaxGetSonModules = '介面:獲得子菜單列表'; - -$lang->tree->confirmDelete = '您確定刪除該模組嗎?'; -$lang->tree->successSave = '成功保存'; - -$lang->tree->name = '模組名稱'; -$lang->tree->parent = '上級模組'; -$lang->tree->child = '子模組'; -$lang->tree->owner = '負責人'; -$lang->tree->order = '排序'; -$lang->tree->projectDoc = '項目文檔'; + + * @package tree + * @version $Id: zh-tw.php 2007 2011-07-03 08:18:16Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->tree->common = '模組維護'; +$lang->tree->add = '添加'; +$lang->tree->edit = '編輯'; +$lang->tree->addChild = '添加子模組'; +$lang->tree->delete = '刪除模組'; +$lang->tree->browse = '模組維護'; +$lang->tree->manage = '維護模組'; +$lang->tree->manageProduct = '維護產品視圖模組'; +$lang->tree->manageProject = '維護項目視圖模組'; +$lang->tree->manageBug = '維護測試視圖模組'; +$lang->tree->manageCase = '維護用例視圖模組'; +$lang->tree->manageCustomDoc = '維護文檔庫模組'; +$lang->tree->updateOrder = '更新排序'; +$lang->tree->manageChild = '維護子模組'; +$lang->tree->syncFromProduct = '複製產品視圖模組'; +$lang->tree->ajaxGetOptionMenu = '介面:獲取下拉列表'; +$lang->tree->ajaxGetSonModules = '介面:獲得子菜單列表'; + +$lang->tree->confirmDelete = '您確定刪除該模組嗎?'; +$lang->tree->successSave = '成功保存'; + +$lang->tree->name = '模組名稱'; +$lang->tree->parent = '上級模組'; +$lang->tree->child = '子模組'; +$lang->tree->owner = '負責人'; +$lang->tree->order = '排序'; +$lang->tree->projectDoc = '項目文檔'; diff --git a/module/tree/model.php b/module/tree/model.php index 777c7a9a81..351a205d72 100644 --- a/module/tree/model.php +++ b/module/tree/model.php @@ -1,547 +1,547 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findById((int)$moduleID)->from(TABLE_MODULE)->fetch(); - } - - /** - * Build the sql query. - * - * @param int $rootID - * @param string $type - * @param int $startModule - * @access private - * @return void - */ - private function buildMenuQuery($rootID, $type, $startModule) - { - /* Set the start module. */ - $startModulePath = ''; - if($startModule > 0) - { - $startModule = $this->getById($startModule); - if($startModule) $startModulePath = $startModule->path . '%'; - } - - return $this->dao->select('*')->from(TABLE_MODULE) - ->where('root')->eq((int)$rootID) - ->andWhere('type')->eq($type) - ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi() - ->orderBy('grade desc, `order`') - ->get(); - } - - /** - * Create an option menu in html. - * - * @param int $rootID - * @param string $type - * @param int $startModule - * @access public - * @return string - */ - public function getOptionMenu($rootID, $type = 'story', $startModule = 0) - { - $treeMenu = array(); - $stmt = $this->dbh->query($this->buildMenuQuery($rootID, $type, $startModule)); - $modules = array(); - while($module = $stmt->fetch()) $modules[$module->id] = $module; - - foreach($modules as $module) - { - $parentModules = explode(',', $module->path); - $moduleName = '/'; - foreach($parentModules as $parentModuleID) - { - if(empty($parentModuleID)) continue; - $moduleName .= $modules[$parentModuleID]->name . '/'; - } - $moduleName = rtrim($moduleName, '/'); - $moduleName .= "|$module->id\n"; - - if(isset($treeMenu[$module->id]) and !empty($treeMenu[$module->id])) - { - if(isset($treeMenu[$module->parent])) - { - $treeMenu[$module->parent] .= $moduleName; - } - else - { - $treeMenu[$module->parent] = $moduleName;; - } - $treeMenu[$module->parent] .= $treeMenu[$module->id]; - } - else - { - if(isset($treeMenu[$module->parent]) and !empty($treeMenu[$module->parent])) - { - $treeMenu[$module->parent] .= $moduleName; - } - else - { - $treeMenu[$module->parent] = $moduleName; - } - } - } - - $topMenu = @array_pop($treeMenu); - $topMenu = explode("\n", trim($topMenu)); - $lastMenu[] = '/'; - foreach($topMenu as $menu) - { - if(!strpos($menu, '|')) continue; - list($label, $moduleID) = explode('|', $menu); - $lastMenu[$moduleID] = $label; - } - return $lastMenu; - } - - /** - * Get the tree menu in html. - * - * @param int $rootID - * @param string $type - * @param int $startModule - * @param string $userFunc the function used to create link - * @param string $extra extra params - * @access public - * @return string - */ - public function getTreeMenu($rootID, $type = 'root', $startModule = 0, $userFunc, $extra = '') - { - $treeMenu = array(); - $stmt = $this->dbh->query($this->buildMenuQuery($rootID, $type, $startModule)); - while($module = $stmt->fetch()) - { - $linkHtml = call_user_func($userFunc, $module, $extra); - - if(isset($treeMenu[$module->id]) and !empty($treeMenu[$module->id])) - { - if(!isset($treeMenu[$module->parent])) $treeMenu[$module->parent] = ''; - $treeMenu[$module->parent] .= "
        • $linkHtml"; - $treeMenu[$module->parent] .= "
            ".$treeMenu[$module->id]."
          \n"; - } - else - { - if(isset($treeMenu[$module->parent]) and !empty($treeMenu[$module->parent])) - { - $treeMenu[$module->parent] .= "
        • $linkHtml\n"; - } - else - { - $treeMenu[$module->parent] = "
        • $linkHtml\n"; - } - } - $treeMenu[$module->parent] .= "
        • \n"; - } - - $lastMenu = "
            " . @array_pop($treeMenu) . "
          \n"; - return $lastMenu; - } - - /** - * Get the tree menu of product document library. - * - * @access public - * @return string - */ - public function getProductDocTreeMenu() - { - $menu = "
            "; - $products = $this->loadModel('product')->getPairs('nocode'); - $modules = $this->dao->findByType('productdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); - $projectModules = $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); - - foreach($products as $productID =>$productName) - { - $menu .= '
          • '; - $menu .= html::a(helper::createLink('doc', 'browse', "libID=product&module=0&productID=$productID"), $productName); - if($modules) - { - $menu .= '
              '; - foreach($modules as $module) - { - $menu .= '
            • ' . html::a(helper::createLink('doc', 'browse', "libID=product&module=$module->id&productID=$productID"), $module->name) . '
            • '; - } - - /* If $projectModules not emtpy, append the project modules. */ - if($projectModules) - { - $menu .= '
            • '; - $menu .= html::a(helper::createLink('doc', 'browse', "libID=product&module=0&productID=$productID&projectID=int"), $this->lang->tree->projectDoc); - $menu .= '
                '; - foreach($projectModules as $module) - { - $menu .= '
              • ' . html::a(helper::createLink('doc', 'browse', "libID=product&module=$module->id&productID=$productID"), $module->name) . '
              • '; - } - $menu .= '
            • '; - } - - $menu .= '
            '; - } - } - - $menu .= '
          • '; - return $menu; - } - - /** - * Get the tree menu of project document library. - * - * @access public - * @return void - */ - public function getProjectDocTreeMenu() - { - $menu = "
              "; - $products = $this->loadModel('product')->getPairs('nocode'); - $projects = $this->loadModel('project')->getProductGroupList(); - $modules = $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); - $products[0] = $this->lang->project->noProduct; - foreach($projects as $id => $project) - { - if($id == '') - { - $projects[0] = $projects['']; - unset($projects['']); - } - } - - foreach($products as $productID => $productName) - { - $menu .= '
            • '; - $menu .= $productName; - - if(isset($projects[$productID])) - { - $menu .= '
                '; - foreach($projects[$productID] as $project) - { - $menu .= '
              • ' . html::a(helper::createLink('doc', 'browse', "libID=project&module=0&productID=0&projectID=$project->id"), $project->name); - if($modules) - { - $menu .= '
                  '; - foreach($modules as $module) - { - $menu .= '
                • ' . html::a(helper::createLink('doc', 'browse', "libID=project&module=$module->id&productID=0&projectID=$project->id"), $module->name) . '
                • '; - } - $menu .= '
                '; - } - $menu .= '
              • '; - } - $menu .='
              '; - } - $menu .='
            • '; - } - - $menu .= '
            '; - return $menu; - } - - /** - * Create link of a story. - * - * @param object $module - * @access private - * @return string - */ - private function createStoryLink($module) - { - $linkHtml = html::a(helper::createLink('product', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); - return $linkHtml; - } - - /** - * Create link of a doc. - * - * @param object $module - * @access private - * @return string - */ - private function createDocLink($module) - { - $linkHtml = html::a(helper::createLink('doc', 'browse', "libID={$module->root}&&module={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); - return $linkHtml; - } - - /** - * Create the manage link of a module. - * - * @param object $module - * @access private - * @return string - */ - private function createManageLink($module) - { - static $users; - if(empty($users)) $users = $this->loadModel('user')->getPairs('noletter'); - $linkHtml = $module->name; - if($module->type == 'bug' and $module->owner) $linkHtml .= '[' . $users[$module->owner] . ']'; - if(common::hasPriv('tree', 'edit')) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'edit', "module={$module->id}"), $this->lang->tree->edit, '', 'class="iframe"'); - if(common::hasPriv('tree', 'browse') and strpos('productdoc,projectdoc', $module->type) === false) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'browse', "root={$module->root}&type={$module->type}&module={$module->id}"), $this->lang->tree->child); - if(common::hasPriv('tree', 'delete')) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'delete', "root={$module->root}&module={$module->id}"), $this->lang->delete, 'hiddenwin'); - if(common::hasPriv('tree', 'updateorder')) $linkHtml .= ' ' . html::input("orders[$module->id]", $module->order, 'style="width:30px;text-align:center"'); - return $linkHtml; - } - - /** - * Create link of a bug. - * - * @param object $module - * @access private - * @return string - */ - private function createBugLink($module) - { - $linkHtml = html::a(helper::createLink('bug', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); - return $linkHtml; - } - - /** - * Create link of a test case. - * - * @param object $module - * @access private - * @return string - */ - private function createCaseLink($module) - { - $linkHtml = html::a(helper::createLink('testcase', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); - return $linkHtml; - } - - /** - * Create link of a test task. - * - * @param object $module - * @access private - * @return string - */ - private function createTestTaskLink($module, $extra) - { - $linkHtml = html::a(helper::createLink('testtask', 'cases', "taskID=$extra&type=byModule&module={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); - return $linkHtml; - } - - /** - * Get sons of a module. - * - * @param int $rootID - * @param int $moduleID - * @param string $type - * @access public - * @return array - */ - public function getSons($rootID, $moduleID, $type = 'root') - { - return $this->dao->select('*')->from(TABLE_MODULE) - ->where('root')->eq((int)$rootID) - ->andWhere('parent')->eq((int)$moduleID) - ->andWhere('type')->eq($type) - ->orderBy('`order`') - ->fetchAll(); - } - - /** - * Get id list of a module's childs. - * - * @param int $moduleID - * @access public - * @return array - */ - public function getAllChildId($moduleID) - { - if($moduleID == 0) return array(); - $module = $this->getById((int)$moduleID); - return $this->dao->select('id')->from(TABLE_MODULE)->where('path')->like($module->path . '%')->fetchPairs(); - } - - /** - * Get parents of a module. - * - * @param int $moduleID - * @access public - * @return array - */ - public function getParents($moduleID) - { - if($moduleID == 0) return array(); - $path = $this->dao->select('path')->from(TABLE_MODULE)->where('id')->eq((int)$moduleID)->fetch('path'); - $path = trim($path, ','); - if(!$path) return array(); - return $this->dao->select('*')->from(TABLE_MODULE)->where('id')->in($path)->orderBy('grade')->fetchAll(); - } - - /** - * Update modules' order. - * - * @param array $orders - * @access public - * @return void - */ - public function updateOrder($orders) - { - foreach($orders as $moduleID => $order) - { - $this->dao->update(TABLE_MODULE)->set('`order`')->eq($order)->where('id')->eq((int)$moduleID)->limit(1)->exec(); - } - } - - /** - * Manage childs of a module. - * - * @param int $rootID - * @param string $type - * @param int $parentModuleID - * @param array $childs - * @access public - * @return void - */ - public function manageChild($rootID, $type, $parentModuleID, $childs) - { - $parentModule = $this->getByID($parentModuleID); - if($parentModule) - { - $grade = $parentModule->grade + 1; - $parentPath = $parentModule->path; - } - else - { - $grade = 1; - $parentPath = ','; - } - $i = 1; - foreach($childs as $moduleID => $moduleName) - { - if(empty($moduleName)) continue; - - /* The new modules. */ - if(is_numeric($moduleID)) - { - $module->root = $rootID; - $module->name = strip_tags($moduleName); - $module->parent = $parentModuleID; - $module->grade = $grade; - $module->type = $type; - $module->order = $this->post->maxOrder + $i * 10; - $this->dao->insert(TABLE_MODULE)->data($module)->exec(); - $moduleID = $this->dao->lastInsertID(); - $childPath = $parentPath . "$moduleID,"; - $this->dao->update(TABLE_MODULE)->set('path')->eq($childPath)->where('id')->eq($moduleID)->limit(1)->exec(); - $i ++; - } - else - { - $moduleID = str_replace('id', '', $moduleID); - $this->dao->update(TABLE_MODULE)->set('name')->eq(strip_tags($moduleName))->where('id')->eq($moduleID)->limit(1)->exec(); - } - } - } - - /** - * Update a module. - * - * @param int $moduleID - * @access public - * @return void - */ - public function update($moduleID) - { - $module = fixer::input('post')->specialChars('name')->get(); - $self = $this->getById($moduleID); - $parent = $this->getById($this->post->parent); - $childs = $this->getAllChildId($moduleID); - $module->grade = $parent ? $parent->grade + 1 : 1; - $this->dao->update(TABLE_MODULE)->data($module)->autoCheck()->check('name', 'notempty')->where('id')->eq($moduleID)->exec(); - $this->dao->update(TABLE_MODULE)->set('grade = grade + 1')->where('id')->in($childs)->andWhere('id')->ne($moduleID)->exec(); - $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq('')->exec(); - $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq($self->owner)->exec(); - $this->fixModulePath(); - } - - /** - * Delete a module. - * - * @param int $moduleID - * @access public - * @return void - */ - public function delete($moduleID) - { - $module = $this->getById($moduleID); - $childs = $this->getAllChildId($moduleID); - - $this->dao->update(TABLE_MODULE)->set('grade = grade - 1')->where('id')->in($childs)->exec(); // Update grade of all childs. - $this->dao->update(TABLE_MODULE)->set('parent')->eq($module->parent)->where('parent')->eq($moduleID)->exec(); // Update the parent of sons to my parent. - $this->dao->delete()->from(TABLE_MODULE)->where('id')->eq($moduleID)->exec(); // Delete my self. - $this->fixModulePath(); - - if($module->type == 'story') $this->dao->update(TABLE_STORY)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); - if($module->type == 'bug') $this->dao->update(TABLE_BUG)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); - if($module->type == 'case') $this->dao->update(TABLE_CASE)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); - } - - /** - * Fix fieilds of all module, grade, parent, pathes and so on. - * - * @access public - * @return void - */ - public function fixModulePath() - { - /* Get the max grade. */ - $maxGrade = $this->dao->select('MAX(grade) AS grade')->from(TABLE_MODULE)->fetch('grade'); - $modules = array(); - - /* Cycle ervery grade. */ - for($grade = 1; $grade <= $maxGrade; $grade ++) - { - /* Modules of current grade. */ - $gradeModules = $this->dao->select('id, parent, grade')->from(TABLE_MODULE)->where('grade')->eq($grade)->fetchAll('id'); - foreach($gradeModules as $moduleID => $module) - { - if($grade == 1) - { - $module->path = ",$moduleID,"; - } - else - { - /* Get the parent module to compute path and grade of my self. */ - if(isset($modules[$module->parent])) - { - $module->path = $modules[$module->parent]->path . "$moduleID,"; - $module->grade = $modules[$module->parent]->grade + 1; - } - } - } - $modules += $gradeModules; - } - - /* Save modules to database. */ - foreach($modules as $moduleID => $module) - { - $this->dao->update(TABLE_MODULE)->data($module)->where('id')->eq($module->id)->limit(1)->exec(); - } - } -} + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +?> +dao->findById((int)$moduleID)->from(TABLE_MODULE)->fetch(); + } + + /** + * Build the sql query. + * + * @param int $rootID + * @param string $type + * @param int $startModule + * @access private + * @return void + */ + private function buildMenuQuery($rootID, $type, $startModule) + { + /* Set the start module. */ + $startModulePath = ''; + if($startModule > 0) + { + $startModule = $this->getById($startModule); + if($startModule) $startModulePath = $startModule->path . '%'; + } + + return $this->dao->select('*')->from(TABLE_MODULE) + ->where('root')->eq((int)$rootID) + ->andWhere('type')->eq($type) + ->beginIF($startModulePath)->andWhere('path')->like($startModulePath)->fi() + ->orderBy('grade desc, `order`') + ->get(); + } + + /** + * Create an option menu in html. + * + * @param int $rootID + * @param string $type + * @param int $startModule + * @access public + * @return string + */ + public function getOptionMenu($rootID, $type = 'story', $startModule = 0) + { + $treeMenu = array(); + $stmt = $this->dbh->query($this->buildMenuQuery($rootID, $type, $startModule)); + $modules = array(); + while($module = $stmt->fetch()) $modules[$module->id] = $module; + + foreach($modules as $module) + { + $parentModules = explode(',', $module->path); + $moduleName = '/'; + foreach($parentModules as $parentModuleID) + { + if(empty($parentModuleID)) continue; + $moduleName .= $modules[$parentModuleID]->name . '/'; + } + $moduleName = rtrim($moduleName, '/'); + $moduleName .= "|$module->id\n"; + + if(isset($treeMenu[$module->id]) and !empty($treeMenu[$module->id])) + { + if(isset($treeMenu[$module->parent])) + { + $treeMenu[$module->parent] .= $moduleName; + } + else + { + $treeMenu[$module->parent] = $moduleName;; + } + $treeMenu[$module->parent] .= $treeMenu[$module->id]; + } + else + { + if(isset($treeMenu[$module->parent]) and !empty($treeMenu[$module->parent])) + { + $treeMenu[$module->parent] .= $moduleName; + } + else + { + $treeMenu[$module->parent] = $moduleName; + } + } + } + + $topMenu = @array_pop($treeMenu); + $topMenu = explode("\n", trim($topMenu)); + $lastMenu[] = '/'; + foreach($topMenu as $menu) + { + if(!strpos($menu, '|')) continue; + list($label, $moduleID) = explode('|', $menu); + $lastMenu[$moduleID] = $label; + } + return $lastMenu; + } + + /** + * Get the tree menu in html. + * + * @param int $rootID + * @param string $type + * @param int $startModule + * @param string $userFunc the function used to create link + * @param string $extra extra params + * @access public + * @return string + */ + public function getTreeMenu($rootID, $type = 'root', $startModule = 0, $userFunc, $extra = '') + { + $treeMenu = array(); + $stmt = $this->dbh->query($this->buildMenuQuery($rootID, $type, $startModule)); + while($module = $stmt->fetch()) + { + $linkHtml = call_user_func($userFunc, $module, $extra); + + if(isset($treeMenu[$module->id]) and !empty($treeMenu[$module->id])) + { + if(!isset($treeMenu[$module->parent])) $treeMenu[$module->parent] = ''; + $treeMenu[$module->parent] .= "
          • $linkHtml"; + $treeMenu[$module->parent] .= "
              ".$treeMenu[$module->id]."
            \n"; + } + else + { + if(isset($treeMenu[$module->parent]) and !empty($treeMenu[$module->parent])) + { + $treeMenu[$module->parent] .= "
          • $linkHtml\n"; + } + else + { + $treeMenu[$module->parent] = "
          • $linkHtml\n"; + } + } + $treeMenu[$module->parent] .= "
          • \n"; + } + + $lastMenu = "
              " . @array_pop($treeMenu) . "
            \n"; + return $lastMenu; + } + + /** + * Get the tree menu of product document library. + * + * @access public + * @return string + */ + public function getProductDocTreeMenu() + { + $menu = "
              "; + $products = $this->loadModel('product')->getPairs('nocode'); + $modules = $this->dao->findByType('productdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); + $projectModules = $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); + + foreach($products as $productID =>$productName) + { + $menu .= '
            • '; + $menu .= html::a(helper::createLink('doc', 'browse', "libID=product&module=0&productID=$productID"), $productName); + if($modules) + { + $menu .= '
                '; + foreach($modules as $module) + { + $menu .= '
              • ' . html::a(helper::createLink('doc', 'browse', "libID=product&module=$module->id&productID=$productID"), $module->name) . '
              • '; + } + + /* If $projectModules not emtpy, append the project modules. */ + if($projectModules) + { + $menu .= '
              • '; + $menu .= html::a(helper::createLink('doc', 'browse', "libID=product&module=0&productID=$productID&projectID=int"), $this->lang->tree->projectDoc); + $menu .= '
                  '; + foreach($projectModules as $module) + { + $menu .= '
                • ' . html::a(helper::createLink('doc', 'browse', "libID=product&module=$module->id&productID=$productID"), $module->name) . '
                • '; + } + $menu .= '
              • '; + } + + $menu .= '
              '; + } + } + + $menu .= '
            • '; + return $menu; + } + + /** + * Get the tree menu of project document library. + * + * @access public + * @return void + */ + public function getProjectDocTreeMenu() + { + $menu = "
                "; + $products = $this->loadModel('product')->getPairs('nocode'); + $projects = $this->loadModel('project')->getProductGroupList(); + $modules = $this->dao->findByType('projectdoc')->from(TABLE_MODULE)->orderBy('`order`')->fetchAll(); + $products[0] = $this->lang->project->noProduct; + foreach($projects as $id => $project) + { + if($id == '') + { + $projects[0] = $projects['']; + unset($projects['']); + } + } + + foreach($products as $productID => $productName) + { + $menu .= '
              • '; + $menu .= $productName; + + if(isset($projects[$productID])) + { + $menu .= '
                  '; + foreach($projects[$productID] as $project) + { + $menu .= '
                • ' . html::a(helper::createLink('doc', 'browse', "libID=project&module=0&productID=0&projectID=$project->id"), $project->name); + if($modules) + { + $menu .= '
                    '; + foreach($modules as $module) + { + $menu .= '
                  • ' . html::a(helper::createLink('doc', 'browse', "libID=project&module=$module->id&productID=0&projectID=$project->id"), $module->name) . '
                  • '; + } + $menu .= '
                  '; + } + $menu .= '
                • '; + } + $menu .='
                '; + } + $menu .='
              • '; + } + + $menu .= '
              '; + return $menu; + } + + /** + * Create link of a story. + * + * @param object $module + * @access private + * @return string + */ + private function createStoryLink($module) + { + $linkHtml = html::a(helper::createLink('product', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); + return $linkHtml; + } + + /** + * Create link of a doc. + * + * @param object $module + * @access private + * @return string + */ + private function createDocLink($module) + { + $linkHtml = html::a(helper::createLink('doc', 'browse', "libID={$module->root}&&module={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); + return $linkHtml; + } + + /** + * Create the manage link of a module. + * + * @param object $module + * @access private + * @return string + */ + private function createManageLink($module) + { + static $users; + if(empty($users)) $users = $this->loadModel('user')->getPairs('noletter'); + $linkHtml = $module->name; + if($module->type == 'bug' and $module->owner) $linkHtml .= '[' . $users[$module->owner] . ']'; + if(common::hasPriv('tree', 'edit')) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'edit', "module={$module->id}"), $this->lang->tree->edit, '', 'class="iframe"'); + if(common::hasPriv('tree', 'browse') and strpos('productdoc,projectdoc', $module->type) === false) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'browse', "root={$module->root}&type={$module->type}&module={$module->id}"), $this->lang->tree->child); + if(common::hasPriv('tree', 'delete')) $linkHtml .= ' ' . html::a(helper::createLink('tree', 'delete', "root={$module->root}&module={$module->id}"), $this->lang->delete, 'hiddenwin'); + if(common::hasPriv('tree', 'updateorder')) $linkHtml .= ' ' . html::input("orders[$module->id]", $module->order, 'style="width:30px;text-align:center"'); + return $linkHtml; + } + + /** + * Create link of a bug. + * + * @param object $module + * @access private + * @return string + */ + private function createBugLink($module) + { + $linkHtml = html::a(helper::createLink('bug', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); + return $linkHtml; + } + + /** + * Create link of a test case. + * + * @param object $module + * @access private + * @return string + */ + private function createCaseLink($module) + { + $linkHtml = html::a(helper::createLink('testcase', 'browse', "root={$module->root}&type=byModule¶m={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); + return $linkHtml; + } + + /** + * Create link of a test task. + * + * @param object $module + * @access private + * @return string + */ + private function createTestTaskLink($module, $extra) + { + $linkHtml = html::a(helper::createLink('testtask', 'cases', "taskID=$extra&type=byModule&module={$module->id}"), $module->name, '_self', "id='module{$module->id}'"); + return $linkHtml; + } + + /** + * Get sons of a module. + * + * @param int $rootID + * @param int $moduleID + * @param string $type + * @access public + * @return array + */ + public function getSons($rootID, $moduleID, $type = 'root') + { + return $this->dao->select('*')->from(TABLE_MODULE) + ->where('root')->eq((int)$rootID) + ->andWhere('parent')->eq((int)$moduleID) + ->andWhere('type')->eq($type) + ->orderBy('`order`') + ->fetchAll(); + } + + /** + * Get id list of a module's childs. + * + * @param int $moduleID + * @access public + * @return array + */ + public function getAllChildId($moduleID) + { + if($moduleID == 0) return array(); + $module = $this->getById((int)$moduleID); + return $this->dao->select('id')->from(TABLE_MODULE)->where('path')->like($module->path . '%')->fetchPairs(); + } + + /** + * Get parents of a module. + * + * @param int $moduleID + * @access public + * @return array + */ + public function getParents($moduleID) + { + if($moduleID == 0) return array(); + $path = $this->dao->select('path')->from(TABLE_MODULE)->where('id')->eq((int)$moduleID)->fetch('path'); + $path = trim($path, ','); + if(!$path) return array(); + return $this->dao->select('*')->from(TABLE_MODULE)->where('id')->in($path)->orderBy('grade')->fetchAll(); + } + + /** + * Update modules' order. + * + * @param array $orders + * @access public + * @return void + */ + public function updateOrder($orders) + { + foreach($orders as $moduleID => $order) + { + $this->dao->update(TABLE_MODULE)->set('`order`')->eq($order)->where('id')->eq((int)$moduleID)->limit(1)->exec(); + } + } + + /** + * Manage childs of a module. + * + * @param int $rootID + * @param string $type + * @param int $parentModuleID + * @param array $childs + * @access public + * @return void + */ + public function manageChild($rootID, $type, $parentModuleID, $childs) + { + $parentModule = $this->getByID($parentModuleID); + if($parentModule) + { + $grade = $parentModule->grade + 1; + $parentPath = $parentModule->path; + } + else + { + $grade = 1; + $parentPath = ','; + } + $i = 1; + foreach($childs as $moduleID => $moduleName) + { + if(empty($moduleName)) continue; + + /* The new modules. */ + if(is_numeric($moduleID)) + { + $module->root = $rootID; + $module->name = strip_tags($moduleName); + $module->parent = $parentModuleID; + $module->grade = $grade; + $module->type = $type; + $module->order = $this->post->maxOrder + $i * 10; + $this->dao->insert(TABLE_MODULE)->data($module)->exec(); + $moduleID = $this->dao->lastInsertID(); + $childPath = $parentPath . "$moduleID,"; + $this->dao->update(TABLE_MODULE)->set('path')->eq($childPath)->where('id')->eq($moduleID)->limit(1)->exec(); + $i ++; + } + else + { + $moduleID = str_replace('id', '', $moduleID); + $this->dao->update(TABLE_MODULE)->set('name')->eq(strip_tags($moduleName))->where('id')->eq($moduleID)->limit(1)->exec(); + } + } + } + + /** + * Update a module. + * + * @param int $moduleID + * @access public + * @return void + */ + public function update($moduleID) + { + $module = fixer::input('post')->specialChars('name')->get(); + $self = $this->getById($moduleID); + $parent = $this->getById($this->post->parent); + $childs = $this->getAllChildId($moduleID); + $module->grade = $parent ? $parent->grade + 1 : 1; + $this->dao->update(TABLE_MODULE)->data($module)->autoCheck()->check('name', 'notempty')->where('id')->eq($moduleID)->exec(); + $this->dao->update(TABLE_MODULE)->set('grade = grade + 1')->where('id')->in($childs)->andWhere('id')->ne($moduleID)->exec(); + $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq('')->exec(); + $this->dao->update(TABLE_MODULE)->set('owner')->eq($this->post->owner)->where('id')->in($childs)->andWhere('owner')->eq($self->owner)->exec(); + $this->fixModulePath(); + } + + /** + * Delete a module. + * + * @param int $moduleID + * @access public + * @return void + */ + public function delete($moduleID) + { + $module = $this->getById($moduleID); + $childs = $this->getAllChildId($moduleID); + + $this->dao->update(TABLE_MODULE)->set('grade = grade - 1')->where('id')->in($childs)->exec(); // Update grade of all childs. + $this->dao->update(TABLE_MODULE)->set('parent')->eq($module->parent)->where('parent')->eq($moduleID)->exec(); // Update the parent of sons to my parent. + $this->dao->delete()->from(TABLE_MODULE)->where('id')->eq($moduleID)->exec(); // Delete my self. + $this->fixModulePath(); + + if($module->type == 'story') $this->dao->update(TABLE_STORY)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); + if($module->type == 'bug') $this->dao->update(TABLE_BUG)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); + if($module->type == 'case') $this->dao->update(TABLE_CASE)->set('module')->eq($module->parent)->where('module')->eq($moduleID)->exec(); + } + + /** + * Fix fieilds of all module, grade, parent, pathes and so on. + * + * @access public + * @return void + */ + public function fixModulePath() + { + /* Get the max grade. */ + $maxGrade = $this->dao->select('MAX(grade) AS grade')->from(TABLE_MODULE)->fetch('grade'); + $modules = array(); + + /* Cycle ervery grade. */ + for($grade = 1; $grade <= $maxGrade; $grade ++) + { + /* Modules of current grade. */ + $gradeModules = $this->dao->select('id, parent, grade')->from(TABLE_MODULE)->where('grade')->eq($grade)->fetchAll('id'); + foreach($gradeModules as $moduleID => $module) + { + if($grade == 1) + { + $module->path = ",$moduleID,"; + } + else + { + /* Get the parent module to compute path and grade of my self. */ + if(isset($modules[$module->parent])) + { + $module->path = $modules[$module->parent]->path . "$moduleID,"; + $module->grade = $modules[$module->parent]->grade + 1; + } + } + } + $modules += $gradeModules; + } + + /* Save modules to database. */ + foreach($modules as $moduleID => $module) + { + $this->dao->update(TABLE_MODULE)->data($module)->where('id')->eq($module->id)->limit(1)->exec(); + } + } +} diff --git a/module/tree/view/browse.html.php b/module/tree/view/browse.html.php index 174b375502..7057c1754d 100644 --- a/module/tree/view/browse.html.php +++ b/module/tree/view/browse.html.php @@ -1,96 +1,96 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
              -
              id}&viewType=$viewType");?>'> - - - - - -
              title;?>
              -
              -
              - tree->updateOrder);?> -
              -
              -
              -
              -
              id}&viewType=$viewType");?>'> - - - - - - - - - -
              tree->manageDocChild : $lang->tree->manageChild;?>
              - - createLink('tree', 'browse', "root={$root->id}&viewType=$viewType"), $root->name); - echo $lang->arrow; - foreach($parentModules as $module) - { - echo html::a($this->createLink('tree', 'browse', "root={$root->id}&viewType=$viewType&moduleID=$module->id"), $module->name); - echo $lang->arrow; - } - ?> - - - tree->syncFromProduct, 'onclick=syncModule('.$rootID.')'); - echo '
              '; - } - else if($viewType == 'story') - { - if($allProduct) - { - echo html::select('allProduct', $allProduct, '', 'onchange=syncProduct(this)'); - echo html::select('productModule', $productModules, ''); - echo html::commonButton($lang->tree->syncFromProduct, 'id=copyModule onclick=syncModule('.$currentProduct.')'); - } - echo '
              '; - } - $maxOrder = 0; - echo '
              '; - foreach($sons as $sonModule) - { - if($sonModule->order > $maxOrder) $maxOrder = $sonModule->order; - echo '' . html::input("modules[id$sonModule->id]", $sonModule->name, 'class=text-3 style="margin-bottom:5px"') . '
              '; - } - for($i = 0; $i < TREE::NEW_CHILD_COUNT ; $i ++) echo '' . html::input("modules[]", '', 'class=text-3 style="margin-bottom:5px"') . '
              '; - ?> -
              -
              - - -
              -
              -
              - + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
              +
              id}&viewType=$viewType");?>'> + + + + + +
              title;?>
              +
              +
              + tree->updateOrder);?> +
              +
              +
              +
              +
              id}&viewType=$viewType");?>'> + + + + + + + + + +
              tree->manageDocChild : $lang->tree->manageChild;?>
              + + createLink('tree', 'browse', "root={$root->id}&viewType=$viewType"), $root->name); + echo $lang->arrow; + foreach($parentModules as $module) + { + echo html::a($this->createLink('tree', 'browse', "root={$root->id}&viewType=$viewType&moduleID=$module->id"), $module->name); + echo $lang->arrow; + } + ?> + + + tree->syncFromProduct, 'onclick=syncModule('.$rootID.')'); + echo '
              '; + } + else if($viewType == 'story') + { + if($allProduct) + { + echo html::select('allProduct', $allProduct, '', 'onchange=syncProduct(this)'); + echo html::select('productModule', $productModules, ''); + echo html::commonButton($lang->tree->syncFromProduct, 'id=copyModule onclick=syncModule('.$currentProduct.')'); + } + echo '
              '; + } + $maxOrder = 0; + echo '
              '; + foreach($sons as $sonModule) + { + if($sonModule->order > $maxOrder) $maxOrder = $sonModule->order; + echo '' . html::input("modules[id$sonModule->id]", $sonModule->name, 'class=text-3 style="margin-bottom:5px"') . '
              '; + } + for($i = 0; $i < TREE::NEW_CHILD_COUNT ; $i ++) echo '' . html::input("modules[]", '', 'class=text-3 style="margin-bottom:5px"') . '
              '; + ?> +
              +
              + + +
              +
              +
              + diff --git a/module/tree/view/edit.html.php b/module/tree/view/edit.html.php index f5eff176e4..43d7bb1fd7 100644 --- a/module/tree/view/edit.html.php +++ b/module/tree/view/edit.html.php @@ -1,38 +1,38 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
              - - - - - - - - - - - type == 'bug'):?> - - - - - - - - -
              tree->edit;?>
              tree->parent;?>parent, "class='select-1'");?>
              tree->name;?>name, "class='text-1'");?>
              tree->owner;?>owner, "class='select-1'");?>
              - -
              -
              - + + * @package tree + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
              + + + + + + + + + + + type == 'bug'):?> + + + + + + + + +
              tree->edit;?>
              tree->parent;?>parent, "class='select-1'");?>
              tree->name;?>name, "class='text-1'");?>
              tree->owner;?>owner, "class='select-1'");?>
              + +
              +
              + diff --git a/module/upgrade/control.php b/module/upgrade/control.php index daeab3ca7c..e0e8797e60 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -1,81 +1,81 @@ - - * @package upgrade - * @version $Id$ - * @link http://www.zentao.net - */ -class upgrade extends control -{ - /** - * The index page. - * - * @access public - * @return void - */ - public function index() - { - $this->display(); - } - - /** - * Select the version of old zentao. - * - * @access public - * @return void - */ - public function selectVersion() - { - $version = str_replace(array(' ', '.'), array('', '_'), $this->config->installedVersion); - $version = strtolower($version); - $this->view->header->title = $this->lang->upgrade->common . $this->lang->colon . $this->lang->upgrade->selectVersion; - $this->view->position[] = $this->lang->upgrade->common; - $this->view->version = $version; - $this->display(); - } - - /** - * Confirm the version. - * - * @access public - * @return void - */ - public function confirm() - { - $this->view->header->title = $this->lang->upgrade->confirm; - $this->view->position[] = $this->lang->upgrade->common; - $this->view->confirm = $this->upgrade->getConfirm($this->post->fromVersion); - $this->view->fromVersion = $this->post->fromVersion; - - $this->display(); - } - - /** - * Execute the upgrading. - * - * @access public - * @return void - */ - public function execute() - { - $this->upgrade->execute($this->post->fromVersion); - - $this->view->header->title = $this->lang->upgrade->result; - $this->view->position[] = $this->lang->upgrade->common; - - if(!$this->upgrade->isError()) - { - $this->view->result = 'success'; - } - else - { - $this->view->result = 'fail'; - $this->view->errors = $this->upgrade->getError(); - } - $this->display(); - } -} + + * @package upgrade + * @version $Id$ + * @link http://www.zentao.net + */ +class upgrade extends control +{ + /** + * The index page. + * + * @access public + * @return void + */ + public function index() + { + $this->display(); + } + + /** + * Select the version of old zentao. + * + * @access public + * @return void + */ + public function selectVersion() + { + $version = str_replace(array(' ', '.'), array('', '_'), $this->config->installedVersion); + $version = strtolower($version); + $this->view->header->title = $this->lang->upgrade->common . $this->lang->colon . $this->lang->upgrade->selectVersion; + $this->view->position[] = $this->lang->upgrade->common; + $this->view->version = $version; + $this->display(); + } + + /** + * Confirm the version. + * + * @access public + * @return void + */ + public function confirm() + { + $this->view->header->title = $this->lang->upgrade->confirm; + $this->view->position[] = $this->lang->upgrade->common; + $this->view->confirm = $this->upgrade->getConfirm($this->post->fromVersion); + $this->view->fromVersion = $this->post->fromVersion; + + $this->display(); + } + + /** + * Execute the upgrading. + * + * @access public + * @return void + */ + public function execute() + { + $this->upgrade->execute($this->post->fromVersion); + + $this->view->header->title = $this->lang->upgrade->result; + $this->view->position[] = $this->lang->upgrade->common; + + if(!$this->upgrade->isError()) + { + $this->view->result = 'success'; + } + else + { + $this->view->result = 'fail'; + $this->view->errors = $this->upgrade->getError(); + } + $this->display(); + } +} diff --git a/module/upgrade/lang/en.php b/module/upgrade/lang/en.php index f41e10b822..1cf1cbe7fc 100644 --- a/module/upgrade/lang/en.php +++ b/module/upgrade/lang/en.php @@ -1,60 +1,60 @@ - - * @package upgrade - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->upgrade->common = 'Upgrade'; -$lang->upgrade->result = 'Result'; -$lang->upgrade->fail = 'Fail'; -$lang->upgrade->success = 'Success'; -$lang->upgrade->tohome = 'Go to index'; -$lang->upgrade->warnning= 'Warning'; -$lang->upgrade->warnningContent = << -EOT; - - - - - - -$lang->upgrade->setStatusFile = "

              For security reason, we will check file %s
              - But this file doesn't exist or out of date. You can use the flowing command to create(update)it
              - For linux:touch %s;
              - For windows:echo ok > %s

              - I have done this work, continue upgrade"; - - - -$lang->upgrade->selectVersion = 'Select version'; -$lang->upgrade->noteVersion = "Must select the correct version"; -$lang->upgrade->fromVersion = 'From version'; -$lang->upgrade->toVersion = 'To version'; -$lang->upgrade->confirm = 'Confirm the sql to executed.'; -$lang->upgrade->sureExecute = 'Execute'; - -$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; -$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; -$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; -$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; -$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; -$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; -$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; -$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; -$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; -$lang->upgrade->fromVersions['1_1'] = '1.1'; -$lang->upgrade->fromVersions['1_2'] = '1.2'; -$lang->upgrade->fromVersions['1_3'] = '1.3'; -$lang->upgrade->fromVersions['1_4'] = '1.4'; -$lang->upgrade->fromVersions['1_5'] = '1.5'; -$lang->upgrade->fromVersions['2_0'] = '2.0'; -$lang->upgrade->fromVersions['2_1'] = '2.1'; -$lang->upgrade->fromVersions['2_2'] = '2.2'; -$lang->upgrade->fromVersions['2_3'] = '2.3'; -$lang->upgrade->fromVersions['2_4'] = '2.4'; + + * @package upgrade + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->upgrade->common = 'Upgrade'; +$lang->upgrade->result = 'Result'; +$lang->upgrade->fail = 'Fail'; +$lang->upgrade->success = 'Success'; +$lang->upgrade->tohome = 'Go to index'; +$lang->upgrade->warnning= 'Warning'; +$lang->upgrade->warnningContent = << +EOT; + + + + + + +$lang->upgrade->setStatusFile = "

              For security reason, we will check file %s
              + But this file doesn't exist or out of date. You can use the flowing command to create(update)it
              + For linux:touch %s;
              + For windows:echo ok > %s

              + I have done this work, continue upgrade"; + + + +$lang->upgrade->selectVersion = 'Select version'; +$lang->upgrade->noteVersion = "Must select the correct version"; +$lang->upgrade->fromVersion = 'From version'; +$lang->upgrade->toVersion = 'To version'; +$lang->upgrade->confirm = 'Confirm the sql to executed.'; +$lang->upgrade->sureExecute = 'Execute'; + +$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; +$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; +$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; +$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; +$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; +$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; +$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; +$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; +$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; +$lang->upgrade->fromVersions['1_1'] = '1.1'; +$lang->upgrade->fromVersions['1_2'] = '1.2'; +$lang->upgrade->fromVersions['1_3'] = '1.3'; +$lang->upgrade->fromVersions['1_4'] = '1.4'; +$lang->upgrade->fromVersions['1_5'] = '1.5'; +$lang->upgrade->fromVersions['2_0'] = '2.0'; +$lang->upgrade->fromVersions['2_1'] = '2.1'; +$lang->upgrade->fromVersions['2_2'] = '2.2'; +$lang->upgrade->fromVersions['2_3'] = '2.3'; +$lang->upgrade->fromVersions['2_4'] = '2.4'; diff --git a/module/upgrade/lang/zh-cn.php b/module/upgrade/lang/zh-cn.php index d8e3162e3d..90ab80f233 100644 --- a/module/upgrade/lang/zh-cn.php +++ b/module/upgrade/lang/zh-cn.php @@ -1,60 +1,60 @@ - - * @package upgrade - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->upgrade->common = '升级'; -$lang->upgrade->result = '升级结果'; -$lang->upgrade->fail = '升级失败'; -$lang->upgrade->success = '升级成功'; -$lang->upgrade->tohome = '返回首页'; -$lang->upgrade->warnning= '警告'; -$lang->upgrade->warnningContent = << -备份方法:
              -1. 可以通过phpMyAdmin进行备份。
              -2. 使用mysql命令行的工具。
              - # mysqldump -u username -p dbname > filename
              - 要将上面红色的部分分别替换成对应的用户名和禅道系统的数据库名。
              - 比如: mysqldump -u root -p zentao >zentao.bak -EOT; -$lang->upgrade->setStatusFile = '

              基于安全考虑,升级程序会检查%s文件的最后更新时间, 以确保安全!

              - 该文件不存在或者已经过期,请用下面的命令来创建或者更新它。 -
                -
              • linux下面的命令:touch %s;
              • -
              • windows打开命令行,执行echo ok > %s
              • -
              • 或者删掉原来的ok文件,重新创建一个ok文件,不需要扩展名,不需要内容。
              • -
              - 我已经仔细阅读上面提示且完成上述工作,继续更新'; -$lang->upgrade->selectVersion = '选择版本'; -$lang->upgrade->noteVersion = "务必选择正确的版本,否则会造成数据丢失。"; -$lang->upgrade->fromVersion = '原来的版本'; -$lang->upgrade->toVersion = '升级到'; -$lang->upgrade->confirm = '确认要执行的SQL语句'; -$lang->upgrade->sureExecute = '确认执行'; - -$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; -$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; -$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; -$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; -$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; -$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; -$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; -$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; -$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; -$lang->upgrade->fromVersions['1_1'] = '1.1'; -$lang->upgrade->fromVersions['1_2'] = '1.2'; -$lang->upgrade->fromVersions['1_3'] = '1.3'; -$lang->upgrade->fromVersions['1_4'] = '1.4'; -$lang->upgrade->fromVersions['1_5'] = '1.5'; -$lang->upgrade->fromVersions['2_0'] = '2.0'; -$lang->upgrade->fromVersions['2_1'] = '2.1'; -$lang->upgrade->fromVersions['2_2'] = '2.2'; -$lang->upgrade->fromVersions['2_3'] = '2.3'; -$lang->upgrade->fromVersions['2_4'] = '2.4'; + + * @package upgrade + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->upgrade->common = '升级'; +$lang->upgrade->result = '升级结果'; +$lang->upgrade->fail = '升级失败'; +$lang->upgrade->success = '升级成功'; +$lang->upgrade->tohome = '返回首页'; +$lang->upgrade->warnning= '警告'; +$lang->upgrade->warnningContent = << +备份方法:
              +1. 可以通过phpMyAdmin进行备份。
              +2. 使用mysql命令行的工具。
              + # mysqldump -u username -p dbname > filename
              + 要将上面红色的部分分别替换成对应的用户名和禅道系统的数据库名。
              + 比如: mysqldump -u root -p zentao >zentao.bak +EOT; +$lang->upgrade->setStatusFile = '

              基于安全考虑,升级程序会检查%s文件的最后更新时间, 以确保安全!

              + 该文件不存在或者已经过期,请用下面的命令来创建或者更新它。 +
                +
              • linux下面的命令:touch %s;
              • +
              • windows打开命令行,执行echo ok > %s
              • +
              • 或者删掉原来的ok文件,重新创建一个ok文件,不需要扩展名,不需要内容。
              • +
              + 我已经仔细阅读上面提示且完成上述工作,继续更新'; +$lang->upgrade->selectVersion = '选择版本'; +$lang->upgrade->noteVersion = "务必选择正确的版本,否则会造成数据丢失。"; +$lang->upgrade->fromVersion = '原来的版本'; +$lang->upgrade->toVersion = '升级到'; +$lang->upgrade->confirm = '确认要执行的SQL语句'; +$lang->upgrade->sureExecute = '确认执行'; + +$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; +$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; +$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; +$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; +$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; +$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; +$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; +$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; +$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; +$lang->upgrade->fromVersions['1_1'] = '1.1'; +$lang->upgrade->fromVersions['1_2'] = '1.2'; +$lang->upgrade->fromVersions['1_3'] = '1.3'; +$lang->upgrade->fromVersions['1_4'] = '1.4'; +$lang->upgrade->fromVersions['1_5'] = '1.5'; +$lang->upgrade->fromVersions['2_0'] = '2.0'; +$lang->upgrade->fromVersions['2_1'] = '2.1'; +$lang->upgrade->fromVersions['2_2'] = '2.2'; +$lang->upgrade->fromVersions['2_3'] = '2.3'; +$lang->upgrade->fromVersions['2_4'] = '2.4'; diff --git a/module/upgrade/lang/zh-tw.php b/module/upgrade/lang/zh-tw.php index 049019535f..8124fd1aff 100644 --- a/module/upgrade/lang/zh-tw.php +++ b/module/upgrade/lang/zh-tw.php @@ -1,60 +1,60 @@ - - * @package upgrade - * @version $Id: zh-tw.php 2535 2012-01-04 06:39:54Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -$lang->upgrade->common = '升級'; -$lang->upgrade->result = '升級結果'; -$lang->upgrade->fail = '升級失敗'; -$lang->upgrade->success = '升級成功'; -$lang->upgrade->tohome = '返迴首頁'; -$lang->upgrade->warnning= '警告'; -$lang->upgrade->warnningContent = << -備份方法:
              -1. 可以通過phpMyAdmin進行備份。
              -2. 使用mysql命令行的工具。
              - # mysqldump -u username -p dbname > filename
              - 要將上面紅色的部分分別替換成對應的用戶名和禪道系統的資料庫名。
              - 比如: mysqldump -u root -p zentao >zentao.bak -EOT; -$lang->upgrade->setStatusFile = '

              基于安全考慮,升級程序會檢查%s檔案的最後更新時間, 以確保安全!

              - 該檔案不存在或者已經過期,請用下面的命令來創建或者更新它。 -
                -
              • linux下面的命令:touch %s;
              • -
              • windows打開命令行,執行echo ok > %s
              • -
              • 或者刪掉原來的ok檔案,重新創建一個ok檔案,不需要副檔名,不需要內容。
              • -
              - 我已經仔細閲讀上面提示且完成上述工作,繼續更新'; -$lang->upgrade->selectVersion = '選擇版本'; -$lang->upgrade->noteVersion = "務必選擇正確的版本,否則會造成數據丟失。"; -$lang->upgrade->fromVersion = '原來的版本'; -$lang->upgrade->toVersion = '升級到'; -$lang->upgrade->confirm = '確認要執行的SQL語句'; -$lang->upgrade->sureExecute = '確認執行'; - -$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; -$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; -$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; -$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; -$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; -$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; -$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; -$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; -$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; -$lang->upgrade->fromVersions['1_1'] = '1.1'; -$lang->upgrade->fromVersions['1_2'] = '1.2'; -$lang->upgrade->fromVersions['1_3'] = '1.3'; -$lang->upgrade->fromVersions['1_4'] = '1.4'; -$lang->upgrade->fromVersions['1_5'] = '1.5'; -$lang->upgrade->fromVersions['2_0'] = '2.0'; -$lang->upgrade->fromVersions['2_1'] = '2.1'; -$lang->upgrade->fromVersions['2_2'] = '2.2'; -$lang->upgrade->fromVersions['2_3'] = '2.3'; -$lang->upgrade->fromVersions['2_4'] = '2.4'; + + * @package upgrade + * @version $Id: zh-tw.php 2535 2012-01-04 06:39:54Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +$lang->upgrade->common = '升級'; +$lang->upgrade->result = '升級結果'; +$lang->upgrade->fail = '升級失敗'; +$lang->upgrade->success = '升級成功'; +$lang->upgrade->tohome = '返迴首頁'; +$lang->upgrade->warnning= '警告'; +$lang->upgrade->warnningContent = << +備份方法:
              +1. 可以通過phpMyAdmin進行備份。
              +2. 使用mysql命令行的工具。
              + # mysqldump -u username -p dbname > filename
              + 要將上面紅色的部分分別替換成對應的用戶名和禪道系統的資料庫名。
              + 比如: mysqldump -u root -p zentao >zentao.bak +EOT; +$lang->upgrade->setStatusFile = '

              基于安全考慮,升級程序會檢查%s檔案的最後更新時間, 以確保安全!

              + 該檔案不存在或者已經過期,請用下面的命令來創建或者更新它。 +
                +
              • linux下面的命令:touch %s;
              • +
              • windows打開命令行,執行echo ok > %s
              • +
              • 或者刪掉原來的ok檔案,重新創建一個ok檔案,不需要副檔名,不需要內容。
              • +
              + 我已經仔細閲讀上面提示且完成上述工作,繼續更新'; +$lang->upgrade->selectVersion = '選擇版本'; +$lang->upgrade->noteVersion = "務必選擇正確的版本,否則會造成數據丟失。"; +$lang->upgrade->fromVersion = '原來的版本'; +$lang->upgrade->toVersion = '升級到'; +$lang->upgrade->confirm = '確認要執行的SQL語句'; +$lang->upgrade->sureExecute = '確認執行'; + +$lang->upgrade->fromVersions['0_3beta'] = '0.3 BETA'; +$lang->upgrade->fromVersions['0_4beta'] = '0.4 BETA'; +$lang->upgrade->fromVersions['0_5beta'] = '0.5 BETA'; +$lang->upgrade->fromVersions['0_6beta'] = '0.6 BETA'; +$lang->upgrade->fromVersions['1_0beta'] = '1.0 BETA'; +$lang->upgrade->fromVersions['1_0rc1'] = '1.0 RC1'; +$lang->upgrade->fromVersions['1_0rc2'] = '1.0 RC2'; +$lang->upgrade->fromVersions['1_0'] = '1.0 STABLE'; +$lang->upgrade->fromVersions['1_0_1'] = '1.0.1'; +$lang->upgrade->fromVersions['1_1'] = '1.1'; +$lang->upgrade->fromVersions['1_2'] = '1.2'; +$lang->upgrade->fromVersions['1_3'] = '1.3'; +$lang->upgrade->fromVersions['1_4'] = '1.4'; +$lang->upgrade->fromVersions['1_5'] = '1.5'; +$lang->upgrade->fromVersions['2_0'] = '2.0'; +$lang->upgrade->fromVersions['2_1'] = '2.1'; +$lang->upgrade->fromVersions['2_2'] = '2.2'; +$lang->upgrade->fromVersions['2_3'] = '2.3'; +$lang->upgrade->fromVersions['2_4'] = '2.4'; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 55f3adcad5..8b9a08c0fa 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -1,1087 +1,1087 @@ - - * @package upgrade - * @version $Id$ - * @link http://www.zentao.net - */ -?> -loadModel('setting'); - } - - /** - * The execute method. According to the $fromVersion call related methods. - * - * @param string $fromVersion - * @access public - * @return void - */ - public function execute($fromVersion) - { - if($fromVersion == '0_3beta') - { - $this->upgradeFrom0_3To0_4(); - $this->upgradeFrom0_4To0_5(); - $this->upgradeFrom0_5To0_6(); - $this->upgradeFrom0_6To1_0_B(); - $this->upgradeFrom1_0betaTo1_0rc1(); - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '0_4beta') - { - $this->upgradeFrom0_4To0_5(); - $this->upgradeFrom0_5To0_6(); - $this->upgradeFrom0_6To1_0_B(); - $this->upgradeFrom1_0betaTo1_0rc1(); - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '0_5beta') - { - $this->upgradeFrom0_5To0_6(); - $this->upgradeFrom0_6To1_0_B(); - $this->upgradeFrom1_0betaTo1_0rc1(); - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '0_6beta') - { - $this->upgradeFrom0_6To1_0_B(); - $this->upgradeFrom1_0betaTo1_0rc1(); - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_0beta') - { - $this->upgradeFrom1_0betaTo1_0rc1(); - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_0rc1') - { - $this->upgradeFrom1_0rc1To1_0rc2(); - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_0rc2') - { - $this->upgradeFrom1_0rc2To1_0stable(); - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_0') - { - $this->upgradeFrom1_0stableTo1_0_1(); - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_0_1') - { - $this->upgradeFrom1_0_1To1_1(); - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_1') - { - $this->upgradeFrom1_1To1_2(); - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_2') - { - $this->upgradeFrom1_2To1_3(); - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_3') - { - $this->upgradeFrom1_3To1_4(); - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_4') - { - $this->upgradeFrom1_4To1_5(); - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '1_5') - { - $this->upgradeFrom1_5To2_0(); - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '2_0') - { - $this->upgradeFrom2_0To2_1(); - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '2_1') - { - $this->upgradeFrom2_1To2_2(); - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '2_2') - { - $this->upgradeFrom2_2To2_3(); - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '2_3') - { - $this->upgradeFrom2_3To2_4(); - $this->upgradeFrom2_4To3_0_beta1(); - } - elseif($fromVersion == '2_4') - { - $this->upgradeFrom2_4To3_0_beta1(); - } - - $this->deletePatch(); - $this->setting->setSN(); - } - - /** - * Create the confirm contents. - * - * @param string $fromVersion - * @access public - * @return string - */ - public function getConfirm($fromVersion) - { - $confirmContent = ''; - if($fromVersion == '0_3beta') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('0.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '0_4beta') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '0_5beta') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '0_6beta') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_0beta') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_0rc1') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_0rc2' || $fromVersion == '1_0' || $fromVersion == '1_0_1') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_1') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_2') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_3') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_4') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '1_5') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '2_0') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '2_1') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '2_2') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '2_3') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - elseif($fromVersion == '2_4') - { - $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - } - - return str_replace('zt_', $this->config->db->prefix, $confirmContent); - } - - /** - * Upgrade from 0.3 to 0.4 - * - * @access private - * @return void - */ - private function upgradeFrom0_3To0_4() - { - $this->execSQL($this->getUpgradeFile('0.3')); - if(!$this->isError()) $this->setting->updateVersion('0.4 beta'); - } - - /** - * Upgrade from 0.4 to 0.5 - * - * @access private - * @return void - */ - private function upgradeFrom0_4To0_5() - { - $this->execSQL($this->getUpgradeFile('0.4')); - if(!$this->isError()) $this->setting->updateVersion('0.5 beta'); - } - - /** - * Upgrade from 0.5 to 0.6. - * - * @access private - * @return void - */ - private function upgradeFrom0_5To0_6() - { - $this->execSQL($this->getUpgradeFile('0.5')); - if(!$this->isError()) $this->setting->updateVersion('0.6 beta'); - } - - /** - * Upgrade from 0.6 to 1.0 beta. - * - * @access private - * @return void - */ - private function upgradeFrom0_6To1_0_B() - { - $this->execSQL($this->getUpgradeFile('0.6')); - if(!$this->isError()) $this->setting->updateVersion('1.0beta'); - } - - /** - * Upgrade from 1.0 beta to 1.0 rc1. - * - * @access private - * @return void - */ - private function upgradeFrom1_0betaTo1_0rc1() - { - $this->execSQL($this->getUpgradeFile('1.0.beta')); - $this->updateCompany(); - if(!$this->isError()) $this->setting->updateVersion('1.0rc1'); - } - - /** - * Upgrade from 1.0 rc1 to 1.0 rc2. - * - * @access private - * @return void - */ - private function upgradeFrom1_0rc1To1_0rc2() - { - $this->execSQL($this->getUpgradeFile('1.0.rc1')); - if(!$this->isError()) $this->setting->updateVersion('1.0rc2'); - } - - /** - * Upgrade from 1.0 rc2 to 1.0 stable. - * - * @access private - * @return void - */ - private function upgradeFrom1_0rc2To1_0stable() - { - $this->setting->updateVersion('1.0'); - } - - /** - * Upgrade from 1.0 stable to 1.0.1. - * - * @access private - * @return void - */ - private function upgradeFrom1_0stableTo1_0_1() - { - $this->setting->updateVersion('1.0.1'); - } - - /** - * Upgrade from 1.0.1 to 1.1. - * - * @access private - * @return void - */ - private function upgradeFrom1_0_1To1_1() - { - $this->execSQL($this->getUpgradeFile('1.0.1')); - if(!$this->isError()) $this->setting->updateVersion('1.1'); - } - - /** - * Upgrade from 1.1 to 1.2. - * - * @access private - * @return void - */ - private function upgradeFrom1_1To1_2() - { - $this->execSQL($this->getUpgradeFile('1.1')); - if(!$this->isError()) $this->setting->updateVersion('1.2'); - } - - /** - * Upgrade from 1.2 to 1.3. - * - * @access private - * @return void - */ - private function upgradeFrom1_2To1_3() - { - $this->execSQL($this->getUpgradeFile('1.2')); - $this->updateUBB(); - $this->updateNL1_2(); - if(!$this->isError()) $this->setting->updateVersion('1.3'); - } - - /** - * Upgrade from 1.3 to 1.4. - * - * @access private - * @return void - */ - private function upgradeFrom1_3To1_4() - { - $this->execSQL($this->getUpgradeFile('1.3')); - $this->updateNL1_3(); - $this->updateTasks(); - if(!$this->isError()) $this->setting->updateVersion('1.4'); - } - - /** - * Upgrade from 1.4 to 1.5. - * - * @access private - * @return void - */ - private function upgradeFrom1_4To1_5() - { - $this->execSQL($this->getUpgradeFile('1.4')); - if(!$this->isError()) $this->setting->updateVersion('1.5'); - } - - /** - * Upgrade from 1.5 to 2.0. - * - * @access private - * @return void - */ - private function upgradeFrom1_5To2_0() - { - $this->execSQL($this->getUpgradeFile('1.5')); - if(!$this->isError()) $this->setting->updateVersion('2.0'); - } - - /** - * Upgrade from 2.0 to 2.1. - * - * @access private - * @return void - */ - private function upgradeFrom2_0To2_1() - { - $this->execSQL($this->getUpgradeFile('2.0')); - if(!$this->isError()) $this->setting->updateVersion('2.1'); - } - - /** - * Upgrade from 2.1 to 2.2. - * - * @access private - * @return void - */ - private function upgradeFrom2_1To2_2() - { - $this->execSQL($this->getUpgradeFile('2.1')); - if(!$this->isError()) $this->setting->updateVersion('2.2'); - } - - /** - * Upgrade from 2.2 to 2.3. - * - * @access private - * @return void - */ - private function upgradeFrom2_2To2_3() - { - $this->execSQL($this->getUpgradeFile('2.2')); - $this->updateCases(); - $this->updateActivatedCountOfBug(); - if(!$this->isError()) $this->setting->updateVersion('2.3'); - } - - /** - * Upgrade from 2.3 to 2.4. - * - * @access private - * @return void - */ - private function upgradeFrom2_3To2_4() - { - $this->execSQL($this->getUpgradeFile('2.3')); - if(!$this->isError()) $this->setting->updateVersion('2.4'); - } - - /** - * Upgrade from 2.4 to 3.0.beta1. - * - * @access private - * @return void - */ - private function upgradeFrom2_4To3_0_beta1() - { - $this->execSQL($this->getUpgradeFile('2.4')); - if(!$this->isError()) $this->setting->updateVersion('3.0.beta1'); - } - - /** - * Update company field. - * - * This method is used to update since 1.0 beta. Any new tables added after 1.0 beta should skip. - * - * @access private - * @return void - */ - private function updateCompany() - { - /* Get user defined constants. */ - $constants = get_defined_constants(true); - $userConstants = $constants['user']; - - /* Update tables. */ - foreach($userConstants as $key => $value) - { - if(strpos($key, 'TABLE') === false) continue; - if($key == 'TABLE_COMPANY') continue; - - $table = $value; - $result = $this->dbh->query("SHOW TABLES LIKE '$table'"); - if($result->rowCount() > 0) - { - $this->dbh->query("UPDATE $table SET company = '{$this->app->company->id}'"); - } - } - } - - /** - * Update ubb code in bug table and user Templates table to html. - * - * @access private - * @return void - */ - private function updateUBB() - { - $this->app->loadClass('ubb', true); - - $bugs = $this->dao->select('id, steps')->from(TABLE_BUG)->fetchAll(); - $userTemplates = $this->dao->select('id, content')->from(TABLE_USERTPL)->fetchAll(); - - foreach($bugs as $id => $bug) - { - $bug->steps = ubb::parseUBB($bug->steps); - $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bug->id)->exec(); - } - foreach($userTemplates as $template) - { - $template->content = ubb::parseUBB($template->content); - $this->dao->update(TABLE_USERTPL)->data($template)->where('id')->eq($template->id)->exec(); - } - } - - /** - * Update nl to br from 1.2 version. - * - * @access public - * @return void - */ - public function updateNL1_2() - { - $tasks = $this->dao->select('id, `desc`')->from(TABLE_TASK)->fetchAll(); - $stories = $this->dao->select('story, version, spec')->from(TABLE_STORYSPEC)->fetchAll(); - $todos = $this->dao->select('id, `desc`')->from(TABLE_TODO)->fetchAll(); - $testTasks = $this->dao->select('id, `desc`')->from(TABLE_TESTTASK)->fetchAll(); - - foreach($tasks as $task) - { - $task->desc = nl2br($task->desc); - $this->dao->update(TABLE_TASK)->data($task)->where('id')->eq($task->id)->exec(); - } - foreach($stories as $story) - { - $story->spec = nl2br($story->spec); - $this->dao->update(TABLE_STORYSPEC)->data($story)->where('story')->eq($story->story)->andWhere('version')->eq($story->version)->exec(); - } - - foreach($todos as $todo) - { - $todo->desc = nl2br($todo->desc); - $this->dao->update(TABLE_TODO)->data($todo)->where('id')->eq($todo->id)->exec(); - } - - foreach($testTasks as $testtask) - { - $testtask->desc = nl2br($testtask->desc); - $this->dao->update(TABLE_TESTTASK)->data($testtask)->where('id')->eq($testtask->id)->exec(); - } - } - - /** - * Update nl to br from 1.3 version. - * - * @access public - * @return void - */ - public function updateNL1_3() - { - $products = $this->dao->select('id, `desc`')->from(TABLE_PRODUCT)->fetchAll(); - $plans = $this->dao->select('id, `desc`')->from(TABLE_PRODUCTPLAN)->fetchAll(); - $releases = $this->dao->select('id, `desc`')->from(TABLE_RELEASE)->fetchAll(); - $projects = $this->dao->select('id, `desc`, goal')->from(TABLE_PROJECT)->fetchAll(); - $builds = $this->dao->select('id, `desc`')->from(TABLE_BUILD)->fetchAll(); - - foreach($products as $product) - { - $product->desc = nl2br($product->desc); - $this->dao->update(TABLE_PRODUCT)->data($product)->where('id')->eq($product->id)->exec(); - } - - foreach($plans as $plan) - { - $plan->desc = nl2br($plan->desc); - $this->dao->update(TABLE_PRODUCTPLAN)->data($plan)->where('id')->eq($plan->id)->exec(); - } - - foreach($releases as $release) - { - $release->desc = nl2br($release->desc); - $this->dao->update(TABLE_RELEASE)->data($release)->where('id')->eq($release->id)->exec(); - } - - foreach($projects as $project) - { - $project->desc = nl2br($project->desc); - $project->goal = nl2br($project->goal); - $this->dao->update(TABLE_PROJECT)->data($project)->where('id')->eq($project->id)->exec(); - } - - foreach($builds as $build) - { - $build->desc = nl2br($build->desc); - $this->dao->update(TABLE_BUILD)->data($build)->where('id')->eq($build->id)->exec(); - } - } - - /** - * Update task fields. - * - * @access public - * @return void - */ - public function updateTasks() - { - /* Get all actions of tasks. */ - $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where('objectType')->eq('task') - ->orderBy('id') - ->fetchAll('id'); - - /* Get histories about status field. */ - $histories = $this->dao->select()->from(TABLE_HISTORY) - ->where('action')->in(array_keys($actions)) - ->andWhere('field')->eq('status') - ->orderBy('id') - ->fetchGroup('action'); - - $tasks = array(); - foreach($actions as $action) - { - if(!isset($tasks[$action->objectID])) - { - $tasks[$action->objectID] = new stdclass; - } - $task = $tasks[$action->objectID]; - - $task->id = $action->objectID; - $actionType = strtolower($action->action); - - /* Set the openedBy info. */ - if($actionType == 'opened') - { - $task->openedBy = $action->actor; - $task->openedDate = $action->date; - } - else - { - if(!isset($histories[$action->id])) continue; - - $actionHistories = $histories[$action->id]; - foreach($actionHistories as $history) - { - /* Finished by. */ - if($history->new == 'done') - { - $task->finishedBy = $action->actor; - $task->finishedDate = $action->date; - $action->action = 'finished'; - } - /* Canceled By. */ - elseif($history->new == 'cancel') - { - $task->canceledBy = $action->actor; - $task->canceledDate = $action->date; - $action->action = 'canceled'; - } - } - - /* Last edited by .*/ - $task->lastEditedBy = $action->actor; - $task->lastEditedDate = $action->date; - - /* Update action type. */ - $this->dao->update(TABLE_ACTION)->set('action')->eq($action->action)->where('id')->eq($action->id)->exec(false); - } - } - - /* Update db. */ - foreach($tasks as $task) - { - $this->dao->update(TABLE_TASK)->data($task, false)->where('id')->eq($task->id)->exec(false); - } - - $this->dao->update(TABLE_TASK)->set('assignedTo=openedBy, assignedDate = finishedDate')->where('status')->eq('done')->exec(false); - $this->dao->update(TABLE_TASK)->set('assignedTo=openedBy, assignedDate = canceledDate')->where('status')->eq('cancel')->exec(false); - - /* Update action name. */ - } - - /** - * Update activated count of Bug. - * - * @access public - * @return void - */ - private function updateActivatedCountOfBug() - { - $bugActivatedActions = $this->dao->select('*')->from(TABLE_ACTION)->where('action')->eq('activated')->andWhere('objectType')->eq('bug')->fetchAll(); - if(!empty($bugActivatedActions)) - { - foreach($bugActivatedActions as $action) - { - if(!isset($counts[$action->objectID])) $counts[$action->objectID] = 0; - $counts[$action->objectID] ++; - } - foreach($counts as $key => $count) - { - $this->dao->update(TABLE_BUG)->set('activatedCount')->eq($count)->where('id')->eq($key)->exec(); - } - } - } - - /** - * Update lastRun and lastResult field in zt_case - * - * @access public - * @return void - */ - public function updateCases() - { - $results = $this->dao->select('`case`, date, caseResult')->from(TABLE_TESTRESULT)->orderBy('id desc')->fetchGroup('case'); - foreach($results as $result) - { - $this->dao->update(TABLE_CASE) - ->set('lastRun')->eq($result[0]->date) - ->set('lastResult')->eq($result[0]->caseResult) - ->where('id')->eq($result[0]->case) - ->exec(); - } - } - - /** - * Delete the patch record. - * - * @access public - * @return void - */ - public function deletePatch() - { - $this->dao->delete()->from(TABLE_EXTENSION)->where('type')->eq('patch')->exec(false); - $this->dao->delete()->from(TABLE_EXTENSION)->where('code')->in('zentaopatch,patch')->exec(false); - } - - /** - * Get the upgrade sql file. - * - * @param string $version - * @access private - * @return string - */ - private function getUpgradeFile($version) - { - return $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'update' . $version . '.sql'; - } - - /** - * Execute a sql. - * - * @param string $sqlFile - * @access private - * @return void - */ - private function execSQL($sqlFile) - { - $mysqlVersion = $this->loadModel('install')->getMysqlVersion(); - - /* Read the sql file to lines, remove the comment lines, then join theme by ';'. */ - $sqls = explode("\n", file_get_contents($sqlFile)); - foreach($sqls as $key => $line) - { - $line = trim($line); - $sqls[$key] = $line; - if(strpos($line, '--') !== false or empty($line)) unset($sqls[$key]); - } - $sqls = explode(';', join("\n", $sqls)); - - foreach($sqls as $sql) - { - $sql = trim($sql); - if(empty($sql)) continue; - - if($mysqlVersion <= 4.1) - { - $sql = str_replace('DEFAULT CHARSET=utf8', '', $sql); - $sql = str_replace('CHARACTER SET utf8 COLLATE utf8_general_ci', '', $sql); - } - - $sql = str_replace('zt_', $this->config->db->prefix, $sql); - try - { - $this->dbh->exec($sql); - } - catch (PDOException $e) - { - self::$errors[] = $e->getMessage() . "

              The sql is: $sql

              "; - } - } - } - - /** - * Judge any error occers. - * - * @access public - * @return bool - */ - public function isError() - { - return !empty(self::$errors); - } - - /** - * Get errors during the upgrading. - * - * @access public - * @return array - */ - public function getError() - { - $errors = self::$errors; - self::$errors = array(); - return $errors; - } -} + + * @package upgrade + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('setting'); + } + + /** + * The execute method. According to the $fromVersion call related methods. + * + * @param string $fromVersion + * @access public + * @return void + */ + public function execute($fromVersion) + { + if($fromVersion == '0_3beta') + { + $this->upgradeFrom0_3To0_4(); + $this->upgradeFrom0_4To0_5(); + $this->upgradeFrom0_5To0_6(); + $this->upgradeFrom0_6To1_0_B(); + $this->upgradeFrom1_0betaTo1_0rc1(); + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '0_4beta') + { + $this->upgradeFrom0_4To0_5(); + $this->upgradeFrom0_5To0_6(); + $this->upgradeFrom0_6To1_0_B(); + $this->upgradeFrom1_0betaTo1_0rc1(); + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '0_5beta') + { + $this->upgradeFrom0_5To0_6(); + $this->upgradeFrom0_6To1_0_B(); + $this->upgradeFrom1_0betaTo1_0rc1(); + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '0_6beta') + { + $this->upgradeFrom0_6To1_0_B(); + $this->upgradeFrom1_0betaTo1_0rc1(); + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_0beta') + { + $this->upgradeFrom1_0betaTo1_0rc1(); + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_0rc1') + { + $this->upgradeFrom1_0rc1To1_0rc2(); + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_0rc2') + { + $this->upgradeFrom1_0rc2To1_0stable(); + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_0') + { + $this->upgradeFrom1_0stableTo1_0_1(); + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_0_1') + { + $this->upgradeFrom1_0_1To1_1(); + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_1') + { + $this->upgradeFrom1_1To1_2(); + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_2') + { + $this->upgradeFrom1_2To1_3(); + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_3') + { + $this->upgradeFrom1_3To1_4(); + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_4') + { + $this->upgradeFrom1_4To1_5(); + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '1_5') + { + $this->upgradeFrom1_5To2_0(); + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '2_0') + { + $this->upgradeFrom2_0To2_1(); + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '2_1') + { + $this->upgradeFrom2_1To2_2(); + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '2_2') + { + $this->upgradeFrom2_2To2_3(); + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '2_3') + { + $this->upgradeFrom2_3To2_4(); + $this->upgradeFrom2_4To3_0_beta1(); + } + elseif($fromVersion == '2_4') + { + $this->upgradeFrom2_4To3_0_beta1(); + } + + $this->deletePatch(); + $this->setting->setSN(); + } + + /** + * Create the confirm contents. + * + * @param string $fromVersion + * @access public + * @return string + */ + public function getConfirm($fromVersion) + { + $confirmContent = ''; + if($fromVersion == '0_3beta') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('0.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '0_4beta') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '0_5beta') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '0_6beta') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_0beta') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_0rc1') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_0rc2' || $fromVersion == '1_0' || $fromVersion == '1_0_1') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_1') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_2') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_3') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_4') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '1_5') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '2_0') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '2_1') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '2_2') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '2_3') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + elseif($fromVersion == '2_4') + { + $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + } + + return str_replace('zt_', $this->config->db->prefix, $confirmContent); + } + + /** + * Upgrade from 0.3 to 0.4 + * + * @access private + * @return void + */ + private function upgradeFrom0_3To0_4() + { + $this->execSQL($this->getUpgradeFile('0.3')); + if(!$this->isError()) $this->setting->updateVersion('0.4 beta'); + } + + /** + * Upgrade from 0.4 to 0.5 + * + * @access private + * @return void + */ + private function upgradeFrom0_4To0_5() + { + $this->execSQL($this->getUpgradeFile('0.4')); + if(!$this->isError()) $this->setting->updateVersion('0.5 beta'); + } + + /** + * Upgrade from 0.5 to 0.6. + * + * @access private + * @return void + */ + private function upgradeFrom0_5To0_6() + { + $this->execSQL($this->getUpgradeFile('0.5')); + if(!$this->isError()) $this->setting->updateVersion('0.6 beta'); + } + + /** + * Upgrade from 0.6 to 1.0 beta. + * + * @access private + * @return void + */ + private function upgradeFrom0_6To1_0_B() + { + $this->execSQL($this->getUpgradeFile('0.6')); + if(!$this->isError()) $this->setting->updateVersion('1.0beta'); + } + + /** + * Upgrade from 1.0 beta to 1.0 rc1. + * + * @access private + * @return void + */ + private function upgradeFrom1_0betaTo1_0rc1() + { + $this->execSQL($this->getUpgradeFile('1.0.beta')); + $this->updateCompany(); + if(!$this->isError()) $this->setting->updateVersion('1.0rc1'); + } + + /** + * Upgrade from 1.0 rc1 to 1.0 rc2. + * + * @access private + * @return void + */ + private function upgradeFrom1_0rc1To1_0rc2() + { + $this->execSQL($this->getUpgradeFile('1.0.rc1')); + if(!$this->isError()) $this->setting->updateVersion('1.0rc2'); + } + + /** + * Upgrade from 1.0 rc2 to 1.0 stable. + * + * @access private + * @return void + */ + private function upgradeFrom1_0rc2To1_0stable() + { + $this->setting->updateVersion('1.0'); + } + + /** + * Upgrade from 1.0 stable to 1.0.1. + * + * @access private + * @return void + */ + private function upgradeFrom1_0stableTo1_0_1() + { + $this->setting->updateVersion('1.0.1'); + } + + /** + * Upgrade from 1.0.1 to 1.1. + * + * @access private + * @return void + */ + private function upgradeFrom1_0_1To1_1() + { + $this->execSQL($this->getUpgradeFile('1.0.1')); + if(!$this->isError()) $this->setting->updateVersion('1.1'); + } + + /** + * Upgrade from 1.1 to 1.2. + * + * @access private + * @return void + */ + private function upgradeFrom1_1To1_2() + { + $this->execSQL($this->getUpgradeFile('1.1')); + if(!$this->isError()) $this->setting->updateVersion('1.2'); + } + + /** + * Upgrade from 1.2 to 1.3. + * + * @access private + * @return void + */ + private function upgradeFrom1_2To1_3() + { + $this->execSQL($this->getUpgradeFile('1.2')); + $this->updateUBB(); + $this->updateNL1_2(); + if(!$this->isError()) $this->setting->updateVersion('1.3'); + } + + /** + * Upgrade from 1.3 to 1.4. + * + * @access private + * @return void + */ + private function upgradeFrom1_3To1_4() + { + $this->execSQL($this->getUpgradeFile('1.3')); + $this->updateNL1_3(); + $this->updateTasks(); + if(!$this->isError()) $this->setting->updateVersion('1.4'); + } + + /** + * Upgrade from 1.4 to 1.5. + * + * @access private + * @return void + */ + private function upgradeFrom1_4To1_5() + { + $this->execSQL($this->getUpgradeFile('1.4')); + if(!$this->isError()) $this->setting->updateVersion('1.5'); + } + + /** + * Upgrade from 1.5 to 2.0. + * + * @access private + * @return void + */ + private function upgradeFrom1_5To2_0() + { + $this->execSQL($this->getUpgradeFile('1.5')); + if(!$this->isError()) $this->setting->updateVersion('2.0'); + } + + /** + * Upgrade from 2.0 to 2.1. + * + * @access private + * @return void + */ + private function upgradeFrom2_0To2_1() + { + $this->execSQL($this->getUpgradeFile('2.0')); + if(!$this->isError()) $this->setting->updateVersion('2.1'); + } + + /** + * Upgrade from 2.1 to 2.2. + * + * @access private + * @return void + */ + private function upgradeFrom2_1To2_2() + { + $this->execSQL($this->getUpgradeFile('2.1')); + if(!$this->isError()) $this->setting->updateVersion('2.2'); + } + + /** + * Upgrade from 2.2 to 2.3. + * + * @access private + * @return void + */ + private function upgradeFrom2_2To2_3() + { + $this->execSQL($this->getUpgradeFile('2.2')); + $this->updateCases(); + $this->updateActivatedCountOfBug(); + if(!$this->isError()) $this->setting->updateVersion('2.3'); + } + + /** + * Upgrade from 2.3 to 2.4. + * + * @access private + * @return void + */ + private function upgradeFrom2_3To2_4() + { + $this->execSQL($this->getUpgradeFile('2.3')); + if(!$this->isError()) $this->setting->updateVersion('2.4'); + } + + /** + * Upgrade from 2.4 to 3.0.beta1. + * + * @access private + * @return void + */ + private function upgradeFrom2_4To3_0_beta1() + { + $this->execSQL($this->getUpgradeFile('2.4')); + if(!$this->isError()) $this->setting->updateVersion('3.0.beta1'); + } + + /** + * Update company field. + * + * This method is used to update since 1.0 beta. Any new tables added after 1.0 beta should skip. + * + * @access private + * @return void + */ + private function updateCompany() + { + /* Get user defined constants. */ + $constants = get_defined_constants(true); + $userConstants = $constants['user']; + + /* Update tables. */ + foreach($userConstants as $key => $value) + { + if(strpos($key, 'TABLE') === false) continue; + if($key == 'TABLE_COMPANY') continue; + + $table = $value; + $result = $this->dbh->query("SHOW TABLES LIKE '$table'"); + if($result->rowCount() > 0) + { + $this->dbh->query("UPDATE $table SET company = '{$this->app->company->id}'"); + } + } + } + + /** + * Update ubb code in bug table and user Templates table to html. + * + * @access private + * @return void + */ + private function updateUBB() + { + $this->app->loadClass('ubb', true); + + $bugs = $this->dao->select('id, steps')->from(TABLE_BUG)->fetchAll(); + $userTemplates = $this->dao->select('id, content')->from(TABLE_USERTPL)->fetchAll(); + + foreach($bugs as $id => $bug) + { + $bug->steps = ubb::parseUBB($bug->steps); + $this->dao->update(TABLE_BUG)->data($bug)->where('id')->eq($bug->id)->exec(); + } + foreach($userTemplates as $template) + { + $template->content = ubb::parseUBB($template->content); + $this->dao->update(TABLE_USERTPL)->data($template)->where('id')->eq($template->id)->exec(); + } + } + + /** + * Update nl to br from 1.2 version. + * + * @access public + * @return void + */ + public function updateNL1_2() + { + $tasks = $this->dao->select('id, `desc`')->from(TABLE_TASK)->fetchAll(); + $stories = $this->dao->select('story, version, spec')->from(TABLE_STORYSPEC)->fetchAll(); + $todos = $this->dao->select('id, `desc`')->from(TABLE_TODO)->fetchAll(); + $testTasks = $this->dao->select('id, `desc`')->from(TABLE_TESTTASK)->fetchAll(); + + foreach($tasks as $task) + { + $task->desc = nl2br($task->desc); + $this->dao->update(TABLE_TASK)->data($task)->where('id')->eq($task->id)->exec(); + } + foreach($stories as $story) + { + $story->spec = nl2br($story->spec); + $this->dao->update(TABLE_STORYSPEC)->data($story)->where('story')->eq($story->story)->andWhere('version')->eq($story->version)->exec(); + } + + foreach($todos as $todo) + { + $todo->desc = nl2br($todo->desc); + $this->dao->update(TABLE_TODO)->data($todo)->where('id')->eq($todo->id)->exec(); + } + + foreach($testTasks as $testtask) + { + $testtask->desc = nl2br($testtask->desc); + $this->dao->update(TABLE_TESTTASK)->data($testtask)->where('id')->eq($testtask->id)->exec(); + } + } + + /** + * Update nl to br from 1.3 version. + * + * @access public + * @return void + */ + public function updateNL1_3() + { + $products = $this->dao->select('id, `desc`')->from(TABLE_PRODUCT)->fetchAll(); + $plans = $this->dao->select('id, `desc`')->from(TABLE_PRODUCTPLAN)->fetchAll(); + $releases = $this->dao->select('id, `desc`')->from(TABLE_RELEASE)->fetchAll(); + $projects = $this->dao->select('id, `desc`, goal')->from(TABLE_PROJECT)->fetchAll(); + $builds = $this->dao->select('id, `desc`')->from(TABLE_BUILD)->fetchAll(); + + foreach($products as $product) + { + $product->desc = nl2br($product->desc); + $this->dao->update(TABLE_PRODUCT)->data($product)->where('id')->eq($product->id)->exec(); + } + + foreach($plans as $plan) + { + $plan->desc = nl2br($plan->desc); + $this->dao->update(TABLE_PRODUCTPLAN)->data($plan)->where('id')->eq($plan->id)->exec(); + } + + foreach($releases as $release) + { + $release->desc = nl2br($release->desc); + $this->dao->update(TABLE_RELEASE)->data($release)->where('id')->eq($release->id)->exec(); + } + + foreach($projects as $project) + { + $project->desc = nl2br($project->desc); + $project->goal = nl2br($project->goal); + $this->dao->update(TABLE_PROJECT)->data($project)->where('id')->eq($project->id)->exec(); + } + + foreach($builds as $build) + { + $build->desc = nl2br($build->desc); + $this->dao->update(TABLE_BUILD)->data($build)->where('id')->eq($build->id)->exec(); + } + } + + /** + * Update task fields. + * + * @access public + * @return void + */ + public function updateTasks() + { + /* Get all actions of tasks. */ + $actions = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectType')->eq('task') + ->orderBy('id') + ->fetchAll('id'); + + /* Get histories about status field. */ + $histories = $this->dao->select()->from(TABLE_HISTORY) + ->where('action')->in(array_keys($actions)) + ->andWhere('field')->eq('status') + ->orderBy('id') + ->fetchGroup('action'); + + $tasks = array(); + foreach($actions as $action) + { + if(!isset($tasks[$action->objectID])) + { + $tasks[$action->objectID] = new stdclass; + } + $task = $tasks[$action->objectID]; + + $task->id = $action->objectID; + $actionType = strtolower($action->action); + + /* Set the openedBy info. */ + if($actionType == 'opened') + { + $task->openedBy = $action->actor; + $task->openedDate = $action->date; + } + else + { + if(!isset($histories[$action->id])) continue; + + $actionHistories = $histories[$action->id]; + foreach($actionHistories as $history) + { + /* Finished by. */ + if($history->new == 'done') + { + $task->finishedBy = $action->actor; + $task->finishedDate = $action->date; + $action->action = 'finished'; + } + /* Canceled By. */ + elseif($history->new == 'cancel') + { + $task->canceledBy = $action->actor; + $task->canceledDate = $action->date; + $action->action = 'canceled'; + } + } + + /* Last edited by .*/ + $task->lastEditedBy = $action->actor; + $task->lastEditedDate = $action->date; + + /* Update action type. */ + $this->dao->update(TABLE_ACTION)->set('action')->eq($action->action)->where('id')->eq($action->id)->exec(false); + } + } + + /* Update db. */ + foreach($tasks as $task) + { + $this->dao->update(TABLE_TASK)->data($task, false)->where('id')->eq($task->id)->exec(false); + } + + $this->dao->update(TABLE_TASK)->set('assignedTo=openedBy, assignedDate = finishedDate')->where('status')->eq('done')->exec(false); + $this->dao->update(TABLE_TASK)->set('assignedTo=openedBy, assignedDate = canceledDate')->where('status')->eq('cancel')->exec(false); + + /* Update action name. */ + } + + /** + * Update activated count of Bug. + * + * @access public + * @return void + */ + private function updateActivatedCountOfBug() + { + $bugActivatedActions = $this->dao->select('*')->from(TABLE_ACTION)->where('action')->eq('activated')->andWhere('objectType')->eq('bug')->fetchAll(); + if(!empty($bugActivatedActions)) + { + foreach($bugActivatedActions as $action) + { + if(!isset($counts[$action->objectID])) $counts[$action->objectID] = 0; + $counts[$action->objectID] ++; + } + foreach($counts as $key => $count) + { + $this->dao->update(TABLE_BUG)->set('activatedCount')->eq($count)->where('id')->eq($key)->exec(); + } + } + } + + /** + * Update lastRun and lastResult field in zt_case + * + * @access public + * @return void + */ + public function updateCases() + { + $results = $this->dao->select('`case`, date, caseResult')->from(TABLE_TESTRESULT)->orderBy('id desc')->fetchGroup('case'); + foreach($results as $result) + { + $this->dao->update(TABLE_CASE) + ->set('lastRun')->eq($result[0]->date) + ->set('lastResult')->eq($result[0]->caseResult) + ->where('id')->eq($result[0]->case) + ->exec(); + } + } + + /** + * Delete the patch record. + * + * @access public + * @return void + */ + public function deletePatch() + { + $this->dao->delete()->from(TABLE_EXTENSION)->where('type')->eq('patch')->exec(false); + $this->dao->delete()->from(TABLE_EXTENSION)->where('code')->in('zentaopatch,patch')->exec(false); + } + + /** + * Get the upgrade sql file. + * + * @param string $version + * @access private + * @return string + */ + private function getUpgradeFile($version) + { + return $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'update' . $version . '.sql'; + } + + /** + * Execute a sql. + * + * @param string $sqlFile + * @access private + * @return void + */ + private function execSQL($sqlFile) + { + $mysqlVersion = $this->loadModel('install')->getMysqlVersion(); + + /* Read the sql file to lines, remove the comment lines, then join theme by ';'. */ + $sqls = explode("\n", file_get_contents($sqlFile)); + foreach($sqls as $key => $line) + { + $line = trim($line); + $sqls[$key] = $line; + if(strpos($line, '--') !== false or empty($line)) unset($sqls[$key]); + } + $sqls = explode(';', join("\n", $sqls)); + + foreach($sqls as $sql) + { + $sql = trim($sql); + if(empty($sql)) continue; + + if($mysqlVersion <= 4.1) + { + $sql = str_replace('DEFAULT CHARSET=utf8', '', $sql); + $sql = str_replace('CHARACTER SET utf8 COLLATE utf8_general_ci', '', $sql); + } + + $sql = str_replace('zt_', $this->config->db->prefix, $sql); + try + { + $this->dbh->exec($sql); + } + catch (PDOException $e) + { + self::$errors[] = $e->getMessage() . "

              The sql is: $sql

              "; + } + } + } + + /** + * Judge any error occers. + * + * @access public + * @return bool + */ + public function isError() + { + return !empty(self::$errors); + } + + /** + * Get errors during the upgrading. + * + * @access public + * @return array + */ + public function getError() + { + $errors = self::$errors; + self::$errors = array(); + return $errors; + } +} diff --git a/module/upgrade/view/confirm.html.php b/module/upgrade/view/confirm.html.php index b975f33cd8..fc9d901350 100644 --- a/module/upgrade/view/confirm.html.php +++ b/module/upgrade/view/confirm.html.php @@ -1,26 +1,26 @@ - - * @package upgrade - * @version $Id$ - */ -?> - - -
              -
              '> - - - - - - - -
              upgrade->confirm;?>
              upgrade->sureExecute) . html::hidden('fromVersion', $fromVersion);?>
              -
              -
              - + + * @package upgrade + * @version $Id$ + */ +?> + + +
              +
              '> + + + + + + + +
              upgrade->confirm;?>
              upgrade->sureExecute) . html::hidden('fromVersion', $fromVersion);?>
              +
              +
              + diff --git a/module/upgrade/view/execute.html.php b/module/upgrade/view/execute.html.php index 206ac354ff..432afa9da3 100644 --- a/module/upgrade/view/execute.html.php +++ b/module/upgrade/view/execute.html.php @@ -1,30 +1,30 @@ - - * @package upgrade - * @version $Id$ - */ -?> - - - - - - -
              upgrade->$result;?>
              - upgrade->tohome, 'index.php'); - } - ?> -
              - + + * @package upgrade + * @version $Id$ + */ +?> + + + + + + +
              upgrade->$result;?>
              + upgrade->tohome, 'index.php'); + } + ?> +
              + diff --git a/module/upgrade/view/index.html.php b/module/upgrade/view/index.html.php index 57f1cd030c..31f639a889 100644 --- a/module/upgrade/view/index.html.php +++ b/module/upgrade/view/index.html.php @@ -1,22 +1,22 @@ - - * @package upgrade - * @version $Id$ - */ -?> - - - - - - - - - -
              upgrade->warnning;?>
              upgrade->warnningContent;?>
              upgrade->common, inlink('selectVersion'));?>
              - + + * @package upgrade + * @version $Id$ + */ +?> + + + + + + + + + +
              upgrade->warnning;?>
              upgrade->warnningContent;?>
              upgrade->common, inlink('selectVersion'));?>
              + diff --git a/module/upgrade/view/selectversion.html.php b/module/upgrade/view/selectversion.html.php index e13610859c..34e540201e 100644 --- a/module/upgrade/view/selectversion.html.php +++ b/module/upgrade/view/selectversion.html.php @@ -1,29 +1,29 @@ - - * @package upgrade - * @version $Id$ - */ -?> - -
              '> - - - - - - - - - - - - - -
              upgrade->selectVersion;?>
              upgrade->fromVersion;?>upgrade->fromVersions, $version) . "{$lang->upgrade->noteVersion}";?>
              upgrade->toVersion;?>version;?>
              upgrade->common);?>
              -
              - + + * @package upgrade + * @version $Id$ + */ +?> + +
              '> + + + + + + + + + + + + + +
              upgrade->selectVersion;?>
              upgrade->fromVersion;?>upgrade->fromVersions, $version) . "{$lang->upgrade->noteVersion}";?>
              upgrade->toVersion;?>version;?>
              upgrade->common);?>
              +
              + diff --git a/module/user/control.php b/module/user/control.php index 4c83a1d4d8..826c842d67 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -1,506 +1,506 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -class user extends control -{ - private $referer; - - /** - * Construct - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('company')->setMenu(); - $this->loadModel('dept'); - } - - /** - * View a user. - * - * @param string $account - * @access public - * @return void - */ - public function view($account) - { - $this->locate($this->createLink('user', 'profile', "account=$account")); - } - - /** - * Todos of a user. - * - * @param string $account - * @param string $type the tod type, today|lastweek|thisweek|all|undone, or a date. - * @param string $status - * @access public - * @return void - */ - public function todo($account, $type = 'today', $status = 'all') - { - /* Set thie url to session. */ - $uri = $this->app->getURI(true); - $this->session->set('todoList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('taskList', $uri); - - /* set menus. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - /* Get user, totos. */ - $user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $todos = $this->loadModel('todo')->getList($type, $account, $status); - $date = (int)$type == 0 ? $this->todo->today() : $type; - - $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->user->todo; - $position[] = $this->lang->user->todo; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->tabID = 'todo'; - $this->view->dates = $this->todo->buildDateList(); - $this->view->date = $date; - $this->view->todos = $todos; - $this->view->user = $user; - $this->view->account = $account; - $this->view->type = $type; - - $this->display(); - } - - /** - * Taskes of a user. - * - * @param string $account - * @access public - * @return void - */ - public function task($account) - { - /* Save the session. */ - $this->session->set('taskList', $this->app->getURI(true)); - - /* Set the menu. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - /* Assign. */ - $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->task; - $position[] = $this->lang->user->task; - $this->view->header = $header; - $this->view->position = $position; - $this->view->tabID = 'task'; - $this->view->tasks = $this->loadModel('task')->getUserTasks($account); - $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - - $this->display(); - } - - /** - * User bugs. - * - * @param string $account - * @access public - * @return void - */ - public function bug($account) - { - /* Save the session. */ - $this->session->set('bugList', $this->app->getURI(true)); - - /* Set menu. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - /* Load the lang of bug module. */ - $this->app->loadLang('bug'); - - $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->bug; - $position[] = $this->lang->user->bug; - - $this->view->header = $header; - $this->view->position = $position; - $this->view->tabID = 'bug'; - $this->view->bugs = $this->user->getBugs($account); - $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $this->view->users = $this->user->getPairs('noletter'); - - $this->display(); - } - - /** - * User projects. - * - * @param string $account - * @access public - * @return void - */ - public function project($account) - { - /* Set the menus. */ - $this->loadModel('project'); - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->project; - $position[] = $this->lang->user->project; - $this->view->header = $header; - $this->view->position = $position; - $this->view->tabID = 'project'; - $this->view->projects = $this->user->getProjects($account); - $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - - $this->display(); - } - - /** - * The profile of a user. - * - * @param string $account - * @access public - * @return void - */ - public function profile($account) - { - $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->profile; - $position[] = $this->lang->user->profile; - - /* Set menu. */ - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - $user = $this->user->getById($account); - $deptPath = $this->dept->getParents($user->dept); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->user = $user; - - $this->view->deptPath = $deptPath; - - $this->display(); - } - - /** - * Set the rerferer. - * - * @param string $referer - * @access private - * @return void - */ - private function setReferer($referer = '') - { - if(!empty($referer)) - { - $this->referer = helper::safe64Decode($referer); - } - else - { - $this->referer = $this->server->http_referer ? $this->server->http_referer: ''; - } - } - - /** - * Create a suer. - * - * @param int $deptID - * @access public - * @return void - */ - public function create($deptID = 0) - { - $this->lang->set('menugroup.user', 'company'); - $this->lang->user->menu = $this->lang->company->menu; - - if(!empty($_POST)) - { - $this->user->create(); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('company', 'browse'), 'parent')); - } - - $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->create; - $position[] = $this->lang->user->create; - $this->view->header = $header; - $this->view->position = $position; - $this->view->depts = $this->dept->getOptionMenu(); - $this->view->deptID = $deptID; - - $this->display(); - } - - /** - * Edit a user. - * - * @param string|int $userID the int user id or account - * @access public - * @return void - */ - public function edit($userID) - { - $this->lang->set('menugroup.user', 'company'); - $this->lang->user->menu = $this->lang->company->menu; - if(!empty($_POST)) - { - $this->user->update($userID); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('company', 'browse'), 'parent')); - } - - $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->edit; - $position[] = $this->lang->user->edit; - $this->view->header = $header; - $this->view->position = $position; - $this->view->user = $this->user->getById($userID); - $this->view->depts = $this->dept->getOptionMenu(); - - $this->display(); - } - - /** - * Delete a user. - * - * @param int $userID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($userID, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->user->confirmDelete, $this->createLink('user', 'delete', "userID=$userID&confirm=yes"))); - } - else - { - $this->user->delete(TABLE_USER, $userID); - die(js::locate($this->createLink('company', 'browse'), 'parent')); - } - } - - /** - * User login, identify him and authorize him. - * - * @access public - * @return void - */ - public function login($referer = '', $from = '') - { - $this->setReferer($referer); - - $loginLink = $this->createLink('user', 'login'); - $denyLink = $this->createLink('user', 'deny'); - - /* If user is logon, back to the rerferer. */ - if($this->user->isLogon()) - { - if(strpos($this->referer, $loginLink) === false and - strpos($this->referer, $denyLink) === false and - strpos($this->referer, $this->app->company->pms) !== false - ) - { - $this->locate($this->referer); - } - else - { - $this->locate($this->createLink($this->config->default->module)); - } - } - - /* Passed account and password by post or get. */ - if(!empty($_POST) or (isset($_GET['account']) and isset($_GET['password']))) - { - $account = ''; - $password = ''; - if($this->post->account) $account = $this->post->account; - if($this->get->account) $account = $this->get->account; - if($this->post->password) $password = $this->post->password; - if($this->get->password) $password = $this->get->password; - - $user = $this->user->identify($account, $password); - - if($user) - { - /* Authorize him and save to session. */ - $user->rights = $this->user->authorize($account); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - $this->loadModel('action')->create('user', $user->id, 'login'); - - /* Keep login. */ - if($this->post->keepLogin) $this->user->keepLogin($user); - - /* Go to the referer. */ - if($this->post->referer and - strpos($this->post->referer, $loginLink) === false and - strpos($this->post->referer, $denyLink) === false - ) - { - if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'success'))); - - /* Get the module and method of the referer. */ - if($this->config->requestType == 'PATH_INFO') - { - $path = substr($this->post->referer, strrpos($this->post->referer, '/') + 1); - $path = rtrim($path, '.html'); - list($module, $method) = explode($this->config->requestFix, $path); - } - else - { - $url = html_entity_decode($this->post->referer); - $param = substr($url, strrpos($url, '?') + 1); - list($module, $method) = explode('&', $param); - $module = str_replace('m=', '', $module); - $method = str_replace('f=', '', $method); - } - - if(common::hasPriv($module, $method)) - { - die(js::locate($this->post->referer, 'parent')); - } - else - { - die(js::locate($this->createLink($this->config->default->module), 'parent')); - } - } - else - { - if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'success'))); - die(js::locate($this->createLink($this->config->default->module), 'parent')); - } - } - else - { - if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'failed'))); - die(js::error($this->lang->user->loginFailed)); - } - } - else - { - $header['title'] = $this->lang->user->login; - $this->view->header = $header; - $this->view->referer = $this->referer; - $this->view->s = $this->loadModel('setting')->getItem('system', 'global', 'sn'); - $this->view->keepLogin = $this->cookie->keepLogin ? $this->cookie->keepLogin : 'off'; - $this->display(); - } - } - - /** - * Deny page. - * - * @param string $module - * @param string $method - * @param string $refererBeforeDeny the referer of the denied page. - * @access public - * @return void - */ - public function deny($module, $method, $refererBeforeDeny = '') - { - $this->setReferer(); - $header['title'] = $this->lang->user->deny; - $this->view->header = $header; - $this->view->module = $module; - $this->view->method = $method; - $this->view->denyPage = $this->referer; // The denied page. - $this->view->refererBeforeDeny = $refererBeforeDeny; // The referer of the denied page. - $this->app->loadLang($module); - $this->app->loadLang('my'); - $this->display(); - exit; - } - - /** - * Logout. - * - * @access public - * @return void - */ - public function logout($referer = 0) - { - $this->loadModel('action')->create('user', $this->app->user->id, 'logout'); - session_destroy(); - setcookie('za', false); - setcookie('zp', false); - $vars = !empty($referer) ? "referer=$referer" : ''; - $this->locate($this->createLink('user', 'login', $vars)); - } - - /** - * User dynamic. - * - * @param string $period - * @param string $account - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function dynamic($period = 'today', $account = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* set menus. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('productList', $uri); - $this->session->set('productPlanList', $uri); - $this->session->set('releaseList', $uri); - $this->session->set('storyList', $uri); - $this->session->set('projectList', $uri); - $this->session->set('taskList', $uri); - $this->session->set('buildList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('caseList', $uri); - $this->session->set('testtaskList', $uri); - - /* Set the pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic; - $this->view->position[] = $this->lang->company->dynamic; - - /* Assign. */ - $this->view->period = $period; - $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter'); - $this->view->account = $account; - $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager); - $this->display(); - } - - /** - * Get user for ajax - * - * @param string $requestID - * @param string $assignedTo - * @access public - * @return void - */ - public function ajaxGetUser($taskID = '', $assignedTo = '') - { - $users = $this->user->getPairs('noletter, noclosed'); - $html = "
              "; - $html .= html::select('assignedTo', $users, $assignedTo); - $html .= html::submitButton(); - $html .= '
              '; - echo $html; - } - -} + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +class user extends control +{ + private $referer; + + /** + * Construct + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('company')->setMenu(); + $this->loadModel('dept'); + } + + /** + * View a user. + * + * @param string $account + * @access public + * @return void + */ + public function view($account) + { + $this->locate($this->createLink('user', 'profile', "account=$account")); + } + + /** + * Todos of a user. + * + * @param string $account + * @param string $type the tod type, today|lastweek|thisweek|all|undone, or a date. + * @param string $status + * @access public + * @return void + */ + public function todo($account, $type = 'today', $status = 'all') + { + /* Set thie url to session. */ + $uri = $this->app->getURI(true); + $this->session->set('todoList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('taskList', $uri); + + /* set menus. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + /* Get user, totos. */ + $user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $todos = $this->loadModel('todo')->getList($type, $account, $status); + $date = (int)$type == 0 ? $this->todo->today() : $type; + + $header['title'] = $this->lang->company->orgView . $this->lang->colon . $this->lang->user->todo; + $position[] = $this->lang->user->todo; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->tabID = 'todo'; + $this->view->dates = $this->todo->buildDateList(); + $this->view->date = $date; + $this->view->todos = $todos; + $this->view->user = $user; + $this->view->account = $account; + $this->view->type = $type; + + $this->display(); + } + + /** + * Taskes of a user. + * + * @param string $account + * @access public + * @return void + */ + public function task($account) + { + /* Save the session. */ + $this->session->set('taskList', $this->app->getURI(true)); + + /* Set the menu. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + /* Assign. */ + $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->task; + $position[] = $this->lang->user->task; + $this->view->header = $header; + $this->view->position = $position; + $this->view->tabID = 'task'; + $this->view->tasks = $this->loadModel('task')->getUserTasks($account); + $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + + $this->display(); + } + + /** + * User bugs. + * + * @param string $account + * @access public + * @return void + */ + public function bug($account) + { + /* Save the session. */ + $this->session->set('bugList', $this->app->getURI(true)); + + /* Set menu. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + /* Load the lang of bug module. */ + $this->app->loadLang('bug'); + + $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->bug; + $position[] = $this->lang->user->bug; + + $this->view->header = $header; + $this->view->position = $position; + $this->view->tabID = 'bug'; + $this->view->bugs = $this->user->getBugs($account); + $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $this->view->users = $this->user->getPairs('noletter'); + + $this->display(); + } + + /** + * User projects. + * + * @param string $account + * @access public + * @return void + */ + public function project($account) + { + /* Set the menus. */ + $this->loadModel('project'); + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->project; + $position[] = $this->lang->user->project; + $this->view->header = $header; + $this->view->position = $position; + $this->view->tabID = 'project'; + $this->view->projects = $this->user->getProjects($account); + $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + + $this->display(); + } + + /** + * The profile of a user. + * + * @param string $account + * @access public + * @return void + */ + public function profile($account) + { + $header['title'] = $this->lang->user->common . $this->lang->colon . $this->lang->user->profile; + $position[] = $this->lang->user->profile; + + /* Set menu. */ + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + $user = $this->user->getById($account); + $deptPath = $this->dept->getParents($user->dept); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->user = $user; + + $this->view->deptPath = $deptPath; + + $this->display(); + } + + /** + * Set the rerferer. + * + * @param string $referer + * @access private + * @return void + */ + private function setReferer($referer = '') + { + if(!empty($referer)) + { + $this->referer = helper::safe64Decode($referer); + } + else + { + $this->referer = $this->server->http_referer ? $this->server->http_referer: ''; + } + } + + /** + * Create a suer. + * + * @param int $deptID + * @access public + * @return void + */ + public function create($deptID = 0) + { + $this->lang->set('menugroup.user', 'company'); + $this->lang->user->menu = $this->lang->company->menu; + + if(!empty($_POST)) + { + $this->user->create(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('company', 'browse'), 'parent')); + } + + $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->create; + $position[] = $this->lang->user->create; + $this->view->header = $header; + $this->view->position = $position; + $this->view->depts = $this->dept->getOptionMenu(); + $this->view->deptID = $deptID; + + $this->display(); + } + + /** + * Edit a user. + * + * @param string|int $userID the int user id or account + * @access public + * @return void + */ + public function edit($userID) + { + $this->lang->set('menugroup.user', 'company'); + $this->lang->user->menu = $this->lang->company->menu; + if(!empty($_POST)) + { + $this->user->update($userID); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('company', 'browse'), 'parent')); + } + + $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->edit; + $position[] = $this->lang->user->edit; + $this->view->header = $header; + $this->view->position = $position; + $this->view->user = $this->user->getById($userID); + $this->view->depts = $this->dept->getOptionMenu(); + + $this->display(); + } + + /** + * Delete a user. + * + * @param int $userID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($userID, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->user->confirmDelete, $this->createLink('user', 'delete', "userID=$userID&confirm=yes"))); + } + else + { + $this->user->delete(TABLE_USER, $userID); + die(js::locate($this->createLink('company', 'browse'), 'parent')); + } + } + + /** + * User login, identify him and authorize him. + * + * @access public + * @return void + */ + public function login($referer = '', $from = '') + { + $this->setReferer($referer); + + $loginLink = $this->createLink('user', 'login'); + $denyLink = $this->createLink('user', 'deny'); + + /* If user is logon, back to the rerferer. */ + if($this->user->isLogon()) + { + if(strpos($this->referer, $loginLink) === false and + strpos($this->referer, $denyLink) === false and + strpos($this->referer, $this->app->company->pms) !== false + ) + { + $this->locate($this->referer); + } + else + { + $this->locate($this->createLink($this->config->default->module)); + } + } + + /* Passed account and password by post or get. */ + if(!empty($_POST) or (isset($_GET['account']) and isset($_GET['password']))) + { + $account = ''; + $password = ''; + if($this->post->account) $account = $this->post->account; + if($this->get->account) $account = $this->get->account; + if($this->post->password) $password = $this->post->password; + if($this->get->password) $password = $this->get->password; + + $user = $this->user->identify($account, $password); + + if($user) + { + /* Authorize him and save to session. */ + $user->rights = $this->user->authorize($account); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + $this->loadModel('action')->create('user', $user->id, 'login'); + + /* Keep login. */ + if($this->post->keepLogin) $this->user->keepLogin($user); + + /* Go to the referer. */ + if($this->post->referer and + strpos($this->post->referer, $loginLink) === false and + strpos($this->post->referer, $denyLink) === false + ) + { + if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'success'))); + + /* Get the module and method of the referer. */ + if($this->config->requestType == 'PATH_INFO') + { + $path = substr($this->post->referer, strrpos($this->post->referer, '/') + 1); + $path = rtrim($path, '.html'); + list($module, $method) = explode($this->config->requestFix, $path); + } + else + { + $url = html_entity_decode($this->post->referer); + $param = substr($url, strrpos($url, '?') + 1); + list($module, $method) = explode('&', $param); + $module = str_replace('m=', '', $module); + $method = str_replace('f=', '', $method); + } + + if(common::hasPriv($module, $method)) + { + die(js::locate($this->post->referer, 'parent')); + } + else + { + die(js::locate($this->createLink($this->config->default->module), 'parent')); + } + } + else + { + if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'success'))); + die(js::locate($this->createLink($this->config->default->module), 'parent')); + } + } + else + { + if($this->app->getViewType() == 'json') die(json_encode(array('status' => 'failed'))); + die(js::error($this->lang->user->loginFailed)); + } + } + else + { + $header['title'] = $this->lang->user->login; + $this->view->header = $header; + $this->view->referer = $this->referer; + $this->view->s = $this->loadModel('setting')->getItem('system', 'global', 'sn'); + $this->view->keepLogin = $this->cookie->keepLogin ? $this->cookie->keepLogin : 'off'; + $this->display(); + } + } + + /** + * Deny page. + * + * @param string $module + * @param string $method + * @param string $refererBeforeDeny the referer of the denied page. + * @access public + * @return void + */ + public function deny($module, $method, $refererBeforeDeny = '') + { + $this->setReferer(); + $header['title'] = $this->lang->user->deny; + $this->view->header = $header; + $this->view->module = $module; + $this->view->method = $method; + $this->view->denyPage = $this->referer; // The denied page. + $this->view->refererBeforeDeny = $refererBeforeDeny; // The referer of the denied page. + $this->app->loadLang($module); + $this->app->loadLang('my'); + $this->display(); + exit; + } + + /** + * Logout. + * + * @access public + * @return void + */ + public function logout($referer = 0) + { + $this->loadModel('action')->create('user', $this->app->user->id, 'logout'); + session_destroy(); + setcookie('za', false); + setcookie('zp', false); + $vars = !empty($referer) ? "referer=$referer" : ''; + $this->locate($this->createLink('user', 'login', $vars)); + } + + /** + * User dynamic. + * + * @param string $period + * @param string $account + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function dynamic($period = 'today', $account = '', $orderBy = 'date_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* set menus. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('productList', $uri); + $this->session->set('productPlanList', $uri); + $this->session->set('releaseList', $uri); + $this->session->set('storyList', $uri); + $this->session->set('projectList', $uri); + $this->session->set('taskList', $uri); + $this->session->set('buildList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('caseList', $uri); + $this->session->set('testtaskList', $uri); + + /* Set the pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + $this->view->header->title = $this->lang->company->common . $this->lang->colon . $this->lang->company->dynamic; + $this->view->position[] = $this->lang->company->dynamic; + + /* Assign. */ + $this->view->period = $period; + $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter'); + $this->view->account = $account; + $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager); + $this->display(); + } + + /** + * Get user for ajax + * + * @param string $requestID + * @param string $assignedTo + * @access public + * @return void + */ + public function ajaxGetUser($taskID = '', $assignedTo = '') + { + $users = $this->user->getPairs('noletter, noclosed'); + $html = "
              "; + $html .= html::select('assignedTo', $users, $assignedTo); + $html .= html::submitButton(); + $html .= '
              '; + echo $html; + } + +} diff --git a/module/user/lang/en.php b/module/user/lang/en.php index 45f2015605..f2ee4acdc4 100644 --- a/module/user/lang/en.php +++ b/module/user/lang/en.php @@ -1,82 +1,82 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->user->common = 'User'; -$lang->user->index = "Index"; -$lang->user->view = "Info"; -$lang->user->create = "Add"; -$lang->user->read = "Info"; -$lang->user->edit = "Edit"; -$lang->user->update = "Upgrade"; -$lang->user->delete = "Delete"; -$lang->user->browse = "Browse"; -$lang->user->login = "Login"; -$lang->user->userView = "User view"; -$lang->user->editProfile = "Edit profile"; -$lang->user->editPassword = "Change password"; -$lang->user->deny = "Denied"; -$lang->user->confirmDelete = "Are you sure to delete this user?"; -$lang->user->confirmActivate = "Are you sure to activate this user?"; -$lang->user->relogin = "Relogin"; -$lang->user->asGuest = "Guest"; -$lang->user->goback = "Back"; -$lang->user->allUsers = 'All users'; -$lang->user->deleted = '(deleted)'; -$lang->user->select = '--select user--'; - -$lang->user->profile = 'Profile'; -$lang->user->project = 'Project'; -$lang->user->task = 'Task'; -$lang->user->bug = 'Bug'; -$lang->user->todo = 'Todo'; -$lang->user->story = 'Story'; -$lang->user->team = 'Team'; -$lang->user->dynamic = 'Dynamic'; -$lang->user->ajaxGetUser = 'AJAX:get users'; -$lang->user->editProfile = 'Edit profile'; - -$lang->user->errorDeny = "Sorry, you can't access the %s module's %s feature"; -$lang->user->loginFailed = "Login failed, please check your account and password."; - -$lang->user->genderList->m = 'Male'; -$lang->user->genderList->f = 'Female'; - -$lang->user->statusList['active'] = 'Activate'; -$lang->user->statusList['delete'] = 'Deleted'; -$lang->user->keepLogin['on'] = 'Keep login'; - -$lang->user->id = 'ID'; -$lang->user->company = 'Company'; -$lang->user->dept = 'Department'; -$lang->user->account = 'Account'; -$lang->user->password = 'Password'; -$lang->user->password2 = 'Repeat password'; -$lang->user->realname = 'Fullname'; -$lang->user->nickname = 'Nickname'; -$lang->user->commiter = 'Commit account'; -$lang->user->avatar = 'Avatar'; -$lang->user->birthyear = 'Birth year'; -$lang->user->gender = 'Gender'; -$lang->user->email = 'Email'; -$lang->user->msn = 'MSN'; -$lang->user->qq = 'QQ'; -$lang->user->yahoo = 'Yahoo!'; -$lang->user->gtalk = 'GTalk'; -$lang->user->wangwang = 'Wangwang'; -$lang->user->mobile = 'Mobile'; -$lang->user->phone = 'Phone'; -$lang->user->address = 'Address'; -$lang->user->zipcode = 'Zipcode'; -$lang->user->join = 'Join date'; -$lang->user->visits = 'Visits'; -$lang->user->ip = 'Last IP'; -$lang->user->last = 'Last login'; -$lang->user->status = 'Status'; + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->user->common = 'User'; +$lang->user->index = "Index"; +$lang->user->view = "Info"; +$lang->user->create = "Add"; +$lang->user->read = "Info"; +$lang->user->edit = "Edit"; +$lang->user->update = "Upgrade"; +$lang->user->delete = "Delete"; +$lang->user->browse = "Browse"; +$lang->user->login = "Login"; +$lang->user->userView = "User view"; +$lang->user->editProfile = "Edit profile"; +$lang->user->editPassword = "Change password"; +$lang->user->deny = "Denied"; +$lang->user->confirmDelete = "Are you sure to delete this user?"; +$lang->user->confirmActivate = "Are you sure to activate this user?"; +$lang->user->relogin = "Relogin"; +$lang->user->asGuest = "Guest"; +$lang->user->goback = "Back"; +$lang->user->allUsers = 'All users'; +$lang->user->deleted = '(deleted)'; +$lang->user->select = '--select user--'; + +$lang->user->profile = 'Profile'; +$lang->user->project = 'Project'; +$lang->user->task = 'Task'; +$lang->user->bug = 'Bug'; +$lang->user->todo = 'Todo'; +$lang->user->story = 'Story'; +$lang->user->team = 'Team'; +$lang->user->dynamic = 'Dynamic'; +$lang->user->ajaxGetUser = 'AJAX:get users'; +$lang->user->editProfile = 'Edit profile'; + +$lang->user->errorDeny = "Sorry, you can't access the %s module's %s feature"; +$lang->user->loginFailed = "Login failed, please check your account and password."; + +$lang->user->genderList->m = 'Male'; +$lang->user->genderList->f = 'Female'; + +$lang->user->statusList['active'] = 'Activate'; +$lang->user->statusList['delete'] = 'Deleted'; +$lang->user->keepLogin['on'] = 'Keep login'; + +$lang->user->id = 'ID'; +$lang->user->company = 'Company'; +$lang->user->dept = 'Department'; +$lang->user->account = 'Account'; +$lang->user->password = 'Password'; +$lang->user->password2 = 'Repeat password'; +$lang->user->realname = 'Fullname'; +$lang->user->nickname = 'Nickname'; +$lang->user->commiter = 'Commit account'; +$lang->user->avatar = 'Avatar'; +$lang->user->birthyear = 'Birth year'; +$lang->user->gender = 'Gender'; +$lang->user->email = 'Email'; +$lang->user->msn = 'MSN'; +$lang->user->qq = 'QQ'; +$lang->user->yahoo = 'Yahoo!'; +$lang->user->gtalk = 'GTalk'; +$lang->user->wangwang = 'Wangwang'; +$lang->user->mobile = 'Mobile'; +$lang->user->phone = 'Phone'; +$lang->user->address = 'Address'; +$lang->user->zipcode = 'Zipcode'; +$lang->user->join = 'Join date'; +$lang->user->visits = 'Visits'; +$lang->user->ip = 'Last IP'; +$lang->user->last = 'Last login'; +$lang->user->status = 'Status'; diff --git a/module/user/lang/zh-cn.php b/module/user/lang/zh-cn.php index 79028005df..339bd1987e 100644 --- a/module/user/lang/zh-cn.php +++ b/module/user/lang/zh-cn.php @@ -1,82 +1,82 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->user->common = '用户'; -$lang->user->index = "用户视图首页"; -$lang->user->view = "用户详情"; -$lang->user->create = "添加用户"; -$lang->user->read = "查看用户"; -$lang->user->edit = "编辑用户"; -$lang->user->update = "编辑用户"; -$lang->user->delete = "删除用户"; -$lang->user->browse = "浏览用户"; -$lang->user->login = "用户登录"; -$lang->user->userView = "人员视图"; -$lang->user->editProfile = "修改个人信息"; -$lang->user->editPassword = "修改密码"; -$lang->user->deny = "访问受限"; -$lang->user->confirmDelete = "您确认删除该用户吗?"; -$lang->user->confirmActivate = "您确认激活该用户吗?"; -$lang->user->relogin = "重新登录"; -$lang->user->asGuest = "游客访问"; -$lang->user->goback = "返回前一页"; -$lang->user->allUsers = '全部用户'; -$lang->user->deleted = '(已删除)'; -$lang->user->select = '--请选择用户--'; - -$lang->user->profile = '用户档案'; -$lang->user->project = '用户项目'; -$lang->user->task = '用户任务'; -$lang->user->bug = '用户Bug'; -$lang->user->todo = '用户TODO'; -$lang->user->story = '用户需求'; -$lang->user->team = '用户团队'; -$lang->user->dynamic = '用户动态'; -$lang->user->ajaxGetUser = '接口:获得用户'; -$lang->user->editProfile = '修改信息'; - -$lang->user->errorDeny = "抱歉,您无权访问『%s』模块的『%s』功能。请联系管理员获取权限。点击后退返回上页。"; -$lang->user->loginFailed = "登录失败,请检查您的用户名或密码是否填写正确。"; - -$lang->user->genderList->m = '男'; -$lang->user->genderList->f = '女'; - -$lang->user->statusList['active'] = '正常'; -$lang->user->statusList['delete'] = '删除'; -$lang->user->keepLogin['on'] = '保持登录'; - -$lang->user->id = '用户编号'; -$lang->user->company = '所属公司'; -$lang->user->dept = '所属部门'; -$lang->user->account = '用户名'; -$lang->user->password = '密码'; -$lang->user->password2 = '请重复密码'; -$lang->user->realname = '真实姓名'; -$lang->user->nickname = '昵称'; -$lang->user->commiter = '源代码提交帐号'; -$lang->user->avatar = '头像'; -$lang->user->birthyear = '出生年'; -$lang->user->gender = '性别'; -$lang->user->email = '邮箱'; -$lang->user->msn = 'MSN'; -$lang->user->qq = 'QQ'; -$lang->user->yahoo = '雅虎通'; -$lang->user->gtalk = 'GTalk'; -$lang->user->wangwang = '旺旺'; -$lang->user->mobile = '手机'; -$lang->user->phone = '电话'; -$lang->user->address = '通讯地址'; -$lang->user->zipcode = '邮编'; -$lang->user->join = '加入日期'; -$lang->user->visits = '访问次数'; -$lang->user->ip = '最后IP'; -$lang->user->last = '最后登录'; -$lang->user->status = '状态'; + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->user->common = '用户'; +$lang->user->index = "用户视图首页"; +$lang->user->view = "用户详情"; +$lang->user->create = "添加用户"; +$lang->user->read = "查看用户"; +$lang->user->edit = "编辑用户"; +$lang->user->update = "编辑用户"; +$lang->user->delete = "删除用户"; +$lang->user->browse = "浏览用户"; +$lang->user->login = "用户登录"; +$lang->user->userView = "人员视图"; +$lang->user->editProfile = "修改个人信息"; +$lang->user->editPassword = "修改密码"; +$lang->user->deny = "访问受限"; +$lang->user->confirmDelete = "您确认删除该用户吗?"; +$lang->user->confirmActivate = "您确认激活该用户吗?"; +$lang->user->relogin = "重新登录"; +$lang->user->asGuest = "游客访问"; +$lang->user->goback = "返回前一页"; +$lang->user->allUsers = '全部用户'; +$lang->user->deleted = '(已删除)'; +$lang->user->select = '--请选择用户--'; + +$lang->user->profile = '用户档案'; +$lang->user->project = '用户项目'; +$lang->user->task = '用户任务'; +$lang->user->bug = '用户Bug'; +$lang->user->todo = '用户TODO'; +$lang->user->story = '用户需求'; +$lang->user->team = '用户团队'; +$lang->user->dynamic = '用户动态'; +$lang->user->ajaxGetUser = '接口:获得用户'; +$lang->user->editProfile = '修改信息'; + +$lang->user->errorDeny = "抱歉,您无权访问『%s』模块的『%s』功能。请联系管理员获取权限。点击后退返回上页。"; +$lang->user->loginFailed = "登录失败,请检查您的用户名或密码是否填写正确。"; + +$lang->user->genderList->m = '男'; +$lang->user->genderList->f = '女'; + +$lang->user->statusList['active'] = '正常'; +$lang->user->statusList['delete'] = '删除'; +$lang->user->keepLogin['on'] = '保持登录'; + +$lang->user->id = '用户编号'; +$lang->user->company = '所属公司'; +$lang->user->dept = '所属部门'; +$lang->user->account = '用户名'; +$lang->user->password = '密码'; +$lang->user->password2 = '请重复密码'; +$lang->user->realname = '真实姓名'; +$lang->user->nickname = '昵称'; +$lang->user->commiter = '源代码提交帐号'; +$lang->user->avatar = '头像'; +$lang->user->birthyear = '出生年'; +$lang->user->gender = '性别'; +$lang->user->email = '邮箱'; +$lang->user->msn = 'MSN'; +$lang->user->qq = 'QQ'; +$lang->user->yahoo = '雅虎通'; +$lang->user->gtalk = 'GTalk'; +$lang->user->wangwang = '旺旺'; +$lang->user->mobile = '手机'; +$lang->user->phone = '电话'; +$lang->user->address = '通讯地址'; +$lang->user->zipcode = '邮编'; +$lang->user->join = '加入日期'; +$lang->user->visits = '访问次数'; +$lang->user->ip = '最后IP'; +$lang->user->last = '最后登录'; +$lang->user->status = '状态'; diff --git a/module/user/lang/zh-tw.php b/module/user/lang/zh-tw.php index ee611228e4..c544b18c5e 100644 --- a/module/user/lang/zh-tw.php +++ b/module/user/lang/zh-tw.php @@ -1,82 +1,82 @@ - - * @package user - * @version $Id: zh-tw.php 2464 2011-12-23 12:38:47Z wwccss $ - * @link http://www.zentao.net - */ -$lang->user->common = '用戶'; -$lang->user->index = "用戶視圖首頁"; -$lang->user->view = "用戶詳情"; -$lang->user->create = "添加用戶"; -$lang->user->read = "查看用戶"; -$lang->user->edit = "編輯用戶"; -$lang->user->update = "編輯用戶"; -$lang->user->delete = "刪除用戶"; -$lang->user->browse = "瀏覽用戶"; -$lang->user->login = "用戶登錄"; -$lang->user->userView = "人員視圖"; -$lang->user->editProfile = "修改個人信息"; -$lang->user->editPassword = "修改密碼"; -$lang->user->deny = "訪問受限"; -$lang->user->confirmDelete = "您確認刪除該用戶嗎?"; -$lang->user->confirmActivate = "您確認激活該用戶嗎?"; -$lang->user->relogin = "重新登錄"; -$lang->user->asGuest = "遊客訪問"; -$lang->user->goback = "返回前一頁"; -$lang->user->allUsers = '全部用戶'; -$lang->user->deleted = '(已刪除)'; -$lang->user->select = '--請選擇用戶--'; - -$lang->user->profile = '用戶檔案'; -$lang->user->project = '用戶項目'; -$lang->user->task = '用戶任務'; -$lang->user->bug = '用戶Bug'; -$lang->user->todo = '用戶TODO'; -$lang->user->story = '用戶需求'; -$lang->user->team = '用戶團隊'; -$lang->user->dynamic = '用戶動態'; -$lang->user->ajaxGetUser = '介面:獲得用戶'; -$lang->user->editProfile = '修改信息'; - -$lang->user->errorDeny = "抱歉,您無權訪問『%s』模組的『%s』功能。請聯繫管理員獲取權限。點擊後退返回上頁。"; -$lang->user->loginFailed = "登錄失敗,請檢查您的用戶名或密碼是否填寫正確。"; - -$lang->user->genderList->m = '男'; -$lang->user->genderList->f = '女'; - -$lang->user->statusList['active'] = '正常'; -$lang->user->statusList['delete'] = '刪除'; -$lang->user->keepLogin['on'] = '保持登錄'; - -$lang->user->id = '用戶編號'; -$lang->user->company = '所屬公司'; -$lang->user->dept = '所屬部門'; -$lang->user->account = '用戶名'; -$lang->user->password = '密碼'; -$lang->user->password2 = '請重複密碼'; -$lang->user->realname = '真實姓名'; -$lang->user->nickname = '暱稱'; -$lang->user->commiter = '原始碼提交帳號'; -$lang->user->avatar = '頭像'; -$lang->user->birthyear = '出生年'; -$lang->user->gender = '性別'; -$lang->user->email = '郵箱'; -$lang->user->msn = 'MSN'; -$lang->user->qq = 'QQ'; -$lang->user->yahoo = '雅虎通'; -$lang->user->gtalk = 'GTalk'; -$lang->user->wangwang = '旺旺'; -$lang->user->mobile = '手機'; -$lang->user->phone = '電話'; -$lang->user->address = '通訊地址'; -$lang->user->zipcode = '郵編'; -$lang->user->join = '加入日期'; -$lang->user->visits = '訪問次數'; -$lang->user->ip = '最後IP'; -$lang->user->last = '最後登錄'; -$lang->user->status = '狀態'; + + * @package user + * @version $Id: zh-tw.php 2464 2011-12-23 12:38:47Z wwccss $ + * @link http://www.zentao.net + */ +$lang->user->common = '用戶'; +$lang->user->index = "用戶視圖首頁"; +$lang->user->view = "用戶詳情"; +$lang->user->create = "添加用戶"; +$lang->user->read = "查看用戶"; +$lang->user->edit = "編輯用戶"; +$lang->user->update = "編輯用戶"; +$lang->user->delete = "刪除用戶"; +$lang->user->browse = "瀏覽用戶"; +$lang->user->login = "用戶登錄"; +$lang->user->userView = "人員視圖"; +$lang->user->editProfile = "修改個人信息"; +$lang->user->editPassword = "修改密碼"; +$lang->user->deny = "訪問受限"; +$lang->user->confirmDelete = "您確認刪除該用戶嗎?"; +$lang->user->confirmActivate = "您確認激活該用戶嗎?"; +$lang->user->relogin = "重新登錄"; +$lang->user->asGuest = "遊客訪問"; +$lang->user->goback = "返回前一頁"; +$lang->user->allUsers = '全部用戶'; +$lang->user->deleted = '(已刪除)'; +$lang->user->select = '--請選擇用戶--'; + +$lang->user->profile = '用戶檔案'; +$lang->user->project = '用戶項目'; +$lang->user->task = '用戶任務'; +$lang->user->bug = '用戶Bug'; +$lang->user->todo = '用戶TODO'; +$lang->user->story = '用戶需求'; +$lang->user->team = '用戶團隊'; +$lang->user->dynamic = '用戶動態'; +$lang->user->ajaxGetUser = '介面:獲得用戶'; +$lang->user->editProfile = '修改信息'; + +$lang->user->errorDeny = "抱歉,您無權訪問『%s』模組的『%s』功能。請聯繫管理員獲取權限。點擊後退返回上頁。"; +$lang->user->loginFailed = "登錄失敗,請檢查您的用戶名或密碼是否填寫正確。"; + +$lang->user->genderList->m = '男'; +$lang->user->genderList->f = '女'; + +$lang->user->statusList['active'] = '正常'; +$lang->user->statusList['delete'] = '刪除'; +$lang->user->keepLogin['on'] = '保持登錄'; + +$lang->user->id = '用戶編號'; +$lang->user->company = '所屬公司'; +$lang->user->dept = '所屬部門'; +$lang->user->account = '用戶名'; +$lang->user->password = '密碼'; +$lang->user->password2 = '請重複密碼'; +$lang->user->realname = '真實姓名'; +$lang->user->nickname = '暱稱'; +$lang->user->commiter = '原始碼提交帳號'; +$lang->user->avatar = '頭像'; +$lang->user->birthyear = '出生年'; +$lang->user->gender = '性別'; +$lang->user->email = '郵箱'; +$lang->user->msn = 'MSN'; +$lang->user->qq = 'QQ'; +$lang->user->yahoo = '雅虎通'; +$lang->user->gtalk = 'GTalk'; +$lang->user->wangwang = '旺旺'; +$lang->user->mobile = '手機'; +$lang->user->phone = '電話'; +$lang->user->address = '通訊地址'; +$lang->user->zipcode = '郵編'; +$lang->user->join = '加入日期'; +$lang->user->visits = '訪問次數'; +$lang->user->ip = '最後IP'; +$lang->user->last = '最後登錄'; +$lang->user->status = '狀態'; diff --git a/module/user/model.php b/module/user/model.php index 477d66c402..0e12bfc4e3 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1,411 +1,411 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->getMethodName(); - $selectHtml = html::select('account', $users, $account, "onchange=\"switchAccount(this.value, '$methodName')\""); - foreach($this->lang->user->menu as $key => $value) - { - $replace = ($key == 'account') ? $selectHtml : $account; - common::setMenuVars($this->lang->user->menu, $key, $replace); - } - } - - /** - * Get users list of current company. - * - * @access public - * @return void - */ - public function getList() - { - return $this->dao->select('*')->from(TABLE_USER)->where('deleted')->eq(0)->orderBy('account')->fetchAll(); - } - - /** - * Get the account=>relaname pairs. - * - * @param string $params noletter|noempty|noclosed|nodeleted|withguest, can be sets of theme - * @access public - * @return array - */ - public function getPairs($params = '') - { - $users = $this->dao->select('account, realname')->from(TABLE_USER) - ->where('deleted')->eq(0) - ->beginIF(strpos($params, 'nodeleted') !== false) - ->fi() - ->orderBy('account')->fetchPairs(); - foreach($users as $account => $realName) - { - $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; - if(strpos($params, 'noletter') !== false) $firstLetter = ''; - $users[$account] = $firstLetter . ($realName ? $realName : $account); - } - if(strpos($params, 'noempty') === false) $users = array('' => '') + $users; - if(strpos($params, 'noclosed') === false) $users = $users + array('closed' => 'Closed'); - if(strpos($params, 'withguest') !== false) $users = $users + array('guest' => 'Guest'); - return $users; - } - - /** - * Get commiters from the user table. - * - * @access public - * @return array - */ - public function getCommiters() - { - $rawCommiters = $this->dao->select('commiter, account, realname')->from(TABLE_USER)->where('commiter')->ne('')->fetchAll(); - if(!$rawCommiters) return array(); - - $commiters = array(); - foreach($rawCommiters as $commiter) $commiters[$commiter->commiter] = $commiter->realname ? $commiter->realname : $commiter->account; - - return $commiters; - } - - /** - * Appened deleted users to the user list. - * - * @param array $users - * @param string $deleteds the deleted users, can be a list - * @access public - * @return array new user lists with deleted users. - */ - public function appendDeleted($users, $deleteds = '') - { - $deleteds = explode(',', $deleteds); - foreach($deleteds as $deleted) - { - if(!isset($users[$deleted])) $users[$deleted] = $deleted . $this->lang->user->deleted; - } - return $users; - } - - /** - * Get user list with email and real name. - * - * @param string|array $users - * @access public - * @return array - */ - public function getRealNameAndEmails($users) - { - $users = $this->dao->select('account, email, realname')->from(TABLE_USER)->where('account')->in($users)->fetchAll('account'); - if(!$users) return array(); - foreach($users as $account => $user) if($user->realname == '') $user->realname = $account; - return $users; - } - - /** - * Get user info by ID. - * - * @param int $userID - * @access public - * @return object|bool - */ - public function getById($userID) - { - $user = $this->dao->select('*')->from(TABLE_USER) - ->beginIF(is_numeric($userID))->where('id')->eq((int)$userID)->fi() - ->beginIF(!is_numeric($userID))->where('account')->eq($userID)->fi() - ->fetch(); - if(!$user) return false; - $user->last = date(DT_DATETIME1, $user->last); - return $user; - } - - /** - * Create a user. - * - * @access public - * @return void - */ - public function create() - { - if(!$this->checkPassword()) return; - - $user = fixer::input('post') - ->setDefault('join', '0000-00-00') - ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) - ->setIF($this->post->password1 == false, 'password', '') - ->remove('password1, password2') - ->get(); - - $this->dao->insert(TABLE_USER)->data($user) - ->autoCheck() - ->batchCheck($this->config->user->create->requiredFields, 'notempty') - ->check('account', 'unique') - ->check('account', 'account') - ->checkIF($this->post->email != false, 'email', 'email') - ->exec(); - } - - /** - * Update a user. - * - * @param int $userID - * @access public - * @return void - */ - public function update($userID) - { - if(!$this->checkPassword()) return; - - $oldUser = $this->getById($userID); - - $userID = (int)$userID; - $user = fixer::input('post') - ->setDefault('join', '0000-00-00') - ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) - ->remove('password1, password2') - ->specialChars('msn,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode') - ->get(); - - $this->dao->update(TABLE_USER)->data($user) - ->autoCheck() - ->batchCheck($this->config->user->edit->requiredFields, 'notempty') - ->check('account', 'unique', "id != '$userID'") - ->check('account', 'account') - ->checkIF($this->post->email != false, 'email', 'email') - ->where('id')->eq((int)$userID) - ->exec(); - - /* If account changed, update the privilege. */ - if($this->post->account != $oldUser->account) - { - $this->dao->update(TABLE_USERGROUP)->set('account')->eq($this->post->account)->where('account')->eq($oldUser->account)->exec(); - if(strpos($this->app->company->admins, ',' . $oldUser->account . ',') !== false) - { - $admins = ',' . $this->post->account . ','; - $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); - } - } - } - - /** - * Check the passwds posted. - * - * @access public - * @return bool - */ - public function checkPassword() - { - if($this->post->password1 != false) - { - if($this->post->password1 != $this->post->password2) dao::$errors['password'][] = $this->lang->error->passwordsame; - if(!validater::checkReg($this->post->password1, '|(.){6,}|')) dao::$errors['password'][] = $this->lang->error->passwordrule; - } - return !dao::isError(); - } - - /** - * Identify a user. - * - * @param string $account the user account - * @param string $password the user password or auth hash - * @access public - * @return object - */ - public function identify($account, $password) - { - if(!$account or !$password) return false; - - /* Get the user first. If $password length is 32, don't add the password condition. */ - $user = $this->dao->select('*')->from(TABLE_USER) - ->where('account')->eq($account) - ->beginIF(strlen($password) < 32)->andWhere('password')->eq(md5($password))->fi() - ->andWhere('deleted')->eq(0) - ->fetch(); - - /* If the length of $password is 32 or 40, checking by the auth hash. */ - if($user and strlen($password) == 32) - { - $hash = $this->session->rand ? md5($user->password . $this->session->rand) : $user->password; - $user = $password == $hash ? $user : ''; - } - elseif($user and strlen($password) == 40) - { - $hash = sha1($user->account . $user->password . $user->last); - $user = $password == $hash ? $user : ''; - } - - if($user) - { - $ip = $this->server->remote_addr; - $last = $this->server->request_time; - $this->dao->update(TABLE_USER)->set('visits = visits + 1')->set('ip')->eq($ip)->set('last')->eq($last)->where('account')->eq($account)->exec(); - $user->last = date(DT_DATETIME1, $user->last); - } - return $user; - } - - /** - * Identify user by PHP_AUTH_USER. - * - * @access public - * @return void - */ - public function identifyByPhpAuth() - { - $account = $this->server->php_auth_user; - $password = $this->server->php_auth_pw; - $user = $this->identify($account, $password); - if(!$user) return false; - - $user->rights = $this->authorize($account); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - $this->loadModel('action')->create('user', $user->id, 'login'); - } - - /** - * Identify user by cookie. - * - * @access public - * @return void - */ - public function identifyByCookie() - { - $account = $this->cookie->za; - $authHash = $this->cookie->zp; - $user = $this->identify($account, $authHash); - if(!$user) return false; - - $user->rights = $this->authorize($account); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - $this->loadModel('action')->create('user', $user->id, 'login'); - - $this->keepLogin($user); - } - - /** - * Authorize a user. - * - * @param string $account - * @access public - * @return array the user rights. - */ - public function authorize($account) - { - $account = filter_var($account, FILTER_SANITIZE_STRING); - if(!$account) return false; - - $rights = array(); - if($account == 'guest') - { - $sql = $this->dao->select('module, method')->from(TABLE_GROUP)->alias('t1')->leftJoin(TABLE_GROUPPRIV)->alias('t2') - ->on('t1.id = t2.group')->where('t1.name')->eq('guest'); - } - else - { - $sql = $this->dao->select('module, method')->from(TABLE_USERGROUP)->alias('t1')->leftJoin(TABLE_GROUPPRIV)->alias('t2') - ->on('t1.group = t2.group') - ->where('t1.account')->eq($account); - } - $stmt = $sql->query(); - if(!$stmt) return $rights; - while($row = $stmt->fetch(PDO::FETCH_ASSOC)) - { - $rights[strtolower($row['module'])][strtolower($row['method'])] = true; - } - return $rights; - } - - /** - * Keep the user in login state. - * - * @param string $account - * @param string $password - * @access public - * @return void - */ - public function keepLogin($user) - { - setcookie('keepLogin', 'on', $this->config->cookieLife, $this->config->webRoot); - setcookie('za', $user->account, $this->config->cookieLife, $this->config->webRoot); - setcookie('zp', sha1($user->account . $user->password . $this->server->request_time), $this->config->cookieLife, $this->config->webRoot); - } - - /* - /** - * Judge a user is logon or not. - * - * @access public - * @return bool - */ - public function isLogon() - { - return ($this->session->user and $this->session->user->account != 'guest'); - } - - /** - * Get groups a user belongs to. - * - * @param string $account - * @access public - * @return array - */ - public function getGroups($account) - { - return $this->dao->findByAccount($account)->from(TABLE_USERGROUP)->fields('`group`')->fetchPairs(); - } - - /** - * Get projects a user participated. - * - * @param string $account - * @access public - * @return array - */ - public function getProjects($account) - { - return $this->dao->select('t1.*,t2.*')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.account')->eq($account) - ->andWhere('t2.deleted')->eq(0) - ->fetchAll(); - } - - /** - * Get bugs assigned to a user. - * - * @param string $account - * @access public - * @return array - */ - public function getBugs($account) - { - return $this->dao->select('t1.*') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t2.deleted')->eq(0) - ->andwhere('t1.deleted')->eq(0) - ->andwhere('t1.assignedTo')->eq($account) - ->fetchAll(); - } -} + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> +app->getMethodName(); + $selectHtml = html::select('account', $users, $account, "onchange=\"switchAccount(this.value, '$methodName')\""); + foreach($this->lang->user->menu as $key => $value) + { + $replace = ($key == 'account') ? $selectHtml : $account; + common::setMenuVars($this->lang->user->menu, $key, $replace); + } + } + + /** + * Get users list of current company. + * + * @access public + * @return void + */ + public function getList() + { + return $this->dao->select('*')->from(TABLE_USER)->where('deleted')->eq(0)->orderBy('account')->fetchAll(); + } + + /** + * Get the account=>relaname pairs. + * + * @param string $params noletter|noempty|noclosed|nodeleted|withguest, can be sets of theme + * @access public + * @return array + */ + public function getPairs($params = '') + { + $users = $this->dao->select('account, realname')->from(TABLE_USER) + ->where('deleted')->eq(0) + ->beginIF(strpos($params, 'nodeleted') !== false) + ->fi() + ->orderBy('account')->fetchPairs(); + foreach($users as $account => $realName) + { + $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; + if(strpos($params, 'noletter') !== false) $firstLetter = ''; + $users[$account] = $firstLetter . ($realName ? $realName : $account); + } + if(strpos($params, 'noempty') === false) $users = array('' => '') + $users; + if(strpos($params, 'noclosed') === false) $users = $users + array('closed' => 'Closed'); + if(strpos($params, 'withguest') !== false) $users = $users + array('guest' => 'Guest'); + return $users; + } + + /** + * Get commiters from the user table. + * + * @access public + * @return array + */ + public function getCommiters() + { + $rawCommiters = $this->dao->select('commiter, account, realname')->from(TABLE_USER)->where('commiter')->ne('')->fetchAll(); + if(!$rawCommiters) return array(); + + $commiters = array(); + foreach($rawCommiters as $commiter) $commiters[$commiter->commiter] = $commiter->realname ? $commiter->realname : $commiter->account; + + return $commiters; + } + + /** + * Appened deleted users to the user list. + * + * @param array $users + * @param string $deleteds the deleted users, can be a list + * @access public + * @return array new user lists with deleted users. + */ + public function appendDeleted($users, $deleteds = '') + { + $deleteds = explode(',', $deleteds); + foreach($deleteds as $deleted) + { + if(!isset($users[$deleted])) $users[$deleted] = $deleted . $this->lang->user->deleted; + } + return $users; + } + + /** + * Get user list with email and real name. + * + * @param string|array $users + * @access public + * @return array + */ + public function getRealNameAndEmails($users) + { + $users = $this->dao->select('account, email, realname')->from(TABLE_USER)->where('account')->in($users)->fetchAll('account'); + if(!$users) return array(); + foreach($users as $account => $user) if($user->realname == '') $user->realname = $account; + return $users; + } + + /** + * Get user info by ID. + * + * @param int $userID + * @access public + * @return object|bool + */ + public function getById($userID) + { + $user = $this->dao->select('*')->from(TABLE_USER) + ->beginIF(is_numeric($userID))->where('id')->eq((int)$userID)->fi() + ->beginIF(!is_numeric($userID))->where('account')->eq($userID)->fi() + ->fetch(); + if(!$user) return false; + $user->last = date(DT_DATETIME1, $user->last); + return $user; + } + + /** + * Create a user. + * + * @access public + * @return void + */ + public function create() + { + if(!$this->checkPassword()) return; + + $user = fixer::input('post') + ->setDefault('join', '0000-00-00') + ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) + ->setIF($this->post->password1 == false, 'password', '') + ->remove('password1, password2') + ->get(); + + $this->dao->insert(TABLE_USER)->data($user) + ->autoCheck() + ->batchCheck($this->config->user->create->requiredFields, 'notempty') + ->check('account', 'unique') + ->check('account', 'account') + ->checkIF($this->post->email != false, 'email', 'email') + ->exec(); + } + + /** + * Update a user. + * + * @param int $userID + * @access public + * @return void + */ + public function update($userID) + { + if(!$this->checkPassword()) return; + + $oldUser = $this->getById($userID); + + $userID = (int)$userID; + $user = fixer::input('post') + ->setDefault('join', '0000-00-00') + ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) + ->remove('password1, password2') + ->specialChars('msn,qq,yahoo,gtalk,wangwang,mobile,phone,address,zipcode') + ->get(); + + $this->dao->update(TABLE_USER)->data($user) + ->autoCheck() + ->batchCheck($this->config->user->edit->requiredFields, 'notempty') + ->check('account', 'unique', "id != '$userID'") + ->check('account', 'account') + ->checkIF($this->post->email != false, 'email', 'email') + ->where('id')->eq((int)$userID) + ->exec(); + + /* If account changed, update the privilege. */ + if($this->post->account != $oldUser->account) + { + $this->dao->update(TABLE_USERGROUP)->set('account')->eq($this->post->account)->where('account')->eq($oldUser->account)->exec(); + if(strpos($this->app->company->admins, ',' . $oldUser->account . ',') !== false) + { + $admins = ',' . $this->post->account . ','; + $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); + } + } + } + + /** + * Check the passwds posted. + * + * @access public + * @return bool + */ + public function checkPassword() + { + if($this->post->password1 != false) + { + if($this->post->password1 != $this->post->password2) dao::$errors['password'][] = $this->lang->error->passwordsame; + if(!validater::checkReg($this->post->password1, '|(.){6,}|')) dao::$errors['password'][] = $this->lang->error->passwordrule; + } + return !dao::isError(); + } + + /** + * Identify a user. + * + * @param string $account the user account + * @param string $password the user password or auth hash + * @access public + * @return object + */ + public function identify($account, $password) + { + if(!$account or !$password) return false; + + /* Get the user first. If $password length is 32, don't add the password condition. */ + $user = $this->dao->select('*')->from(TABLE_USER) + ->where('account')->eq($account) + ->beginIF(strlen($password) < 32)->andWhere('password')->eq(md5($password))->fi() + ->andWhere('deleted')->eq(0) + ->fetch(); + + /* If the length of $password is 32 or 40, checking by the auth hash. */ + if($user and strlen($password) == 32) + { + $hash = $this->session->rand ? md5($user->password . $this->session->rand) : $user->password; + $user = $password == $hash ? $user : ''; + } + elseif($user and strlen($password) == 40) + { + $hash = sha1($user->account . $user->password . $user->last); + $user = $password == $hash ? $user : ''; + } + + if($user) + { + $ip = $this->server->remote_addr; + $last = $this->server->request_time; + $this->dao->update(TABLE_USER)->set('visits = visits + 1')->set('ip')->eq($ip)->set('last')->eq($last)->where('account')->eq($account)->exec(); + $user->last = date(DT_DATETIME1, $user->last); + } + return $user; + } + + /** + * Identify user by PHP_AUTH_USER. + * + * @access public + * @return void + */ + public function identifyByPhpAuth() + { + $account = $this->server->php_auth_user; + $password = $this->server->php_auth_pw; + $user = $this->identify($account, $password); + if(!$user) return false; + + $user->rights = $this->authorize($account); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + $this->loadModel('action')->create('user', $user->id, 'login'); + } + + /** + * Identify user by cookie. + * + * @access public + * @return void + */ + public function identifyByCookie() + { + $account = $this->cookie->za; + $authHash = $this->cookie->zp; + $user = $this->identify($account, $authHash); + if(!$user) return false; + + $user->rights = $this->authorize($account); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + $this->loadModel('action')->create('user', $user->id, 'login'); + + $this->keepLogin($user); + } + + /** + * Authorize a user. + * + * @param string $account + * @access public + * @return array the user rights. + */ + public function authorize($account) + { + $account = filter_var($account, FILTER_SANITIZE_STRING); + if(!$account) return false; + + $rights = array(); + if($account == 'guest') + { + $sql = $this->dao->select('module, method')->from(TABLE_GROUP)->alias('t1')->leftJoin(TABLE_GROUPPRIV)->alias('t2') + ->on('t1.id = t2.group')->where('t1.name')->eq('guest'); + } + else + { + $sql = $this->dao->select('module, method')->from(TABLE_USERGROUP)->alias('t1')->leftJoin(TABLE_GROUPPRIV)->alias('t2') + ->on('t1.group = t2.group') + ->where('t1.account')->eq($account); + } + $stmt = $sql->query(); + if(!$stmt) return $rights; + while($row = $stmt->fetch(PDO::FETCH_ASSOC)) + { + $rights[strtolower($row['module'])][strtolower($row['method'])] = true; + } + return $rights; + } + + /** + * Keep the user in login state. + * + * @param string $account + * @param string $password + * @access public + * @return void + */ + public function keepLogin($user) + { + setcookie('keepLogin', 'on', $this->config->cookieLife, $this->config->webRoot); + setcookie('za', $user->account, $this->config->cookieLife, $this->config->webRoot); + setcookie('zp', sha1($user->account . $user->password . $this->server->request_time), $this->config->cookieLife, $this->config->webRoot); + } + + /* + /** + * Judge a user is logon or not. + * + * @access public + * @return bool + */ + public function isLogon() + { + return ($this->session->user and $this->session->user->account != 'guest'); + } + + /** + * Get groups a user belongs to. + * + * @param string $account + * @access public + * @return array + */ + public function getGroups($account) + { + return $this->dao->findByAccount($account)->from(TABLE_USERGROUP)->fields('`group`')->fetchPairs(); + } + + /** + * Get projects a user participated. + * + * @param string $account + * @access public + * @return array + */ + public function getProjects($account) + { + return $this->dao->select('t1.*,t2.*')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.account')->eq($account) + ->andWhere('t2.deleted')->eq(0) + ->fetchAll(); + } + + /** + * Get bugs assigned to a user. + * + * @param string $account + * @access public + * @return array + */ + public function getBugs($account) + { + return $this->dao->select('t1.*') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t2.deleted')->eq(0) + ->andwhere('t1.deleted')->eq(0) + ->andwhere('t1.assignedTo')->eq($account) + ->fetchAll(); + } +} diff --git a/module/user/view/bug.html.php b/module/user/view/bug.html.php index 60ad3897ac..136df17fef 100644 --- a/module/user/view/bug.html.php +++ b/module/user/view/bug.html.php @@ -1,43 +1,43 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              idAB;?>bug->severityAB;?>priAB;?>typeAB;?>bug->title;?>openedByAB;?>bug->resolvedBy;?>bug->resolutionAB;?>
              createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>
              - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              idAB;?>bug->severityAB;?>priAB;?>typeAB;?>bug->title;?>openedByAB;?>bug->resolvedBy;?>bug->resolutionAB;?>
              createLink('bug', 'view', "bugID=$bug->id"), $bug->id, '_blank');?>bug->severityList[$bug->severity]?>bug->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>
              + diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index e32eb2ad73..1742a1c82c 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -1,57 +1,57 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              user->create;?>
              user->dept;?> -
              user->account;?>
              user->realname;?>
              user->commiter;?>
              user->email;?>
              user->join;?>
              user->gender;?>user->genderList, 'm');?>
              user->password;?>
              user->password2;?>
              -
              - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              user->create;?>
              user->dept;?> +
              user->account;?>
              user->realname;?>
              user->commiter;?>
              user->email;?>
              user->join;?>
              user->gender;?>user->genderList, 'm');?>
              user->password;?>
              user->password2;?>
              +
              + diff --git a/module/user/view/deny.html.php b/module/user/view/deny.html.php index 2e6cfd466f..78f60cf436 100644 --- a/module/user/view/deny.html.php +++ b/module/user/view/deny.html.php @@ -1,31 +1,31 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -include '../../common/view/header.lite.html.php'; -?> - - - - - -
              user->account, ' ', $lang->user->deny;?>
              - $module->common) ? $lang->$module->common: $module; - $methodName = isset($lang->$module->$method) ? $lang->$module->$method: $method; - - printf($lang->user->errorDeny, $moduleName, $methodName); - echo "
              "; - echo html::a($this->createLink($config->default->module), $lang->my->common); - if($refererBeforeDeny) echo html::a(helper::safe64Decode($refererBeforeDeny), $lang->user->goback); - echo html::a($this->createLink('user', 'logout', "referer=" . helper::safe64Encode($denyPage)), $lang->user->relogin); - ?> -
              - - + + * @package ZenTaoPMS + * @version $Id$ + */ +include '../../common/view/header.lite.html.php'; +?> + + + + + +
              user->account, ' ', $lang->user->deny;?>
              + $module->common) ? $lang->$module->common: $module; + $methodName = isset($lang->$module->$method) ? $lang->$module->$method: $method; + + printf($lang->user->errorDeny, $moduleName, $methodName); + echo "
              "; + echo html::a($this->createLink($config->default->module), $lang->my->common); + if($refererBeforeDeny) echo html::a(helper::safe64Decode($refererBeforeDeny), $lang->user->goback); + echo html::a($this->createLink('user', 'logout', "referer=" . helper::safe64Encode($denyPage)), $lang->user->relogin); + ?> +
              + + diff --git a/module/user/view/dynamic.html.php b/module/user/view/dynamic.html.php index 88684b7c87..09fc5911c4 100644 --- a/module/user/view/dynamic.html.php +++ b/module/user/view/dynamic.html.php @@ -1,58 +1,58 @@ -dynamic view file of dashboard module of ZenTaoPMS. - * - * @copyright Copyright 2009-2011 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) - * @license LGPL (http://www.gnu.org/licenses/lgpl.html) - * @author Chunsheng Wang - * @package dashboard - * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ - * @link http://www.zentao.net - */ -?> - - -
              - ' . html::a(inlink('dynamic', "type=today&account=$account"), $lang->action->dynamic->today) . ''; - echo '' . html::a(inlink('dynamic', "type=yesterday&account=$account"), $lang->action->dynamic->yesterday) . ''; - echo '' . html::a(inlink('dynamic', "type=twodaysago&account=$account"), $lang->action->dynamic->twoDaysAgo) . ''; - echo '' . html::a(inlink('dynamic', "type=thisweek&account=$account"), $lang->action->dynamic->thisWeek) . ''; - echo '' . html::a(inlink('dynamic', "type=lastweek&account=$account"), $lang->action->dynamic->lastWeek) . ''; - echo '' . html::a(inlink('dynamic', "type=thismonth&account=$account"), $lang->action->dynamic->thisMonth) . ''; - echo '' . html::a(inlink('dynamic', "type=lastmonth&account=$account"), $lang->action->dynamic->lastMonth) . ''; - echo '' . html::a(inlink('dynamic', "type=all&account=$account"), $lang->action->dynamic->all) . ''; - ?> -
              - - - - - - - - - - - - - - - objectType == 'case' ? 'testcase' : $action->objectType;?> - - - - - - - - - - - -
              action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
              date;?>actor];?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
              show();?>
              - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2012 青岛易软天创网络科技有限公司 (QingDao Nature Easy Soft Network Technology Co,LTD www.cnezsoft.com) + * @license LGPL (http://www.gnu.org/licenses/lgpl.html) + * @author Chunsheng Wang + * @package dashboard + * @version $Id: action->dynamic.html.php 1477 2011-03-01 15:25:50Z wwccss $ + * @link http://www.zentao.net + */ +?> + + +
              + ' . html::a(inlink('dynamic', "type=today&account=$account"), $lang->action->dynamic->today) . ''; + echo '' . html::a(inlink('dynamic', "type=yesterday&account=$account"), $lang->action->dynamic->yesterday) . ''; + echo '' . html::a(inlink('dynamic', "type=twodaysago&account=$account"), $lang->action->dynamic->twoDaysAgo) . ''; + echo '' . html::a(inlink('dynamic', "type=thisweek&account=$account"), $lang->action->dynamic->thisWeek) . ''; + echo '' . html::a(inlink('dynamic', "type=lastweek&account=$account"), $lang->action->dynamic->lastWeek) . ''; + echo '' . html::a(inlink('dynamic', "type=thismonth&account=$account"), $lang->action->dynamic->thisMonth) . ''; + echo '' . html::a(inlink('dynamic', "type=lastmonth&account=$account"), $lang->action->dynamic->lastMonth) . ''; + echo '' . html::a(inlink('dynamic', "type=all&account=$account"), $lang->action->dynamic->all) . ''; + ?> +
              + + + + + + + + + + + + + + + objectType == 'case' ? 'testcase' : $action->objectType;?> + + + + + + + + + + + +
              action->date;?> action->actor;?>action->action;?> action->objectType;?> idAB;?>action->objectName;?>
              date;?>actor];?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
              show();?>
              + + diff --git a/module/user/view/edit.html.php b/module/user/view/edit.html.php index 6db56ec75e..fc63fb0146 100644 --- a/module/user/view/edit.html.php +++ b/module/user/view/edit.html.php @@ -1,93 +1,93 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              user->edit;?>
              user->dept;?>dept, "class='select-3'");?> -
              user->account;?>account, "class='text-3'");?>
              user->realname;?>realname, "class='text-3'");?>
              user->commiter;?>commiter, "class='text-3'");?>
              user->email;?>email, "class='text-3'");?>
              user->join;?>join, "class='text-3 date'");?>
              user->gender;?>user->genderList, $user->gender);?>
              user->password;?>
              user->password2;?>
              user->msn;?>msn, "class='text-3'");?>
              user->qq;?>qq, "class='text-3'");?>
              user->yahoo;?>yahoo, "class='text-3'");?>
              user->gtalk;?>gtalk, "class='text-3'");?>
              user->wangwang;?>wangwang, "class='text-3'");?>
              user->mobile;?>mobile, "class='text-3'");?>
              user->phone;?>phone, "class='text-3'");?>
              user->address;?>address, "class='text-3'");?>
              user->zipcode;?>zipcode, "class='text-3'");?>
              -
              - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              user->edit;?>
              user->dept;?>dept, "class='select-3'");?> +
              user->account;?>account, "class='text-3'");?>
              user->realname;?>realname, "class='text-3'");?>
              user->commiter;?>commiter, "class='text-3'");?>
              user->email;?>email, "class='text-3'");?>
              user->join;?>join, "class='text-3 date'");?>
              user->gender;?>user->genderList, $user->gender);?>
              user->password;?>
              user->password2;?>
              user->msn;?>msn, "class='text-3'");?>
              user->qq;?>qq, "class='text-3'");?>
              user->yahoo;?>yahoo, "class='text-3'");?>
              user->gtalk;?>gtalk, "class='text-3'");?>
              user->wangwang;?>wangwang, "class='text-3'");?>
              user->mobile;?>mobile, "class='text-3'");?>
              user->phone;?>phone, "class='text-3'");?>
              user->address;?>address, "class='text-3'");?>
              user->zipcode;?>zipcode, "class='text-3'");?>
              +
              + diff --git a/module/user/view/login.html.php b/module/user/view/login.html.php index 563dec5a8c..8332973fa9 100644 --- a/module/user/view/login.html.php +++ b/module/user/view/login.html.php @@ -1,47 +1,47 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -include '../../common/view/header.lite.html.php'; -include '../../common/view/colorbox.html.php'; -?> -
              - - - - - - - - - - - - - - - - - - -
              welcome, $app->company->name);?>
              user->account;?>:
              user->password;?>:
              Language:langs, $this->app->getClientLang(), 'class=select-2 onchange=selectLang(this.value)');?>
              user->keepLogin, $keepLogin);?>
              - login); - if($app->company->guest) echo html::linkButton($lang->user->asGuest, $this->createLink($config->default->module)); - echo html::hidden('referer', $referer); - ?> -
              -
              - powered by ZenTaoPMS(version;?>) - donate;?> -
              - -
              -
              - + + * @package ZenTaoPMS + * @version $Id$ + */ +include '../../common/view/header.lite.html.php'; +include '../../common/view/colorbox.html.php'; +?> +
              + + + + + + + + + + + + + + + + + + +
              welcome, $app->company->name);?>
              user->account;?>:
              user->password;?>:
              Language:langs, $this->app->getClientLang(), 'class=select-2 onchange=selectLang(this.value)');?>
              user->keepLogin, $keepLogin);?>
              + login); + if($app->company->guest) echo html::linkButton($lang->user->asGuest, $this->createLink($config->default->module)); + echo html::hidden('referer', $referer); + ?> +
              +
              + powered by ZenTaoPMS(version;?>) + donate;?> +
              + +
              +
              + diff --git a/module/user/view/profile.html.php b/module/user/view/profile.html.php index 64dd171932..2608d394e5 100644 --- a/module/user/view/profile.html.php +++ b/module/user/view/profile.html.php @@ -1,119 +1,119 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              user->profile;?>
              user->dept;?> - $dept) - { - if($dept->name) echo $dept->name; - if(isset($deptPath[$key + 1])) echo $lang->arrow; - } - } - ?> -
              user->account;?>account;?>
              user->realname;?>realname;?>
              user->commiter;?>commiter;?>
              user->email;?>email;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              user->msn;?>msn;?>
              user->qq;?>qq;?>
              user->yahoo;?>yahoo;?>
              user->gtalk;?>gtalk;?>
              user->wangwang;?>wangwang;?>
              user->mobile;?>mobile;?>
              user->phone;?>phone;?>
              user->address;?>address;?>
              user->zipcode;?>zipcode;?>
              - createLink('user', 'edit', "userID=$user->id&from=company"), $lang->user->editProfile); - echo html::a($this->createLink('user', 'logout'), $lang->logout); - ?> -
              - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              user->profile;?>
              user->dept;?> + $dept) + { + if($dept->name) echo $dept->name; + if(isset($deptPath[$key + 1])) echo $lang->arrow; + } + } + ?> +
              user->account;?>account;?>
              user->realname;?>realname;?>
              user->commiter;?>commiter;?>
              user->email;?>email;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              user->msn;?>msn;?>
              user->qq;?>qq;?>
              user->yahoo;?>yahoo;?>
              user->gtalk;?>gtalk;?>
              user->wangwang;?>wangwang;?>
              user->mobile;?>mobile;?>
              user->phone;?>phone;?>
              user->address;?>address;?>
              user->zipcode;?>zipcode;?>
              + createLink('user', 'edit', "userID=$user->id&from=company"), $lang->user->editProfile); + echo html::a($this->createLink('user', 'logout'), $lang->logout); + ?> +
              + diff --git a/module/user/view/project.html.php b/module/user/view/project.html.php index 1ee3ffc1ad..289a8a0154 100644 --- a/module/user/view/project.html.php +++ b/module/user/view/project.html.php @@ -1,46 +1,46 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - createLink('project', 'browse', "projectID=$project->id");?> - - - - - - - - - - - - - -
              idAB;?>project->code;?>project->name;?>project->begin;?>project->end;?>statusAB;?>team->role;?>team->join;?>team->hours;?>
              id);?>code;?>name);?>begin;?>end;?>project->statusList[$project->status];?>role;?>join;?>hours;?>
              - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + createLink('project', 'browse', "projectID=$project->id");?> + + + + + + + + + + + + + +
              idAB;?>project->code;?>project->name;?>project->begin;?>project->end;?>statusAB;?>team->role;?>team->join;?>team->hours;?>
              id);?>code;?>name);?>begin;?>end;?>project->statusList[$project->status];?>role;?>join;?>hours;?>
              + diff --git a/module/user/view/story.html.php b/module/user/view/story.html.php index d0e41e7d25..99559689f0 100644 --- a/module/user/view/story.html.php +++ b/module/user/view/story.html.php @@ -1,15 +1,15 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + diff --git a/module/user/view/task.html.php b/module/user/view/task.html.php index 85053a8e62..c0fe6c5baa 100644 --- a/module/user/view/task.html.php +++ b/module/user/view/task.html.php @@ -1,44 +1,44 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              idAB;?>priAB;?>task->project;?>task->name;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>
              createLink('task', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>task->priList[$task->pri];?>createLink('project', 'browse', "projectid=$task->projectID"), $task->projectName);?> - createLink('task', 'view', "taskID=$task->id"), $task->name);?>estimate;?>consumed;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>task->statusList[$task->status];?>
              - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              idAB;?>priAB;?>task->project;?>task->name;?>task->estimateAB;?>task->consumedAB;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>
              createLink('task', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>task->priList[$task->pri];?>createLink('project', 'browse', "projectid=$task->projectID"), $task->projectName);?> + createLink('task', 'view', "taskID=$task->id"), $task->name);?>estimate;?>consumed;?>left;?>delay)) echo 'delayed';?>>deadline, 0, 4) > 0) echo $task->deadline;?>task->statusList[$task->status];?>
              + diff --git a/module/user/view/team.html.php b/module/user/view/team.html.php index ed3f21d400..7030b367d6 100644 --- a/module/user/view/team.html.php +++ b/module/user/view/team.html.php @@ -1,14 +1,14 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + diff --git a/module/user/view/todo.html.php b/module/user/view/todo.html.php index 04059ca054..7224b346d4 100644 --- a/module/user/view/todo.html.php +++ b/module/user/view/todo.html.php @@ -1,60 +1,60 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
              ' id='todoform'> -
              -
              - ' . html::a(inlink('todo', "account=$account&date=today"), $lang->todo->todayTodos) . ''; - echo '' . html::a(inlink('todo', "account=$account&date=thisweek"), $lang->todo->thisWeekTodos) . ''; - echo '' . html::a(inlink('todo', "account=$account&date=lastweek"), $lang->todo->lastWeekTodos) . ''; - echo '' . html::a(inlink('todo', "account=$account&date=all"), $lang->todo->allDaysTodos) . ''; - echo '' . html::a(inlink('todo', "account=$account&date=before&status=undone"), $lang->todo->allUndone) . ''; - echo "" . html::select('date', $dates, $date, 'onchange=changeDate(this.value)') . ''; - ?> - -
              -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              idAB;?>todo->date;?>todo->type;?>priAB;?>todo->name;?>todo->beginAB;?>todo->endAB;?>todo->status;?>
              id;?>date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList->{$todo->type};?>pri;?>id", $todo->name)) echo $todo->name;?>begin;?>end;?>todo->statusList[$todo->status];?>
              -
              - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
              ' id='todoform'> +
              +
              + ' . html::a(inlink('todo', "account=$account&date=today"), $lang->todo->todayTodos) . ''; + echo '' . html::a(inlink('todo', "account=$account&date=thisweek"), $lang->todo->thisWeekTodos) . ''; + echo '' . html::a(inlink('todo', "account=$account&date=lastweek"), $lang->todo->lastWeekTodos) . ''; + echo '' . html::a(inlink('todo', "account=$account&date=all"), $lang->todo->allDaysTodos) . ''; + echo '' . html::a(inlink('todo', "account=$account&date=before&status=undone"), $lang->todo->allUndone) . ''; + echo "" . html::select('date', $dates, $date, 'onchange=changeDate(this.value)') . ''; + ?> + +
              +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              idAB;?>todo->date;?>todo->type;?>priAB;?>todo->name;?>todo->beginAB;?>todo->endAB;?>todo->status;?>
              id;?>date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList->{$todo->type};?>pri;?>id", $todo->name)) echo $todo->name;?>begin;?>end;?>todo->statusList[$todo->status];?>
              +
              + diff --git a/module/user/view/view.html.php b/module/user/view/view.html.php index 4c08f603ea..2a0baf5d7c 100644 --- a/module/user/view/view.html.php +++ b/module/user/view/view.html.php @@ -1,78 +1,78 @@ - - * @package my - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
              -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              my->profile;?>
              user->account;?>account;?>
              user->realname;?>realname;?>
              user->nickname;?>nickname;?>
              user->commiter;?>commiter;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              - -
              -
              -
              -
              -
                - {$user->realname}"; - echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=task"), $lang->my->task) . "
              • "; - //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=todo"), $lang->my->todo) . "
              • "; - echo "
              • ". html::a($this->createLink('user', 'view', "account=$user->account&tabID=project"), $lang->my->myProject) . "
              • "; - //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=story"), $lang->my->story) . "
              • "; - echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=bug"), $lang->my->bug) . "
              • "; - //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=team"), $lang->my->team) . "
              • "; - echo << -$("#{$tabID}tab").addClass('active'); - -EOT; - ?> -
              -
              - -
              -
              -
              - + + * @package my + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
              +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              my->profile;?>
              user->account;?>account;?>
              user->realname;?>realname;?>
              user->nickname;?>nickname;?>
              user->commiter;?>commiter;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              + +
              +
              +
              +
              +
                + {$user->realname}"; + echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=task"), $lang->my->task) . "
              • "; + //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=todo"), $lang->my->todo) . "
              • "; + echo "
              • ". html::a($this->createLink('user', 'view', "account=$user->account&tabID=project"), $lang->my->myProject) . "
              • "; + //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=story"), $lang->my->story) . "
              • "; + echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=bug"), $lang->my->bug) . "
              • "; + //echo "
              • " . html::a($this->createLink('user', 'view', "account=$user->account&tabID=team"), $lang->my->team) . "
              • "; + echo << +$("#{$tabID}tab").addClass('active'); + +EOT; + ?> +
              +
              + +
              +
              +
              + diff --git a/www/index.php b/www/index.php index 057b3260c5..a93b800f7c 100644 --- a/www/index.php +++ b/www/index.php @@ -1,43 +1,43 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -/* Set the error reporting. */ -error_reporting(0); - -/* Start output buffer. */ -ob_start(); - -/* Load the framework. */ -include '../framework/router.class.php'; -include '../framework/control.class.php'; -include '../framework/model.class.php'; -include '../framework/helper.class.php'; - -/* Log the time and define the run mode. */ -$startTime = getTime(); - -/* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__))); - -/* Check the reqeust is getconfig or not. Check installed or not. */ -if(isset($_GET['mode']) and $_GET['mode'] == 'getconfig') die($app->exportConfig()); // -if(!isset($config->installed) or !$config->installed) die(header('location: install.php')); - -/* Run the app. */ -$common = $app->loadCommon(); -$app->parseRequest(); -$common->checkPriv(); -$app->loadModule(); - -/* Flush the buffer. */ -ob_end_flush(); + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +/* Set the error reporting. */ +error_reporting(0); + +/* Start output buffer. */ +ob_start(); + +/* Load the framework. */ +include '../framework/router.class.php'; +include '../framework/control.class.php'; +include '../framework/model.class.php'; +include '../framework/helper.class.php'; + +/* Log the time and define the run mode. */ +$startTime = getTime(); + +/* Instance the app. */ +$app = router::createApp('pms', dirname(dirname(__FILE__))); + +/* Check the reqeust is getconfig or not. Check installed or not. */ +if(isset($_GET['mode']) and $_GET['mode'] == 'getconfig') die($app->exportConfig()); // +if(!isset($config->installed) or !$config->installed) die(header('location: install.php')); + +/* Run the app. */ +$common = $app->loadCommon(); +$app->parseRequest(); +$common->checkPriv(); +$app->loadModule(); + +/* Flush the buffer. */ +ob_end_flush(); diff --git a/www/install.php b/www/install.php index c577f9699d..58f0aa9f71 100644 --- a/www/install.php +++ b/www/install.php @@ -1,38 +1,38 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -error_reporting(0); -session_start(); -define('IN_INSTALL', true); - -/* Load the framework. */ -include '../framework/router.class.php'; -include '../framework/control.class.php'; -include '../framework/model.class.php'; -include '../framework/helper.class.php'; - -/* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__))); - -/* Check installed or not. */ -if(!isset($_SESSION['installing']) and isset($config->installed) and $config->installed) die(header('location: index.php')); - -/* Reset the config params to make sure the install program will be lauched. */ -$config->set('requestType', 'GET'); -$config->set('debug', true); -$config->set('default.module', 'install'); -$app->setDebug(); - -/* During the installation, if the database params is setted, auto connect the db. */ -if(isset($config->installed) and $config->installed) $app->connectDB(); - -$app->parseRequest(); -$app->loadModule(); + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +error_reporting(0); +session_start(); +define('IN_INSTALL', true); + +/* Load the framework. */ +include '../framework/router.class.php'; +include '../framework/control.class.php'; +include '../framework/model.class.php'; +include '../framework/helper.class.php'; + +/* Instance the app. */ +$app = router::createApp('pms', dirname(dirname(__FILE__))); + +/* Check installed or not. */ +if(!isset($_SESSION['installing']) and isset($config->installed) and $config->installed) die(header('location: index.php')); + +/* Reset the config params to make sure the install program will be lauched. */ +$config->set('requestType', 'GET'); +$config->set('debug', true); +$config->set('default.module', 'install'); +$app->setDebug(); + +/* During the installation, if the database params is setted, auto connect the db. */ +if(isset($config->installed) and $config->installed) $app->connectDB(); + +$app->parseRequest(); +$app->loadModule(); diff --git a/www/upgrade.php b/www/upgrade.php index 2d6324304f..95a76f3d8f 100644 --- a/www/upgrade.php +++ b/www/upgrade.php @@ -1,37 +1,37 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -error_reporting(0); - -/* Load the framework. */ -include '../framework/router.class.php'; -include '../framework/control.class.php'; -include '../framework/model.class.php'; -include '../framework/helper.class.php'; - -/* Instance the app. */ -$app = router::createApp('pms', dirname(dirname(__FILE__))); -$common = $app->loadCommon(); - -/* Reset the config params to make sure the install program will be lauched. */ -$config->set('requestType', 'GET'); -$config->set('debug', true); -$config->set('default.module', 'upgrade'); -$app->setDebug(); - -/* Check the installed version is the latest or not. */ -$config->installedVersion = $common->loadModel('setting')->getVersion(); -if(version_compare($config->version, $config->installedVersion) <= 0) die(header('location: index.php')); - -/* Run it. */ -$app->parseRequest(); -$common->checkUpgradeStatus(); -$app->loadModule(); + + * @package ZenTaoPMS + * @version $Id$ + * @link http://www.zentao.net + */ +error_reporting(0); + +/* Load the framework. */ +include '../framework/router.class.php'; +include '../framework/control.class.php'; +include '../framework/model.class.php'; +include '../framework/helper.class.php'; + +/* Instance the app. */ +$app = router::createApp('pms', dirname(dirname(__FILE__))); +$common = $app->loadCommon(); + +/* Reset the config params to make sure the install program will be lauched. */ +$config->set('requestType', 'GET'); +$config->set('debug', true); +$config->set('default.module', 'upgrade'); +$app->setDebug(); + +/* Check the installed version is the latest or not. */ +$config->installedVersion = $common->loadModel('setting')->getVersion(); +if(version_compare($config->version, $config->installedVersion) <= 0) die(header('location: index.php')); + +/* Run it. */ +$app->parseRequest(); +$common->checkUpgradeStatus(); +$app->loadModule();