From 48d43cb5e1d34f4a16c71e59c765a19fb4f6546b Mon Sep 17 00:00:00 2001 From: wangchunsheng Date: Fri, 18 Jan 2013 01:18:58 +0000 Subject: [PATCH] * change copyright time. --- bin/build/initext.php | 120 +- bin/ztcli | 124 +- config/config.php | 288 +- lib/api/api.class.php | 3010 +++++++++--------- lib/zfile/zfile.class.php | 388 +-- module/action/control.php | 160 +- module/action/lang/en.php | 388 +-- module/action/lang/zh-cn.php | 388 +-- module/action/lang/zh-tw.php | 380 +-- module/action/model.php | 1254 ++++---- module/action/view/trash.html.php | 108 +- module/admin/control.php | 380 +-- module/admin/lang/en.php | 112 +- module/admin/lang/zh-cn.php | 112 +- module/admin/lang/zh-tw.php | 112 +- module/admin/model.php | 366 +-- module/admin/view/bind.html.php | 60 +- module/admin/view/browsecompany.html.php | 94 +- module/admin/view/cleardata.html.php | 42 +- module/admin/view/index.html.php | 56 +- module/admin/view/register.html.php | 114 +- 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 | 2196 +++++++------- module/bug/lang/en.php | 722 ++--- module/bug/lang/zh-cn.php | 720 ++--- module/bug/lang/zh-tw.php | 720 ++--- module/bug/model.php | 2428 +++++++-------- module/bug/view/activate.html.php | 86 +- module/bug/view/assignto.html.php | 62 +- module/bug/view/batchedit.html.php | 118 +- module/bug/view/browse.html.php | 366 +-- module/bug/view/close.html.php | 62 +- module/bug/view/confirmbug.html.php | 62 +- module/bug/view/create.html.php | 224 +- module/bug/view/customfields.html.php | 98 +- module/bug/view/edit.html.php | 410 +-- module/bug/view/export.html.php | 26 +- module/bug/view/report.html.php | 124 +- module/bug/view/resolve.html.php | 102 +- module/bug/view/sendmail.html.php | 78 +- module/bug/view/view.html.php | 572 ++-- module/build/control.php | 384 +-- module/build/lang/en.php | 84 +- module/build/lang/zh-cn.php | 84 +- module/build/lang/zh-tw.php | 84 +- module/build/model.php | 308 +- module/build/view/create.html.php | 264 +- module/build/view/edit.html.php | 252 +- module/build/view/view.html.php | 238 +- module/common/control.php | 828 ++--- module/common/lang/en.php | 790 ++--- module/common/lang/zh-cn.php | 790 ++--- module/common/lang/zh-tw.php | 792 ++--- module/common/model.php | 1240 ++++---- module/company/control.php | 560 ++-- module/company/lang/en.php | 78 +- module/company/lang/zh-cn.php | 78 +- module/company/lang/zh-tw.php | 80 +- module/company/model.php | 246 +- module/company/view/browse.html.php | 184 +- 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 | 248 +- module/convert/lang/zh-cn.php | 248 +- module/convert/lang/zh-tw.php | 248 +- 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 | 616 ++-- module/dept/view/browse.html.php | 134 +- module/doc/control.php | 850 +++--- module/doc/lang/en.php | 142 +- module/doc/lang/zh-cn.php | 142 +- module/doc/lang/zh-tw.php | 142 +- module/doc/model.php | 638 ++-- module/doc/view/browse.html.php | 168 +- module/doc/view/create.html.php | 142 +- 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 | 220 +- module/editor/control.php | 328 +- module/editor/model.php | 1136 +++---- 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 | 774 ++--- module/extension/lang/en.php | 196 +- module/extension/lang/zh-cn.php | 196 +- module/extension/lang/zh-tw.php | 196 +- module/extension/model.php | 1514 ++++----- module/extension/view/activate.html.php | 66 +- module/extension/view/browse.html.php | 122 +- 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 | 108 +- module/extension/view/obtain.html.php | 226 +- module/extension/view/structure.html.php | 52 +- 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 | 588 ++-- module/file/lang/en.php | 50 +- module/file/lang/zh-cn.php | 50 +- module/file/lang/zh-tw.php | 50 +- module/file/model.php | 478 +-- module/file/view/edit.html.php | 82 +- module/file/view/export.html.php | 124 +- 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 | 472 +-- module/group/lang/en.php | 128 +- module/group/lang/resource.php | 1590 +++++----- module/group/lang/zh-cn.php | 128 +- module/group/lang/zh-tw.php | 122 +- module/group/model.php | 746 ++--- module/group/view/browse.html.php | 96 +- 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 | 156 +- 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 | 112 +- module/index/model.php | 30 +- module/index/view/index.html.php | 74 +- module/install/control.php | 326 +- module/install/lang/en.php | 274 +- module/install/lang/zh-cn.php | 274 +- module/install/lang/zh-tw.php | 274 +- module/install/model.php | 902 +++--- module/install/view/index.html.php | 72 +- module/install/view/step1.html.php | 242 +- module/install/view/step2.html.php | 126 +- module/install/view/step3.html.php | 146 +- module/install/view/step4.html.php | 104 +- module/install/view/step5.html.php | 42 +- module/mail/control.php | 304 +- module/mail/model.php | 812 ++--- module/mail/view/detect.html.php | 40 +- module/mail/view/edit.html.php | 136 +- module/mail/view/save.html.php | 50 +- module/mail/view/test.html.php | 56 +- module/misc/control.php | 236 +- module/misc/lang/en.php | 98 +- module/misc/lang/zh-cn.php | 98 +- module/misc/lang/zh-tw.php | 98 +- module/misc/model.php | 40 +- module/my/control.php | 934 +++--- module/my/model.php | 92 +- module/my/view/bug.html.php | 130 +- module/my/view/changepassword.html.php | 68 +- module/my/view/dynamic.html.php | 110 +- module/my/view/editprofile.html.php | 200 +- module/my/view/index.html.php | 82 +- module/my/view/profile.html.php | 248 +- module/my/view/project.html.php | 92 +- module/my/view/story.html.php | 132 +- module/my/view/task.html.php | 174 +- module/my/view/team.html.php | 28 +- module/my/view/testcase.html.php | 110 +- module/my/view/testtask.html.php | 122 +- module/my/view/todo.html.php | 252 +- module/product/control.php | 896 +++--- module/product/lang/en.php | 170 +- module/product/lang/zh-cn.php | 170 +- module/product/lang/zh-tw.php | 170 +- module/product/model.php | 1218 ++++---- module/product/view/browse.html.php | 282 +- module/product/view/close.html.php | 54 +- 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 | 120 +- module/product/view/order.html.php | 64 +- module/product/view/project.html.php | 88 +- module/product/view/roadmap.html.php | 98 +- module/product/view/view.html.php | 314 +- module/productplan/control.php | 384 +-- module/productplan/lang/en.php | 82 +- module/productplan/lang/zh-cn.php | 82 +- module/productplan/lang/zh-tw.php | 68 +- module/productplan/model.php | 304 +- module/productplan/view/browse.html.php | 98 +- module/productplan/view/create.html.php | 108 +- module/productplan/view/edit.html.php | 100 +- module/productplan/view/linkstory.html.php | 178 +- module/productplan/view/view.html.php | 192 +- module/project/control.php | 3032 +++++++++---------- module/project/lang/en.php | 412 +-- module/project/lang/zh-cn.php | 412 +-- module/project/lang/zh-tw.php | 398 +-- module/project/model.php | 2800 ++++++++--------- module/project/view/activate.html.php | 58 +- 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 | 46 +- module/project/view/close.html.php | 54 +- module/project/view/computeburn.html.php | 36 +- module/project/view/create.html.php | 200 +- module/project/view/delay.html.php | 82 +- module/project/view/doc.html.php | 108 +- module/project/view/dynamic.html.php | 112 +- module/project/view/edit.html.php | 174 +- module/project/view/grouptask.html.php | 236 +- module/project/view/importbug.html.php | 118 +- module/project/view/importtask.html.php | 144 +- module/project/view/index.html.php | 102 +- module/project/view/linkstory.html.php | 126 +- module/project/view/managechilds.html.php | 58 +- module/project/view/managemembers.html.php | 164 +- module/project/view/manageproducts.html.php | 46 +- module/project/view/order.html.php | 110 +- module/project/view/sendmail.html.php | 78 +- module/project/view/start.html.php | 56 +- module/project/view/story.html.php | 230 +- module/project/view/suspend.html.php | 54 +- module/project/view/task.html.php | 326 +- module/project/view/team.html.php | 112 +- module/project/view/testtask.html.php | 108 +- module/project/view/view.html.php | 268 +- 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 | 520 ++-- module/release/lang/en.php | 74 +- module/release/lang/zh-cn.php | 74 +- module/release/lang/zh-tw.php | 74 +- module/release/model.php | 262 +- module/release/view/browse.html.php | 92 +- module/release/view/create.html.php | 90 +- module/release/view/edit.html.php | 236 +- module/release/view/export.html.php | 98 +- module/release/view/view.html.php | 234 +- module/report/control.php | 244 +- module/report/lang/en.php | 144 +- module/report/lang/zh-cn.php | 144 +- module/report/lang/zh-tw.php | 144 +- module/report/model.php | 922 +++--- module/search/control.php | 162 +- module/search/lang/en.php | 102 +- module/search/lang/zh-cn.php | 102 +- module/search/lang/zh-tw.php | 102 +- module/search/model.php | 702 ++--- module/search/view/buildform.html.php | 624 ++-- module/setting/model.php | 522 ++-- module/story/control.php | 2060 ++++++------- module/story/lang/en.php | 538 ++-- module/story/lang/zh-cn.php | 538 ++-- module/story/lang/zh-tw.php | 538 ++-- module/story/model.php | 2794 ++++++++--------- module/story/view/activate.html.php | 72 +- module/story/view/batchclose.html.php | 128 +- module/story/view/batchcreate.html.php | 98 +- module/story/view/batchedit.html.php | 152 +- module/story/view/change.html.php | 104 +- module/story/view/close.html.php | 84 +- module/story/view/create.html.php | 158 +- module/story/view/edit.html.php | 286 +- 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 | 78 +- module/story/view/view.html.php | 548 ++-- 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 | 1306 ++++---- module/svn/syncer/syncer.php | 598 ++-- module/svn/view/cat.html.php | 32 +- module/svn/view/diff.html.php | 34 +- module/task/control.php | 1746 +++++------ module/task/lang/en.php | 456 +-- module/task/lang/zh-cn.php | 456 +-- module/task/lang/zh-tw.php | 446 +-- module/task/model.php | 2324 +++++++------- module/task/view/activate.html.php | 80 +- module/task/view/assignto.html.php | 70 +- module/task/view/batchcreate.html.php | 102 +- module/task/view/batchedit.html.php | 110 +- module/task/view/browse.html.php | 72 +- module/task/view/cancel.html.php | 50 +- module/task/view/close.html.php | 54 +- module/task/view/create.html.php | 208 +- module/task/view/edit.html.php | 322 +- module/task/view/export.html.php | 26 +- module/task/view/finish.html.php | 72 +- module/task/view/import.html.php | 116 +- module/task/view/record.html.php | 80 +- module/task/view/report.html.php | 126 +- module/task/view/sendmail.html.php | 78 +- module/task/view/start.html.php | 80 +- module/task/view/view.html.php | 416 +-- module/testcase/control.php | 1306 ++++---- module/testcase/lang/en.php | 294 +- module/testcase/lang/zh-cn.php | 294 +- module/testcase/lang/zh-tw.php | 292 +- module/testcase/model.php | 784 ++--- module/testcase/view/batchcreate.html.php | 94 +- module/testcase/view/batchedit.html.php | 114 +- module/testcase/view/browse.html.php | 256 +- module/testcase/view/create.html.php | 196 +- module/testcase/view/edit.html.php | 264 +- module/testcase/view/export.html.php | 26 +- module/testcase/view/import.html.php | 64 +- module/testcase/view/index.html.php | 30 +- module/testcase/view/view.html.php | 464 +-- module/testtask/control.php | 1184 ++++---- module/testtask/lang/en.php | 170 +- module/testtask/lang/zh-cn.php | 170 +- module/testtask/lang/zh-tw.php | 170 +- module/testtask/model.php | 848 +++--- module/testtask/view/batchrun.html.php | 140 +- module/testtask/view/browse.html.php | 112 +- module/testtask/view/cases.html.php | 226 +- module/testtask/view/create.html.php | 142 +- module/testtask/view/edit.html.php | 120 +- module/testtask/view/linkcase.html.php | 158 +- module/testtask/view/results.html.php | 104 +- module/testtask/view/runcase.html.php | 120 +- module/testtask/view/sendmail.html.php | 78 +- module/testtask/view/view.html.php | 140 +- module/todo/control.php | 744 ++--- module/todo/lang/en.php | 164 +- module/todo/lang/zh-cn.php | 164 +- module/todo/lang/zh-tw.php | 172 +- module/todo/model.php | 648 ++-- module/todo/view/batchcreate.html.php | 108 +- module/todo/view/batchedit.html.php | 124 +- module/todo/view/create.html.php | 142 +- module/todo/view/edit.html.php | 138 +- module/todo/view/export.html.php | 26 +- module/todo/view/view.html.php | 174 +- module/tree/control.php | 586 ++-- module/tree/lang/en.php | 86 +- module/tree/lang/zh-cn.php | 86 +- module/tree/lang/zh-tw.php | 86 +- module/tree/model.php | 1174 +++---- module/tree/view/browse.html.php | 232 +- module/tree/view/edit.html.php | 76 +- module/upgrade/control.php | 162 +- module/upgrade/lang/en.php | 136 +- module/upgrade/lang/zh-cn.php | 136 +- module/upgrade/lang/zh-tw.php | 136 +- module/upgrade/model.php | 1126 +++---- 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 | 1524 +++++----- module/user/lang/en.php | 270 +- module/user/lang/zh-cn.php | 270 +- module/user/lang/zh-tw.php | 268 +- module/user/model.php | 1594 +++++----- module/user/view/batchcreate.html.php | 108 +- module/user/view/batchedit.html.php | 92 +- module/user/view/bug.html.php | 90 +- module/user/view/create.html.php | 136 +- module/user/view/deny.html.php | 62 +- module/user/view/dynamic.html.php | 128 +- module/user/view/edit.html.php | 194 +- module/user/view/login.html.php | 126 +- module/user/view/managecontacts.html.php | 142 +- module/user/view/profile.html.php | 248 +- module/user/view/project.html.php | 94 +- module/user/view/story.html.php | 30 +- module/user/view/task.html.php | 92 +- module/user/view/team.html.php | 28 +- module/user/view/todo.html.php | 144 +- module/webapp/lang/en.php | 136 +- module/webapp/lang/zh-cn.php | 136 +- module/webapp/lang/zh-tw.php | 136 +- module/webapp/model.php | 606 ++-- module/webapp/view/index.html.php | 128 +- module/webapp/view/obtain.html.php | 132 +- www/index.php | 84 +- www/install.php | 76 +- www/upgrade.php | 92 +- 409 files changed, 58058 insertions(+), 58058 deletions(-) diff --git a/bin/build/initext.php b/bin/build/initext.php index 80d424a587..3458be4299 100755 --- a/bin/build/initext.php +++ b/bin/build/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 f1ee5f18c6..e8de76409b 100755 --- a/bin/ztcli +++ b/bin/ztcli @@ -1,62 +1,62 @@ -#!/usr/bin/env php - - * @package bin - * @version $Id$ - * @link http://www.ZenTaoPMS.com - */ -error_reporting(E_ALL ^ E_NOTICE); -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(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') -{ - $path = pathinfo($request['path']); - if(strpos($path['basename'], $config->requestFix)) - { - $_SERVER['PATH_INFO'] = $path['basename']; - } - else - { - if(is_dir('./module/' . $path['basename'])) - { - $_SERVER['PATH_INFO'] = $path['basename']; - } - else - { - $_SERVER['PATH_INFO'] = ''; - } - } -} -else -{ - parse_str($request['query'], $_GET); - $_SERVER['SCRIPT_NAME'] = $_SERVER['HTTP_HOST'] . '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(E_ALL ^ E_NOTICE); +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(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') +{ + $path = pathinfo($request['path']); + if(strpos($path['basename'], $config->requestFix)) + { + $_SERVER['PATH_INFO'] = $path['basename']; + } + else + { + if(is_dir('./module/' . $path['basename'])) + { + $_SERVER['PATH_INFO'] = $path['basename']; + } + else + { + $_SERVER['PATH_INFO'] = ''; + } + } +} +else +{ + parse_str($request['query'], $_GET); + $_SERVER['SCRIPT_NAME'] = $_SERVER['HTTP_HOST'] . '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 7e3a9dbad8..6c570a70f2 100644 --- a/config/config.php +++ b/config/config.php @@ -1,144 +1,144 @@ - - * @package config - * @version $Id$ - * @link http://www.zentao.net - */ -/* Basic settings. */ -$config = new config(); -$config->version = '4.0.beta2'; // The version of zentaopms. Don't change it. -$config->encoding = 'UTF-8'; // The encoding of zentaopms. -$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 = new stdclass(); -$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 = new stdclass(); -$config->file->dangers = 'php,jsp,py,rb,asp,'; // Dangerous files. -$config->file->maxSize = 1024 * 1024; // Max size. - -/* Master database settings. */ -$config->db = new stdclass(); -$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 = new stdclass(); -$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; - -/* 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_USERCONTACT', '`' . $config->db->prefix . 'userContact`'); - -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`'); -define('TABLE_WEBAPP', '`' . $config->db->prefix . 'webapp`'); - -$config->objectTables['product'] = TABLE_PRODUCT; -$config->objectTables['story'] = TABLE_STORY; -$config->objectTables['productplan'] = TABLE_PRODUCTPLAN; -$config->objectTables['release'] = TABLE_RELEASE; -$config->objectTables['project'] = TABLE_PROJECT; -$config->objectTables['task'] = TABLE_TASK; -$config->objectTables['build'] = TABLE_BUILD; -$config->objectTables['bug'] = TABLE_BUG; -$config->objectTables['case'] = TABLE_CASE; -$config->objectTables['testcase'] = TABLE_CASE; -$config->objectTables['testtask'] = TABLE_TESTTASK; -$config->objectTables['user'] = TABLE_USER; -$config->objectTables['doc'] = TABLE_DOC; -$config->objectTables['doclib'] = TABLE_DOCLIB; -$config->objectTables['todo'] = TABLE_TODO; - -/* Include extension config files. */ -$extConfigFiles = glob($configRoot . 'ext/*.php'); -if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile; + + * @package config + * @version $Id$ + * @link http://www.zentao.net + */ +/* Basic settings. */ +$config = new config(); +$config->version = '4.0.beta2'; // The version of zentaopms. Don't change it. +$config->encoding = 'UTF-8'; // The encoding of zentaopms. +$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 = new stdclass(); +$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 = new stdclass(); +$config->file->dangers = 'php,jsp,py,rb,asp,'; // Dangerous files. +$config->file->maxSize = 1024 * 1024; // Max size. + +/* Master database settings. */ +$config->db = new stdclass(); +$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 = new stdclass(); +$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; + +/* 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_USERCONTACT', '`' . $config->db->prefix . 'userContact`'); + +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`'); +define('TABLE_WEBAPP', '`' . $config->db->prefix . 'webapp`'); + +$config->objectTables['product'] = TABLE_PRODUCT; +$config->objectTables['story'] = TABLE_STORY; +$config->objectTables['productplan'] = TABLE_PRODUCTPLAN; +$config->objectTables['release'] = TABLE_RELEASE; +$config->objectTables['project'] = TABLE_PROJECT; +$config->objectTables['task'] = TABLE_TASK; +$config->objectTables['build'] = TABLE_BUILD; +$config->objectTables['bug'] = TABLE_BUG; +$config->objectTables['case'] = TABLE_CASE; +$config->objectTables['testcase'] = TABLE_CASE; +$config->objectTables['testtask'] = TABLE_TESTTASK; +$config->objectTables['user'] = TABLE_USER; +$config->objectTables['doc'] = TABLE_DOC; +$config->objectTables['doclib'] = TABLE_DOCLIB; +$config->objectTables['todo'] = TABLE_TODO; + +/* Include extension config files. */ +$extConfigFiles = glob($configRoot . 'ext/*.php'); +if($extConfigFiles) foreach($extConfigFiles as $extConfigFile) include $extConfigFile; diff --git a/lib/api/api.class.php b/lib/api/api.class.php index e992d5ecb1..3047a3103b 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/lib/zfile/zfile.class.php b/lib/zfile/zfile.class.php index fd4f781ee8..a18f3d5777 100644 --- a/lib/zfile/zfile.class.php +++ b/lib/zfile/zfile.class.php @@ -1,194 +1,194 @@ - - * @package Zfile - * @version $Id: zfile.class.php 2605 2013-01-09 07:22:58Z wwccss $ - * @link http://www.zentao.net - */ -class zfile -{ - /** - * Copy a directory from an directory to another directory. - * - * @param string $from - * @param string $to - * @access public - * @return array copied files. - */ - public function copyDir($from, $to) - { - static $copiedFiles = array(); - - if(!is_dir($from) or !is_readable($from)) return $copiedFiles; - if(!is_dir($to)) - { - if(!is_writable(dirname($to))) return $copiedFiles; - mkdir($to); - } - - $from = realpath($from) . '/'; - $to = realpath($to) . '/'; - $entries = scandir($from); - - foreach($entries as $entry) - { - if($entry == '.' or $entry == '..' or $entry == '.svn') continue; - - $fullEntry = $from . $entry; - if(is_file($fullEntry)) - { - if(file_exists($to . $entry)) - { - unlink($to . $entry); - } - copy($fullEntry, $to . $entry); - $copiedFiles[] = $to . $entry; - } - else - { - $nextFrom = $from . $entry; - $nextTo = $to . $entry; - $this->copyDir($nextFrom, $nextTo); - } - } - return $copiedFiles; - } - - /** - * Remove a dir. - * - * @param string $dir - * @access public - * @return bool - */ - public function removeDir($dir) - { - $dir = realpath($dir) . '/'; - if($dir == '/') return false; - - if(!is_writable($dir)) return false; - if(!is_dir($dir)) return true; - - $entries = scandir($dir); - foreach($entries as $entry) - { - if($entry == '.' or $entry == '..' or $entry == '.svn') continue; - - $fullEntry = $dir . $entry; - if(is_file($fullEntry)) - { - unlink($fullEntry); - } - else - { - $this->removeDir($fullEntry); - } - } - if(!@rmdir($dir)) return false; - return true; - } - - /** - * Get files under a directory recursive. - * - * @param string $dir - * @param array $exceptions - * @access private - * @return array - */ - public function readDir($dir, $exceptions = array()) - { - static $files = array(); - - if(!is_dir($dir)) return $files; - - $dir = realpath($dir) . '/'; - $entries = scandir($dir); - - foreach($entries as $entry) - { - if($entry == '.' or $entry == '..' or $entry == '.svn') continue; - if(in_array($entry, $exceptions)) continue; - - $fullEntry = $dir . $entry; - if(is_file($fullEntry)) - { - $files[] = $dir . $entry; - } - else - { - $nextDir = $dir . $entry; - $this->readDir($nextDir); - } - } - return $files; - } - - /** - * Make a dir. - * - * @param string $dir - * @access public - * @return bool - */ - public function mkdir($dir) - { - return mkdir($dir, 0755, true); - } - - /** - * Remove a file - * - * @param string $file - * @access public - * @return bool - */ - public function removeFile($file) - { - if(!file_exists($file)) return true; - return @unlink($file); - } - - /** - * Batch remove files. use glob function. - * - * @param string $patern - * @access public - * @return avoid - */ - public function batchRemoveFile($patern) - { - $files = glob($patern); - foreach($files as $file) @unlink($file); - } - - /** - * Remove a file - * - * @param string from - * @param string to - * @access public - * @return bool - */ - public function copyFile($from, $to) - { - return @copy($from, $to); - } - - /** - * Rename a file or directory. - * - * @param string from - * @param string to - * @access public - * @return bool - */ - public function rename($from, $to) - { - return rename($from, $to); - } -} + + * @package Zfile + * @version $Id: zfile.class.php 2605 2013-01-09 07:22:58Z wwccss $ + * @link http://www.zentao.net + */ +class zfile +{ + /** + * Copy a directory from an directory to another directory. + * + * @param string $from + * @param string $to + * @access public + * @return array copied files. + */ + public function copyDir($from, $to) + { + static $copiedFiles = array(); + + if(!is_dir($from) or !is_readable($from)) return $copiedFiles; + if(!is_dir($to)) + { + if(!is_writable(dirname($to))) return $copiedFiles; + mkdir($to); + } + + $from = realpath($from) . '/'; + $to = realpath($to) . '/'; + $entries = scandir($from); + + foreach($entries as $entry) + { + if($entry == '.' or $entry == '..' or $entry == '.svn') continue; + + $fullEntry = $from . $entry; + if(is_file($fullEntry)) + { + if(file_exists($to . $entry)) + { + unlink($to . $entry); + } + copy($fullEntry, $to . $entry); + $copiedFiles[] = $to . $entry; + } + else + { + $nextFrom = $from . $entry; + $nextTo = $to . $entry; + $this->copyDir($nextFrom, $nextTo); + } + } + return $copiedFiles; + } + + /** + * Remove a dir. + * + * @param string $dir + * @access public + * @return bool + */ + public function removeDir($dir) + { + $dir = realpath($dir) . '/'; + if($dir == '/') return false; + + if(!is_writable($dir)) return false; + if(!is_dir($dir)) return true; + + $entries = scandir($dir); + foreach($entries as $entry) + { + if($entry == '.' or $entry == '..' or $entry == '.svn') continue; + + $fullEntry = $dir . $entry; + if(is_file($fullEntry)) + { + unlink($fullEntry); + } + else + { + $this->removeDir($fullEntry); + } + } + if(!@rmdir($dir)) return false; + return true; + } + + /** + * Get files under a directory recursive. + * + * @param string $dir + * @param array $exceptions + * @access private + * @return array + */ + public function readDir($dir, $exceptions = array()) + { + static $files = array(); + + if(!is_dir($dir)) return $files; + + $dir = realpath($dir) . '/'; + $entries = scandir($dir); + + foreach($entries as $entry) + { + if($entry == '.' or $entry == '..' or $entry == '.svn') continue; + if(in_array($entry, $exceptions)) continue; + + $fullEntry = $dir . $entry; + if(is_file($fullEntry)) + { + $files[] = $dir . $entry; + } + else + { + $nextDir = $dir . $entry; + $this->readDir($nextDir); + } + } + return $files; + } + + /** + * Make a dir. + * + * @param string $dir + * @access public + * @return bool + */ + public function mkdir($dir) + { + return mkdir($dir, 0755, true); + } + + /** + * Remove a file + * + * @param string $file + * @access public + * @return bool + */ + public function removeFile($file) + { + if(!file_exists($file)) return true; + return @unlink($file); + } + + /** + * Batch remove files. use glob function. + * + * @param string $patern + * @access public + * @return avoid + */ + public function batchRemoveFile($patern) + { + $files = glob($patern); + foreach($files as $file) @unlink($file); + } + + /** + * Remove a file + * + * @param string from + * @param string to + * @access public + * @return bool + */ + public function copyFile($from, $to) + { + return @copy($from, $to); + } + + /** + * Rename a file or directory. + * + * @param string from + * @param string to + * @access public + * @return bool + */ + public function rename($from, $to) + { + return rename($from, $to); + } +} diff --git a/module/action/control.php b/module/action/control.php index b176b14700..779b93693e 100644 --- a/module/action/control.php +++ b/module/action/control.php @@ -1,80 +1,80 @@ - - * @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); - $this->session->set('docList', $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::reload('parent')); - } - - /** - * Hide object. - * - * @param int $actionID - * @access public - * @return void - */ - public function hide($actionID) - { - $this->action->hide($actionID); - die(js::reload('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); + $this->session->set('docList', $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::reload('parent')); + } + + /** + * Hide object. + * + * @param int $actionID + * @access public + * @return void + */ + public function hide($actionID) + { + $this->action->hide($actionID); + die(js::reload('parent')); + } +} diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 3ca03afe91..e226af1133 100644 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -1,194 +1,194 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->action->common = 'Logs'; -$lang->action->trash = 'Trash'; -$lang->action->undelete = 'Undelete'; -$lang->action->hide = 'Hide'; - -$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->textDiff = 'Text mode'; -$lang->action->original = 'Original content'; - -$lang->action->dynamic = new stdclass(); -$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 = new stdclass(); -$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->hidden = '$date, hidden 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->delayed = '$date, delayed by $actor.'; -$lang->action->desc->suspended = '$date, suspended by $actor.'; -$lang->action->desc->recorded = '$date, recorded by $actor,consumed $extra hour(s).'; -$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:' . "\n" . "
%s
" . "\n"; -$lang->action->desc->diff3 = "changed file's name %s to %s."; - -/* The action labels. */ -$lang->action->label = new stdclass(); -$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->hidden = 'hidden'; -$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->recorded = 'log hour'; -$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['hidden'] = $lang->action->label->hidden; -$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 = 'Undelete'; +$lang->action->hide = 'Hide'; + +$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->textDiff = 'Text mode'; +$lang->action->original = 'Original content'; + +$lang->action->dynamic = new stdclass(); +$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 = new stdclass(); +$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->hidden = '$date, hidden 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->delayed = '$date, delayed by $actor.'; +$lang->action->desc->suspended = '$date, suspended by $actor.'; +$lang->action->desc->recorded = '$date, recorded by $actor,consumed $extra hour(s).'; +$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:' . "\n" . "
%s
" . "\n"; +$lang->action->desc->diff3 = "changed file's name %s to %s."; + +/* The action labels. */ +$lang->action->label = new stdclass(); +$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->hidden = 'hidden'; +$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->recorded = 'log hour'; +$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['hidden'] = $lang->action->label->hidden; +$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 b8846a395a..aa25aa654d 100644 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -1,194 +1,194 @@ - - * @package action - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->action->common = '系统日志'; -$lang->action->trash = '回收站'; -$lang->action->undelete = '还原'; -$lang->action->hide = '隐藏'; - -$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->textDiff = '文本格式'; -$lang->action->original = '原始格式'; - -$lang->action->dynamic = new stdclass(); -$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 = new stdclass(); -$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->hidden = '$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->delayed = '$date, 由 $actor 延期。' . "\n"; -$lang->action->desc->suspended = '$date, 由 $actor 挂起。' . "\n"; -$lang->action->desc->recorded = '$date, 由 $actor 记录工时,消耗了 $extra 小时 。' . "\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 = new stdclass(); -$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->hidden = '隐藏了'; -$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->recorded = '记录了工时'; -$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 = '用户|user|view|account=%s'; -$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['hidden'] = $lang->action->label->hidden; -$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->hide = '隐藏'; + +$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->textDiff = '文本格式'; +$lang->action->original = '原始格式'; + +$lang->action->dynamic = new stdclass(); +$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 = new stdclass(); +$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->hidden = '$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->delayed = '$date, 由 $actor 延期。' . "\n"; +$lang->action->desc->suspended = '$date, 由 $actor 挂起。' . "\n"; +$lang->action->desc->recorded = '$date, 由 $actor 记录工时,消耗了 $extra 小时 。' . "\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 = new stdclass(); +$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->hidden = '隐藏了'; +$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->recorded = '记录了工时'; +$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 = '用户|user|view|account=%s'; +$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['hidden'] = $lang->action->label->hidden; +$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 d116286b8f..5dce6ef9b8 100644 --- a/module/action/lang/zh-tw.php +++ b/module/action/lang/zh-tw.php @@ -1,190 +1,190 @@ - - * @package action - * @version $Id: zh-tw.php 3864 2012-12-20 08:00:07Z wyd621@gmail.com $ - * @link http://www.zentao.net - */ -$lang->action->common = '系統日誌'; -$lang->action->trash = '資源回收筒'; -$lang->action->undelete = '還原'; -$lang->action->hide = '隱藏'; - -$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->textDiff = '文本格式'; -$lang->action->original = '原始格式'; - -$lang->action->dynamic = new stdclass(); -$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 = new stdclass(); -$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->hidden = '$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 = new stdclass(); -$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->hidden = '隱藏了'; -$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['hidden'] = $lang->action->label->hidden; -$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 3864 2012-12-20 08:00:07Z wyd621@gmail.com $ + * @link http://www.zentao.net + */ +$lang->action->common = '系統日誌'; +$lang->action->trash = '資源回收筒'; +$lang->action->undelete = '還原'; +$lang->action->hide = '隱藏'; + +$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->textDiff = '文本格式'; +$lang->action->original = '原始格式'; + +$lang->action->dynamic = new stdclass(); +$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 = new stdclass(); +$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->hidden = '$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 = new stdclass(); +$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->hidden = '隱藏了'; +$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['hidden'] = $lang->action->label->hidden; +$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 e2c70344b6..44345445e8 100644 --- a/module/action/model.php +++ b/module/action/model.php @@ -1,627 +1,627 @@ - - * @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($action->objectType, $objectID); - $action->product = $productAndProject['product']; - $action->project = $productAndProject['project']; - - $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); - return $this->dbh->lastInsertID(); - } - - /** - * Update read field of action when view a task/bug. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return void - */ - public function read($objectType, $objectID) - { - $this->dao->update(TABLE_ACTION) - ->set('`read`')->eq(1) - ->where('objectType')->eq($objectType) - ->andWhere('objectID')->eq($objectID) - ->andWhere('`read`')->eq(0) - ->exec(); - } - - /** - * Get the unread actions. - * - * @param int $actionID - * @access public - * @return void - */ - public function getUnreadActions($actionID = 0) - { - if(!is_numeric($actionID)) $actionID = 0; - $objectList['task'] = TABLE_TASK; - $objectList['bug'] = TABLE_BUG; - $actions = array(); - - foreach($objectList as $object => $table) - { - $idList = $this->dao->select('id')->from($table)->where('assignedTo')->eq($this->app->user->account)->fetchPairs('id', '', false); - - $tmpActions = $this->dao->select('*')->from(TABLE_ACTION) - ->where('objectType')->eq($object) - ->andWhere('objectID')->in($idList) - ->andWhere('`read`')->eq(0) - ->andWhere('id')->gt($actionID) - ->fetchAll('id'); - - if(empty($tmpActions)) continue; - - $tmpActions = $this->transformActions($tmpActions); - foreach($tmpActions as $action) - { - $actions[$action->objectType][] = array( - 'actionID' => $action->id, - 'objectType' => $action->objectType, - 'objectID' => $action->objectID, - 'action' => $action->actor . ' ' . $action->actionLabel . ' ' . $action->objectType . " #$action->objectID" . $action->objectName - ); - } - } - return json_encode($actions); - } - - /** - * Get product and project of an object. - * - * @param string $objectType - * @param int $objectID - * @access public - * @return array - */ - public function getProductAndProject($objectType, $objectID) - { - $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') - { - $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($objectID)->fetchPairs('product'); - $productList = ',' . join(',', array_keys($products)) . ','; - return array('project' => $objectID, 'product' => $productList); - } - - /* Only process these object types. */ - if(strpos('story, productplan, release, task, build. bug, case, testtask, doc', $objectType) !== false) - { - if(!isset($this->config->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->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') - { - if($record->story != 0) - { - $product = $this->dao->select('product')->from(TABLE_STORY)->where('id')->eq($record->story)->fetchPairs('product'); - $record->product = join(',', array_keys($product)); - } - else - { - $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($record->project)->fetchPairs('product'); - $record->product = join(',', array_keys($products)); - } - } - - if($record) - { - $record = (array)$record; - $record['product'] = 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->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. */ - $beginAndEnd = $this->computeBeginAndEnd($period); - extract($beginAndEnd); - - /* Get actions. */ - $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where(1) - ->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi() - ->beginIF($period != 'all')->andWhere('date')->lt($end)->fi() - ->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi() - ->beginIF(is_numeric($productID))->andWhere('product')->like("%,$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; - - $productID = 0; - if(preg_match("/`product` = '(\d*)'/", $actionQuery, $out)) - { - $productID = $out[1]; - } - /* If the sql not include 'product', add check purview for product. */ - if(strpos($actionQuery, $allProduct) === false) - { - if(!in_array($productID, array_keys($products))) return array(); - } - 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($allProject, '1', $actionQuery); - } - - $actionQuery = str_replace("`product` = '$productID'", "`product` LIKE '%,$productID,%'", $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->objectTables[$objectType])) continue; // If no defination for this type, omit it. - - $objectIds = array_unique($objectIds); - $table = $this->config->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 == '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 all|today|yesterday|twodaysago|latest2days|thisweek|lastweek|thismonth|lastmonth - * @access public - * @return array - */ - public function computeBeginAndEnd($period) - { - $this->app->loadClass('date'); - - $today = date::today(); - $tomorrow = date::tomorrow(); - $yesterday = date::yesterday(); - $twoDaysAgo = date::twoDaysAgo(); - - $period = strtolower($period); - - if($period == 'all') return array('begin' => '1970-1-1', 'end' => '2109-1-1'); - if($period == 'today') return array('begin' => $today, 'end' => $tomorrow); - if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today); - if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday); - if($period == 'latest3days')return array('begin' => $twoDaysAgo, 'end' => $tomorrow); - - /* If the period is by week, add the end time to the end date. */ - if($period == 'thisweek' or $period == 'lastweek') - { - $func = "get$period"; - extract(date::$func()); - return array('begin' => $begin, 'end' => $end . ' 23:59:59'); - } - - if($period == 'thismonth') return date::getThisMonth(); - if($period == 'lastmonth') return date::getLastMonth(); - } - - /** - * 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); - $history->noTagDiff = preg_replace('/<\/?([a-z][a-z0-9]*)[^\/]*\/?>/Ui', '', $history->diff); - printf($this->lang->action->desc->diff2, $history->fieldLabel, $history->noTagDiff, $history->diff); - } - else - { - printf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); - } - } - } - - /** - * Hide object. - * - * @param int $actionID - * @access public - * @return void - */ - public function hide($actionID) - { - $action = $this->getById($actionID); - if($action->action != 'deleted') return; - $this->dao->update(TABLE_ACTION)->set('extra')->eq(self::BE_HIDDEN)->where('id')->eq($actionID)->exec(); - $this->create($action->objectType, $action->objectID, 'hidden'); - } -} + + * @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($action->objectType, $objectID); + $action->product = $productAndProject['product']; + $action->project = $productAndProject['project']; + + $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); + return $this->dbh->lastInsertID(); + } + + /** + * Update read field of action when view a task/bug. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return void + */ + public function read($objectType, $objectID) + { + $this->dao->update(TABLE_ACTION) + ->set('`read`')->eq(1) + ->where('objectType')->eq($objectType) + ->andWhere('objectID')->eq($objectID) + ->andWhere('`read`')->eq(0) + ->exec(); + } + + /** + * Get the unread actions. + * + * @param int $actionID + * @access public + * @return void + */ + public function getUnreadActions($actionID = 0) + { + if(!is_numeric($actionID)) $actionID = 0; + $objectList['task'] = TABLE_TASK; + $objectList['bug'] = TABLE_BUG; + $actions = array(); + + foreach($objectList as $object => $table) + { + $idList = $this->dao->select('id')->from($table)->where('assignedTo')->eq($this->app->user->account)->fetchPairs('id', '', false); + + $tmpActions = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectType')->eq($object) + ->andWhere('objectID')->in($idList) + ->andWhere('`read`')->eq(0) + ->andWhere('id')->gt($actionID) + ->fetchAll('id'); + + if(empty($tmpActions)) continue; + + $tmpActions = $this->transformActions($tmpActions); + foreach($tmpActions as $action) + { + $actions[$action->objectType][] = array( + 'actionID' => $action->id, + 'objectType' => $action->objectType, + 'objectID' => $action->objectID, + 'action' => $action->actor . ' ' . $action->actionLabel . ' ' . $action->objectType . " #$action->objectID" . $action->objectName + ); + } + } + return json_encode($actions); + } + + /** + * Get product and project of an object. + * + * @param string $objectType + * @param int $objectID + * @access public + * @return array + */ + public function getProductAndProject($objectType, $objectID) + { + $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') + { + $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($objectID)->fetchPairs('product'); + $productList = ',' . join(',', array_keys($products)) . ','; + return array('project' => $objectID, 'product' => $productList); + } + + /* Only process these object types. */ + if(strpos('story, productplan, release, task, build. bug, case, testtask, doc', $objectType) !== false) + { + if(!isset($this->config->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->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') + { + if($record->story != 0) + { + $product = $this->dao->select('product')->from(TABLE_STORY)->where('id')->eq($record->story)->fetchPairs('product'); + $record->product = join(',', array_keys($product)); + } + else + { + $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($record->project)->fetchPairs('product'); + $record->product = join(',', array_keys($products)); + } + } + + if($record) + { + $record = (array)$record; + $record['product'] = 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->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. */ + $beginAndEnd = $this->computeBeginAndEnd($period); + extract($beginAndEnd); + + /* Get actions. */ + $actions = $this->dao->select('*')->from(TABLE_ACTION) + ->where(1) + ->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi() + ->beginIF($period != 'all')->andWhere('date')->lt($end)->fi() + ->beginIF($account != 'all')->andWhere('actor')->eq($account)->fi() + ->beginIF(is_numeric($productID))->andWhere('product')->like("%,$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; + + $productID = 0; + if(preg_match("/`product` = '(\d*)'/", $actionQuery, $out)) + { + $productID = $out[1]; + } + /* If the sql not include 'product', add check purview for product. */ + if(strpos($actionQuery, $allProduct) === false) + { + if(!in_array($productID, array_keys($products))) return array(); + } + 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($allProject, '1', $actionQuery); + } + + $actionQuery = str_replace("`product` = '$productID'", "`product` LIKE '%,$productID,%'", $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->objectTables[$objectType])) continue; // If no defination for this type, omit it. + + $objectIds = array_unique($objectIds); + $table = $this->config->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 == '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 all|today|yesterday|twodaysago|latest2days|thisweek|lastweek|thismonth|lastmonth + * @access public + * @return array + */ + public function computeBeginAndEnd($period) + { + $this->app->loadClass('date'); + + $today = date::today(); + $tomorrow = date::tomorrow(); + $yesterday = date::yesterday(); + $twoDaysAgo = date::twoDaysAgo(); + + $period = strtolower($period); + + if($period == 'all') return array('begin' => '1970-1-1', 'end' => '2109-1-1'); + if($period == 'today') return array('begin' => $today, 'end' => $tomorrow); + if($period == 'yesterday') return array('begin' => $yesterday, 'end' => $today); + if($period == 'twodaysago') return array('begin' => $twoDaysAgo, 'end' => $yesterday); + if($period == 'latest3days')return array('begin' => $twoDaysAgo, 'end' => $tomorrow); + + /* If the period is by week, add the end time to the end date. */ + if($period == 'thisweek' or $period == 'lastweek') + { + $func = "get$period"; + extract(date::$func()); + return array('begin' => $begin, 'end' => $end . ' 23:59:59'); + } + + if($period == 'thismonth') return date::getThisMonth(); + if($period == 'lastmonth') return date::getLastMonth(); + } + + /** + * 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); + $history->noTagDiff = preg_replace('/<\/?([a-z][a-z0-9]*)[^\/]*\/?>/Ui', '', $history->diff); + printf($this->lang->action->desc->diff2, $history->fieldLabel, $history->noTagDiff, $history->diff); + } + else + { + printf($this->lang->action->desc->diff1, $history->fieldLabel, $history->old, $history->new); + } + } + } + + /** + * Hide object. + * + * @param int $actionID + * @access public + * @return void + */ + public function hide($actionID) + { + $action = $this->getById($actionID); + if($action->action != 'deleted') return; + $this->dao->update(TABLE_ACTION)->set('extra')->eq(self::BE_HIDDEN)->where('id')->eq($actionID)->exec(); + $this->create($action->objectType, $action->objectID, 'hidden'); + } +} diff --git a/module/action/view/trash.html.php b/module/action/view/trash.html.php index 84140b4bb8..1c5c43915c 100644 --- a/module/action/view/trash.html.php +++ b/module/action/view/trash.html.php @@ -1,54 +1,54 @@ - - * @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'); - common::printLink('action', 'hide', "actionid=$action->id", $lang->action->hide, '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'); + common::printLink('action', 'hide', "actionid=$action->id", $lang->action->hide, 'hiddenwin'); + ?> +
+
action->trashTips;?>
+
show();?>
+
+ diff --git a/module/admin/control.php b/module/admin/control.php index d38fa83d3f..868b467821 100644 --- a/module/admin/control.php +++ b/module/admin/control.php @@ -1,190 +1,190 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -class admin extends control -{ - /** - * Index page. - * @access public - * @return void - */ - public function index() - { - $community = zget($this->config->global, 'community'); - if(!$community or $community == 'na') - { - $this->view->bind = false; - $this->view->account = false; - $this->view->ignore = $community == 'na'; - } - else - { - $this->view->bind = true; - $this->view->account = $community; - $this->view->ignore = false; - } - - $this->app->loadLang('misc'); - $this->display(); - } - - /** - * Ignore notice of register and bind. - * - * @access public - * @return void - */ - public function ignore() - { - $this->loadModel('setting')->setItem('system.common.global.community', 'na'); - die(js::locate(inlink('index'), 'parent')); - } - - /** - * Register zentao. - * - * @access public - * @return void - */ - public function register() - { - if($_POST) - { - $response = $this->admin->registerByAPI(); - if($response == 'success') - { - $this->loadModel('setting')->setItem('system.common.global.community', $this->post->account); - echo js::alert($this->lang->admin->register->success); - die(js::locate(inlink('index'), 'parent')); - } - die($response); - } - $this->view->register = $this->admin->getRegisterInfo(); - $this->view->sn = $this->config->global->sn; - $this->display(); - } - - /** - * Bind zentao. - * - * @access public - * @return void - */ - public function bind() - { - if($_POST) - { - $response = $this->admin->bindByAPI(); - if($response == 'success') - { - $this->loadModel('setting')->setItem('system.common.global.community', $this->post->account); - echo js::alert($this->lang->admin->bind->success); - die(js::locate(inlink('index'), 'parent')); - } - die($response); - } - $this->view->sn = $this->config->global->sn; - $this->display(); - } - - /** - * Check all tables. - * - * @access public - * @return void - */ - public function checkDB() - { - $tables = $this->dbh->query('SHOW TABLES')->fetchAll(); - foreach($tables as $table) - { - $tableName = current((array)$table); - $result = $this->dbh->query("REPAIR TABLE $tableName")->fetch(); - echo "Repairing TABLE: " . $result->Table . "\t" . $result->Msg_type . ":" . $result->Msg_text . "\n"; - } - } - - /** - * Rename table for from windows to linux. - * - * @access public - * @return void - */ - public function win2Unix() - { - $renameTables = array( - 'zt_casestep' => 'zt_caseStep' , - 'zt_doclib' => 'zt_docLib' , - 'zt_grouppriv' => 'zt_groupPriv' , - 'zt_productplan' => 'zt_productPlan' , - 'zt_projectproduct' => 'zt_projectProduct' , - 'zt_projectstory' => 'zt_projectStory' , - 'zt_relationoftasks' => 'zt_relationOfTasks', - 'zt_storyspec' => 'zt_storySpec' , - 'zt_taskestimate' => 'zt_taskEstimate' , - 'zt_testresult' => 'zt_testResult' , - 'zt_testrun' => 'zt_testRun' , - 'zt_testtask' => 'zt_testTask' , - 'zt_usercontact' => 'zt_userContact' , - 'zt_usergroup' => 'zt_userGroup' , - 'zt_userquery' => 'zt_userQuery' , - 'zt_usertpl' => 'zt_userTPL' - ); - - $existTables = $this->dbh->query('SHOW TABLES')->fetchAll(); - foreach($existTables as $key => $table) $existTables[$key] = current((array)$table); - $existTables = array_flip($existTables); - - foreach($renameTables as $oldTable => $newTable) - { - if(isset($existTables[$newTable])) - { - echo "Has existed table '$newTable'\n"; - } - elseif(!isset($existTables[$oldTable])) - { - echo "No found table '$oldTable'\n"; - } - else - { - $this->dbh->query("RENAME TABLE `$oldTable` TO `$newTable`"); - echo "RENAME TABLE `$oldTable` TO `$newTable`\n"; - } - } - echo "Finish!\n"; - } - - /** - * Confirm clear data. - * - * @param string $confirm ''|no|yes - * @access public - * @return void - */ - public function clearData($confirm = '') - { - if($confirm == '') $this->display(); - - if($confirm == 'no') - { - die(js::confirm($this->lang->admin->confirmClearData, inlink('clearData', "confirm=yes"))); - } - elseif($confirm == 'yes') - { - $result = $this->admin->clearData(); - if($result) - { - die(js::alert($this->lang->admin->clearDataSucceed)); - } - die(js::alert($this->lang->admin->clearDataFailed)); - } - } -} + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +class admin extends control +{ + /** + * Index page. + * @access public + * @return void + */ + public function index() + { + $community = zget($this->config->global, 'community'); + if(!$community or $community == 'na') + { + $this->view->bind = false; + $this->view->account = false; + $this->view->ignore = $community == 'na'; + } + else + { + $this->view->bind = true; + $this->view->account = $community; + $this->view->ignore = false; + } + + $this->app->loadLang('misc'); + $this->display(); + } + + /** + * Ignore notice of register and bind. + * + * @access public + * @return void + */ + public function ignore() + { + $this->loadModel('setting')->setItem('system.common.global.community', 'na'); + die(js::locate(inlink('index'), 'parent')); + } + + /** + * Register zentao. + * + * @access public + * @return void + */ + public function register() + { + if($_POST) + { + $response = $this->admin->registerByAPI(); + if($response == 'success') + { + $this->loadModel('setting')->setItem('system.common.global.community', $this->post->account); + echo js::alert($this->lang->admin->register->success); + die(js::locate(inlink('index'), 'parent')); + } + die($response); + } + $this->view->register = $this->admin->getRegisterInfo(); + $this->view->sn = $this->config->global->sn; + $this->display(); + } + + /** + * Bind zentao. + * + * @access public + * @return void + */ + public function bind() + { + if($_POST) + { + $response = $this->admin->bindByAPI(); + if($response == 'success') + { + $this->loadModel('setting')->setItem('system.common.global.community', $this->post->account); + echo js::alert($this->lang->admin->bind->success); + die(js::locate(inlink('index'), 'parent')); + } + die($response); + } + $this->view->sn = $this->config->global->sn; + $this->display(); + } + + /** + * Check all tables. + * + * @access public + * @return void + */ + public function checkDB() + { + $tables = $this->dbh->query('SHOW TABLES')->fetchAll(); + foreach($tables as $table) + { + $tableName = current((array)$table); + $result = $this->dbh->query("REPAIR TABLE $tableName")->fetch(); + echo "Repairing TABLE: " . $result->Table . "\t" . $result->Msg_type . ":" . $result->Msg_text . "\n"; + } + } + + /** + * Rename table for from windows to linux. + * + * @access public + * @return void + */ + public function win2Unix() + { + $renameTables = array( + 'zt_casestep' => 'zt_caseStep' , + 'zt_doclib' => 'zt_docLib' , + 'zt_grouppriv' => 'zt_groupPriv' , + 'zt_productplan' => 'zt_productPlan' , + 'zt_projectproduct' => 'zt_projectProduct' , + 'zt_projectstory' => 'zt_projectStory' , + 'zt_relationoftasks' => 'zt_relationOfTasks', + 'zt_storyspec' => 'zt_storySpec' , + 'zt_taskestimate' => 'zt_taskEstimate' , + 'zt_testresult' => 'zt_testResult' , + 'zt_testrun' => 'zt_testRun' , + 'zt_testtask' => 'zt_testTask' , + 'zt_usercontact' => 'zt_userContact' , + 'zt_usergroup' => 'zt_userGroup' , + 'zt_userquery' => 'zt_userQuery' , + 'zt_usertpl' => 'zt_userTPL' + ); + + $existTables = $this->dbh->query('SHOW TABLES')->fetchAll(); + foreach($existTables as $key => $table) $existTables[$key] = current((array)$table); + $existTables = array_flip($existTables); + + foreach($renameTables as $oldTable => $newTable) + { + if(isset($existTables[$newTable])) + { + echo "Has existed table '$newTable'\n"; + } + elseif(!isset($existTables[$oldTable])) + { + echo "No found table '$oldTable'\n"; + } + else + { + $this->dbh->query("RENAME TABLE `$oldTable` TO `$newTable`"); + echo "RENAME TABLE `$oldTable` TO `$newTable`\n"; + } + } + echo "Finish!\n"; + } + + /** + * Confirm clear data. + * + * @param string $confirm ''|no|yes + * @access public + * @return void + */ + public function clearData($confirm = '') + { + if($confirm == '') $this->display(); + + if($confirm == 'no') + { + die(js::confirm($this->lang->admin->confirmClearData, inlink('clearData', "confirm=yes"))); + } + elseif($confirm == 'yes') + { + $result = $this->admin->clearData(); + if($result) + { + die(js::alert($this->lang->admin->clearDataSucceed)); + } + die(js::alert($this->lang->admin->clearDataFailed)); + } + } +} diff --git a/module/admin/lang/en.php b/module/admin/lang/en.php index b121c7e970..713bda6441 100644 --- a/module/admin/lang/en.php +++ b/module/admin/lang/en.php @@ -1,56 +1,56 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->admin->common = 'Admin'; -$lang->admin->index = 'Index'; -$lang->admin->checkDB = 'Repair data'; -$lang->admin->company = 'Company'; -$lang->admin->user = 'User'; -$lang->admin->group = 'Group'; -$lang->admin->welcome = 'Welcome to ZenTaoPMS.'; - -$lang->admin->browseCompany = 'Browse Company'; - -$lang->admin->clearData = 'Clear Data'; -$lang->admin->confirmClearData = 'Are you sure to clear data?'; -$lang->admin->clearDataFailed = 'Failed to clear data!'; -$lang->admin->clearDataSucceed = 'Succeed to clear data!'; -$lang->admin->clearDataDesc = <<Clear data is dangerous. Be sure to backup your database and other data files and sure nobody is using pms when importing.\n -The impact of clearing data: -1、Clearing data will have no effect on table company,table group,and table groupPriv. -2、If you have choosed import demo data when installing,then clearing data will delete the item where key equals showDemoUsers on config table, and delete all demo users on user table. -3、For others tables:clear all data. -EOT; - -$lang->admin->info = new stdclass(); -$lang->admin->info->caption = 'ZentaoPMS information'; -$lang->admin->info->version = 'The current version of the system is %s,'; -$lang->admin->info->links = 'You can visit the following link:'; -$lang->admin->info->account = 'Your account in zentao community is %s. '; - -$lang->admin->notice = new stdclass(); -$lang->admin->notice->register = "Tips: You have not registered in Zentao community (www.zentao.net), %s to register and get the latest information about ZentaoPMS."; -$lang->admin->notice->ignore = "ignore"; - -$lang->admin->register = new stdclass(); -$lang->admin->register->caption = 'Register zentao community'; -$lang->admin->register->click = 'click'; -$lang->admin->register->lblAccount = 'Numbers and letters, at least three'; -$lang->admin->register->lblPasswd = 'Numbers and letters, at least six'; -$lang->admin->register->submit = 'Register'; -$lang->admin->register->bind = "If you have community account, %s to bind it"; -$lang->admin->register->success = "Register success"; - -$lang->admin->bind = new stdclass(); -$lang->admin->bind->caption = 'Bind with community account'; -$lang->admin->bind->action = 'bind'; -$lang->admin->bind->success = "Bind success"; + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->admin->common = 'Admin'; +$lang->admin->index = 'Index'; +$lang->admin->checkDB = 'Repair data'; +$lang->admin->company = 'Company'; +$lang->admin->user = 'User'; +$lang->admin->group = 'Group'; +$lang->admin->welcome = 'Welcome to ZenTaoPMS.'; + +$lang->admin->browseCompany = 'Browse Company'; + +$lang->admin->clearData = 'Clear Data'; +$lang->admin->confirmClearData = 'Are you sure to clear data?'; +$lang->admin->clearDataFailed = 'Failed to clear data!'; +$lang->admin->clearDataSucceed = 'Succeed to clear data!'; +$lang->admin->clearDataDesc = <<Clear data is dangerous. Be sure to backup your database and other data files and sure nobody is using pms when importing.\n +The impact of clearing data: +1、Clearing data will have no effect on table company,table group,and table groupPriv. +2、If you have choosed import demo data when installing,then clearing data will delete the item where key equals showDemoUsers on config table, and delete all demo users on user table. +3、For others tables:clear all data. +EOT; + +$lang->admin->info = new stdclass(); +$lang->admin->info->caption = 'ZentaoPMS information'; +$lang->admin->info->version = 'The current version of the system is %s,'; +$lang->admin->info->links = 'You can visit the following link:'; +$lang->admin->info->account = 'Your account in zentao community is %s. '; + +$lang->admin->notice = new stdclass(); +$lang->admin->notice->register = "Tips: You have not registered in Zentao community (www.zentao.net), %s to register and get the latest information about ZentaoPMS."; +$lang->admin->notice->ignore = "ignore"; + +$lang->admin->register = new stdclass(); +$lang->admin->register->caption = 'Register zentao community'; +$lang->admin->register->click = 'click'; +$lang->admin->register->lblAccount = 'Numbers and letters, at least three'; +$lang->admin->register->lblPasswd = 'Numbers and letters, at least six'; +$lang->admin->register->submit = 'Register'; +$lang->admin->register->bind = "If you have community account, %s to bind it"; +$lang->admin->register->success = "Register success"; + +$lang->admin->bind = new stdclass(); +$lang->admin->bind->caption = 'Bind with community account'; +$lang->admin->bind->action = 'bind'; +$lang->admin->bind->success = "Bind success"; diff --git a/module/admin/lang/zh-cn.php b/module/admin/lang/zh-cn.php index 8ca846522b..28656ece62 100644 --- a/module/admin/lang/zh-cn.php +++ b/module/admin/lang/zh-cn.php @@ -1,56 +1,56 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->admin->common = '后台管理'; -$lang->admin->index = '后台管理首页'; -$lang->admin->checkDB = '修正数据'; -$lang->admin->company = '公司管理'; -$lang->admin->user = '用户管理'; -$lang->admin->group = '分组管理'; -$lang->admin->welcome = '欢迎使用禅道管理软件后台管理系统'; - -$lang->admin->browseCompany = '浏览公司'; - -$lang->admin->clearData = '清除数据'; -$lang->admin->confirmClearData = '您确认要清除数据吗?'; -$lang->admin->clearDataFailed = '清除数据失败!'; -$lang->admin->clearDataSucceed = '清除数据成功!'; -$lang->admin->clearDataDesc = <<清除数据存在一定的风险,清楚数据之前,我们强烈建议您备份数据库及相应的数据文件,并保证清除数据的时候,没有其他人进行操作。\n -清除数据对数据库的影响如下: -1、清除数据不会对company, group, groupPriv表进行操作。 -2、如果安装的时候有导入demo数据,则会删除config表key=showDemoUsers的记录,并删除user表中的所有demo用户。 -3、对于其他表则进行全部清除操作。 -EOT; - -$lang->admin->info = new stdclass(); -$lang->admin->info->caption = '禅道系统信息'; -$lang->admin->info->version = '当前系统的版本是%s,'; -$lang->admin->info->links = '您可以访问以下链接:'; -$lang->admin->info->account = "您的禅道社区账户为%s。"; - -$lang->admin->notice = new stdclass(); -$lang->admin->notice->register = "友情提示:您还未在禅道社区(www.zentao.net)登记,%s进行登记,以及时获得禅道最新信息。"; -$lang->admin->notice->ignore = "不再提示"; - -$lang->admin->register = new stdclass(); -$lang->admin->register->caption = '禅道社区登记'; -$lang->admin->register->click = '点击此处'; -$lang->admin->register->lblAccount = '请设置您的用户名,英文字母和数字的组合,三位以上。'; -$lang->admin->register->lblPasswd = '请设置您的密码。数字和字母的组合,六位以上。'; -$lang->admin->register->submit = '登记'; -$lang->admin->register->bind = "如果您已经拥有社区账号,%s关联账户"; -$lang->admin->register->success = "登记账户成功"; - -$lang->admin->bind = new stdclass(); -$lang->admin->bind->caption = '关联社区账号'; -$lang->admin->bind->action = '关联'; -$lang->admin->bind->success = "关联账户成功"; + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->admin->common = '后台管理'; +$lang->admin->index = '后台管理首页'; +$lang->admin->checkDB = '修正数据'; +$lang->admin->company = '公司管理'; +$lang->admin->user = '用户管理'; +$lang->admin->group = '分组管理'; +$lang->admin->welcome = '欢迎使用禅道管理软件后台管理系统'; + +$lang->admin->browseCompany = '浏览公司'; + +$lang->admin->clearData = '清除数据'; +$lang->admin->confirmClearData = '您确认要清除数据吗?'; +$lang->admin->clearDataFailed = '清除数据失败!'; +$lang->admin->clearDataSucceed = '清除数据成功!'; +$lang->admin->clearDataDesc = <<清除数据存在一定的风险,清楚数据之前,我们强烈建议您备份数据库及相应的数据文件,并保证清除数据的时候,没有其他人进行操作。\n +清除数据对数据库的影响如下: +1、清除数据不会对company, group, groupPriv表进行操作。 +2、如果安装的时候有导入demo数据,则会删除config表key=showDemoUsers的记录,并删除user表中的所有demo用户。 +3、对于其他表则进行全部清除操作。 +EOT; + +$lang->admin->info = new stdclass(); +$lang->admin->info->caption = '禅道系统信息'; +$lang->admin->info->version = '当前系统的版本是%s,'; +$lang->admin->info->links = '您可以访问以下链接:'; +$lang->admin->info->account = "您的禅道社区账户为%s。"; + +$lang->admin->notice = new stdclass(); +$lang->admin->notice->register = "友情提示:您还未在禅道社区(www.zentao.net)登记,%s进行登记,以及时获得禅道最新信息。"; +$lang->admin->notice->ignore = "不再提示"; + +$lang->admin->register = new stdclass(); +$lang->admin->register->caption = '禅道社区登记'; +$lang->admin->register->click = '点击此处'; +$lang->admin->register->lblAccount = '请设置您的用户名,英文字母和数字的组合,三位以上。'; +$lang->admin->register->lblPasswd = '请设置您的密码。数字和字母的组合,六位以上。'; +$lang->admin->register->submit = '登记'; +$lang->admin->register->bind = "如果您已经拥有社区账号,%s关联账户"; +$lang->admin->register->success = "登记账户成功"; + +$lang->admin->bind = new stdclass(); +$lang->admin->bind->caption = '关联社区账号'; +$lang->admin->bind->action = '关联'; +$lang->admin->bind->success = "关联账户成功"; diff --git a/module/admin/lang/zh-tw.php b/module/admin/lang/zh-tw.php index 1c5311c300..59d3af086f 100644 --- a/module/admin/lang/zh-tw.php +++ b/module/admin/lang/zh-tw.php @@ -1,56 +1,56 @@ - - * @package admin - * @version $Id: zh-tw.php 3742 2012-12-10 08:41:09Z wwccss $ - * @link http://www.zentao.net - */ -$lang->admin->common = '後台管理'; -$lang->admin->index = '後台管理首頁'; -$lang->admin->checkDB = '修正數據'; -$lang->admin->company = '公司管理'; -$lang->admin->user = '用戶管理'; -$lang->admin->group = '分組管理'; -$lang->admin->welcome = '歡迎使用禪道管理軟件後台管理系統'; - -$lang->admin->browseCompany = '瀏覽公司'; - -$lang->admin->clearData = '清除數據'; -$lang->admin->confirmClearData = '您確認要清除數據嗎?'; -$lang->admin->clearDataFailed = '清除數據失敗!'; -$lang->admin->clearDataSucceed = '清除數據成功!'; -$lang->admin->clearDataDesc = <<清除數據存在一定的風險,清楚數據之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證清楚數據的時候,沒有其他人進行操作。\n -清除數據對資料庫的影響如下: -1、清除數據不會對company, group, groupPriv表進行操作。 -2、如果安裝的時候有導入demo數據,則會刪除config表key=showDemoUsers的記錄,並刪除user表中的所有demo用戶。 -3、對於其他表則進行全部清除操作。 -EOT; - -$lang->admin->info = new stdclass(); -$lang->admin->info->caption = '禪道系統信息'; -$lang->admin->info->version = '當前系統的版本是%s,'; -$lang->admin->info->links = '您可以訪問以下連結:'; -$lang->admin->info->account = "您的禪道社區賬戶為%s。"; - -$lang->admin->notice = new stdclass(); -$lang->admin->notice->register = "友情提示:您還未在禪道社區(www.zentao.net)登記,%s進行登記,以及時獲得禪道最新信息。"; -$lang->admin->notice->ignore = "不再提示"; - -$lang->admin->register = new stdclass(); -$lang->admin->register->caption = '禪道社區登記'; -$lang->admin->register->click = '點擊此處'; -$lang->admin->register->lblAccount = '請設置您的用戶名,英文字母和數字的組合,三位以上。'; -$lang->admin->register->lblPasswd = '請設置您的密碼。數字和字母的組合,六位以上。'; -$lang->admin->register->submit = '登記'; -$lang->admin->register->bind = "如果您已經擁有社區賬號,%s關聯賬戶"; -$lang->admin->register->success = "登記賬戶成功"; - -$lang->admin->bind = new stdclass(); -$lang->admin->bind->caption = '關聯社區賬號'; -$lang->admin->bind->action = '關聯'; -$lang->admin->bind->success = "關聯賬戶成功"; + + * @package admin + * @version $Id: zh-tw.php 3742 2012-12-10 08:41:09Z wwccss $ + * @link http://www.zentao.net + */ +$lang->admin->common = '後台管理'; +$lang->admin->index = '後台管理首頁'; +$lang->admin->checkDB = '修正數據'; +$lang->admin->company = '公司管理'; +$lang->admin->user = '用戶管理'; +$lang->admin->group = '分組管理'; +$lang->admin->welcome = '歡迎使用禪道管理軟件後台管理系統'; + +$lang->admin->browseCompany = '瀏覽公司'; + +$lang->admin->clearData = '清除數據'; +$lang->admin->confirmClearData = '您確認要清除數據嗎?'; +$lang->admin->clearDataFailed = '清除數據失敗!'; +$lang->admin->clearDataSucceed = '清除數據成功!'; +$lang->admin->clearDataDesc = <<清除數據存在一定的風險,清楚數據之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證清楚數據的時候,沒有其他人進行操作。\n +清除數據對資料庫的影響如下: +1、清除數據不會對company, group, groupPriv表進行操作。 +2、如果安裝的時候有導入demo數據,則會刪除config表key=showDemoUsers的記錄,並刪除user表中的所有demo用戶。 +3、對於其他表則進行全部清除操作。 +EOT; + +$lang->admin->info = new stdclass(); +$lang->admin->info->caption = '禪道系統信息'; +$lang->admin->info->version = '當前系統的版本是%s,'; +$lang->admin->info->links = '您可以訪問以下連結:'; +$lang->admin->info->account = "您的禪道社區賬戶為%s。"; + +$lang->admin->notice = new stdclass(); +$lang->admin->notice->register = "友情提示:您還未在禪道社區(www.zentao.net)登記,%s進行登記,以及時獲得禪道最新信息。"; +$lang->admin->notice->ignore = "不再提示"; + +$lang->admin->register = new stdclass(); +$lang->admin->register->caption = '禪道社區登記'; +$lang->admin->register->click = '點擊此處'; +$lang->admin->register->lblAccount = '請設置您的用戶名,英文字母和數字的組合,三位以上。'; +$lang->admin->register->lblPasswd = '請設置您的密碼。數字和字母的組合,六位以上。'; +$lang->admin->register->submit = '登記'; +$lang->admin->register->bind = "如果您已經擁有社區賬號,%s關聯賬戶"; +$lang->admin->register->success = "登記賬戶成功"; + +$lang->admin->bind = new stdclass(); +$lang->admin->bind->caption = '關聯社區賬號'; +$lang->admin->bind->action = '關聯'; +$lang->admin->bind->success = "關聯賬戶成功"; diff --git a/module/admin/model.php b/module/admin/model.php index 8b4e2c1e55..b2cf839087 100644 --- a/module/admin/model.php +++ b/module/admin/model.php @@ -1,183 +1,183 @@ - - * @package admin - * @version $Id$ - * @link http://www.zentao.net - */ -?> -setAgent(); - } - - /** - * Set the api agent. - * - * @access public - * @return void - */ - public function setAgent() - { - $this->agent = $this->app->loadClass('snoopy'); - } - - /** - * Post data form API - * - * @param string $url - * @param string $formvars - * @access public - * @return void - */ - public function postAPI($url, $formvars = "") - { - $this->agent->cookies['lang'] = $this->cookie->lang; - $this->agent->submit($url, $formvars); - return $this->agent->results; - } - - /** - * Get status of zentaopms. - * - * @access public - * @return void - */ - public function getStatOfPMS() - { - $sql = "SHOW TABLE STATUS"; - $tables = $this->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() - { - - } - - /** - * Register zentao by API. - * - * @access public - * @return void - */ - public function registerByAPI() - { - $apiURL = 'http://www.zentao.net/user-register.json'; - return $this->postAPI($apiURL, $_POST); - } - - /** - * Login zentao by API. - * - * @access public - * @return void - */ - public function bindByAPI() - { - $apiURL = 'http://www.zentao.net/user-login.json'; - return $this->postAPI($apiURL, $_POST); - } - - /** - * Get register information. - * - * @access public - * @return object - */ - public function getRegisterInfo() - { - $register = new stdclass(); - $register->company = $this->app->company->name; - $register->email = $this->app->user->email; - return $register; - } - - /** - * Clear data. - * - * @access public - * @return void - */ - public function clearData() - { - $result = $this->dbh->query('SHOW TABLES')->fetchAll(); - $showDemoUsers = $this->dao->select('value')->from(TABLE_CONFIG)->where('`key`')->eq('showDemoUsers')->fetch(); - foreach($result as $item) - { - $table = current((array)$item); - if(strpos($table, 'company') !== false) continue; - if(strpos($table, 'group') !== false) continue; - if(strpos($table, 'user') !== false) - { - if($showDemoUsers) - { - $this->dao->delete()->from($table) - ->where('account')->in(array('productManager', 'projectManager', 'testManager', 'dev1', 'dev2', 'dev3', 'tester1', 'tester2', 'tester3')) - ->exec(); - if(dao::isError()) return false; - } - continue; - } - if(strpos($table, 'config') !== false) - { - if($showDemoUsers) - { - $this->dao->delete()->from($table) - ->where('`key`')->eq('showDemoUsers') - ->exec(); - if(dao::isError()) return false; - } - continue; - } - if(!$this->dbh->query("TRUNCATE TABLE `$table`")) return false; - } - return true; - } -} + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +?> +setAgent(); + } + + /** + * Set the api agent. + * + * @access public + * @return void + */ + public function setAgent() + { + $this->agent = $this->app->loadClass('snoopy'); + } + + /** + * Post data form API + * + * @param string $url + * @param string $formvars + * @access public + * @return void + */ + public function postAPI($url, $formvars = "") + { + $this->agent->cookies['lang'] = $this->cookie->lang; + $this->agent->submit($url, $formvars); + return $this->agent->results; + } + + /** + * Get status of zentaopms. + * + * @access public + * @return void + */ + public function getStatOfPMS() + { + $sql = "SHOW TABLE STATUS"; + $tables = $this->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() + { + + } + + /** + * Register zentao by API. + * + * @access public + * @return void + */ + public function registerByAPI() + { + $apiURL = 'http://www.zentao.net/user-register.json'; + return $this->postAPI($apiURL, $_POST); + } + + /** + * Login zentao by API. + * + * @access public + * @return void + */ + public function bindByAPI() + { + $apiURL = 'http://www.zentao.net/user-login.json'; + return $this->postAPI($apiURL, $_POST); + } + + /** + * Get register information. + * + * @access public + * @return object + */ + public function getRegisterInfo() + { + $register = new stdclass(); + $register->company = $this->app->company->name; + $register->email = $this->app->user->email; + return $register; + } + + /** + * Clear data. + * + * @access public + * @return void + */ + public function clearData() + { + $result = $this->dbh->query('SHOW TABLES')->fetchAll(); + $showDemoUsers = $this->dao->select('value')->from(TABLE_CONFIG)->where('`key`')->eq('showDemoUsers')->fetch(); + foreach($result as $item) + { + $table = current((array)$item); + if(strpos($table, 'company') !== false) continue; + if(strpos($table, 'group') !== false) continue; + if(strpos($table, 'user') !== false) + { + if($showDemoUsers) + { + $this->dao->delete()->from($table) + ->where('account')->in(array('productManager', 'projectManager', 'testManager', 'dev1', 'dev2', 'dev3', 'tester1', 'tester2', 'tester3')) + ->exec(); + if(dao::isError()) return false; + } + continue; + } + if(strpos($table, 'config') !== false) + { + if($showDemoUsers) + { + $this->dao->delete()->from($table) + ->where('`key`')->eq('showDemoUsers') + ->exec(); + if(dao::isError()) return false; + } + continue; + } + if(!$this->dbh->query("TRUNCATE TABLE `$table`")) return false; + } + return true; + } +} diff --git a/module/admin/view/bind.html.php b/module/admin/view/bind.html.php index a20fa9ccb1..2fed12b7e9 100644 --- a/module/admin/view/bind.html.php +++ b/module/admin/view/bind.html.php @@ -1,30 +1,30 @@ - - * @package admin - * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -?> - -
- - - - - - - - - - - - - -
admin->bind->caption;?>
user->account;?>
user->password;?>
-
- + + * @package admin + * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + + + + + +
admin->bind->caption;?>
user->account;?>
user->password;?>
+
+ diff --git a/module/admin/view/browsecompany.html.php b/module/admin/view/browsecompany.html.php index 643096fc46..2ff4586b57 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/admin/view/cleardata.html.php b/module/admin/view/cleardata.html.php index 54d8e27775..06e782e49e 100755 --- a/module/admin/view/cleardata.html.php +++ b/module/admin/view/cleardata.html.php @@ -1,21 +1,21 @@ - - * @package admin - * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -?> - -
'> - - - - -
admin->clearData;?>
admin->clearDataDesc);?>
admin->clearData);?>
-
- + + * @package admin + * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +?> + +
'> + + + + +
admin->clearData;?>
admin->clearDataDesc);?>
admin->clearData);?>
+
+ diff --git a/module/admin/view/index.html.php b/module/admin/view/index.html.php index fe9da0666d..69100b7957 100644 --- a/module/admin/view/index.html.php +++ b/module/admin/view/index.html.php @@ -1,28 +1,28 @@ - - * @package admin - * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -?> - -

- admin->info->version, $config->version); - if($bind) echo sprintf($lang->admin->info->account, '' . $account . ''); - echo $lang->admin->info->links; - ?> -

- - -
-
admin->notice->register, html::a(inlink('register'), $lang->admin->register->click));?>
-
admin->notice->ignore, 'hiddenwin');?>
-
- - + + * @package admin + * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +?> + +

+ admin->info->version, $config->version); + if($bind) echo sprintf($lang->admin->info->account, '' . $account . ''); + echo $lang->admin->info->links; + ?> +

+ + +
+
admin->notice->register, html::a(inlink('register'), $lang->admin->register->click));?>
+
admin->notice->ignore, 'hiddenwin');?>
+
+ + diff --git a/module/admin/view/register.html.php b/module/admin/view/register.html.php index 1d3fd24f43..9ae9c5424f 100644 --- a/module/admin/view/register.html.php +++ b/module/admin/view/register.html.php @@ -1,57 +1,57 @@ - - * @package admin - * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ - * @link http://www.zentao.net - */ -?> - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
admin->register->caption;?>
user->account;?>*' . $lang->admin->register->lblAccount;?>
user->realname;?>*';?>
user->company;?>company, "class='text-3'");?>
user->phone;?>
user->email;?> - email, "class='text-3'") . '*';?>
user->password;?>*' . $lang->admin->register->lblPasswd;?>
user->password2;?> - *';?>
- - admin->register->submit) . html::hidden('sn', $sn); - echo "" . sprintf($lang->admin->register->bind, html::a(inlink('bind'), $lang->admin->register->click)) . ""; - ?> -
-
- + + * @package admin + * @version $Id: view.html.php 2568 2012-02-09 06:56:35Z shiyangyangwork@yahoo.cn $ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
admin->register->caption;?>
user->account;?>*' . $lang->admin->register->lblAccount;?>
user->realname;?>*';?>
user->company;?>company, "class='text-3'");?>
user->phone;?>
user->email;?> + email, "class='text-3'") . '*';?>
user->password;?>*' . $lang->admin->register->lblPasswd;?>
user->password2;?> + *';?>
+ + admin->register->submit) . html::hidden('sn', $sn); + echo "" . sprintf($lang->admin->register->bind, html::a(inlink('bind'), $lang->admin->register->click)) . ""; + ?> +
+
+ diff --git a/module/api/control.php b/module/api/control.php index bf3a050b00..c481df2957 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 db326bc1a1..90fbd1b0ad 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 eca46bcd28..6b1e7fb02c 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 2ccf5b7f25..448c8a676c 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 2605 2012-02-21 07:22:58Z wwccss $ - * @link http://www.zentao.net - */ -$lang->api->common = 'API介面'; -$lang->api->getModel = '超級model調用介面'; + + * @package api + * @version $Id: zh-tw.php 2605 2012-02-21 07:22:58Z wwccss $ + * @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 7b5d114ffe..dd017eca9f 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 4fec877863..7386bde556 100644 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1,1098 +1,1098 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -class bug extends control -{ - public $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. */ - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true); - - /* 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->loadModel('search')->setSearchParams($this->config->bug->search); - - $users = $this->user->getPairs('noletter'); - - /* Process the openedBuild and resolvedBuild fields. */ - $productIdList = array(); - foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product; - $builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList)); - foreach($bugs as $key => $bug) - { - $openBuildIdList = explode(',', $bug->openedBuild); - $openedBuild = ''; - foreach($openBuildIdList as $buildID) - { - $openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID; - $openedBuild .= ','; - } - $bug->openedBuild = rtrim($openedBuild, ','); - $bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild; - } - - $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,devfirst'); - 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->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); - $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, true); - if(!$bug) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Update action. */ - if($bug->assignedTo == $this->app->user->account) $this->loadModel('action')->read('bug', $bugID); - - /* 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 = "BUG #$bug->id $bug->title - " . $this->products[$productID]; - $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('bug', $bugID); - - $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->bug->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(); - } - - /** - * Batch edit bug. - * - * @param string $from example:bugBrowse, bugBatchEdit. - * @param int $productID - * @param string $orderBy - * @access public - * @return void - */ - public function batchEdit($from = '', $productID = 0, $orderBy = '') - { - if($from == 'bugBrowse') - { - /* Initialize vars.*/ - if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc'; - $editedBugs = array(); - $allBugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugQueryCondition)->orderBy($orderBy)->fetchAll('id'); - $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array(); - $product = $this->product->getByID($productID); - $columns = 9; - $showSuhosinInfo = false; - - /* Set product menu. */ - $this->bug->setMenu($this->products, $productID); - - /* Initialize the tasks whose need to edited. */ - foreach($allBugs as $bug) if(in_array($bug->id, $bugIDList)) $editedBugs[$bug->id] = $bug; - - /* Judge whether the editedTasks is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedBugs), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->bug->batchEdit; - $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->bug->common; - $this->view->position[] = $this->lang->bug->batchEdit; - - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->productID = $productID; - $this->view->editedBugs = $editedBugs; - $this->view->users = $this->user->getPairs('nodeleted,devfirst'); - - $this->display(); - } - elseif($from == 'bugBatchEdit') - { - $allChanges = $this->bug->batchUpdate(); - - foreach($allChanges as $bugID => $changes) - { - $actionID = $this->action->create('bug', $bugID, 'Edited'); - $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->bug->remindTask, $bug->task), $confirmURL, $cancelURL, 'parent', 'parent')); - } - } - } - } - die(js::locate($this->session->bugList, 'parent')); - } - } - - /** - * Update assign of bug. - * - * @param int $bugID - * @access public - * @return void - */ - public function assignTo($bugID) - { - $bug = $this->bug->getById($bugID); - - /* Set menu. */ - $this->bug->setMenu($this->products, $bug->product); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->bug->assign($bugID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo); - $this->action->logHistory($actionID, $changes); - $this->sendmail($bugID, $actionID); - - die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); - } - - $this->view->header->title = $this->products[$bug->product] . $this->lang->colon . $this->lang->bug->assignedTo; - $this->view->position[] = $this->lang->bug->assignedTo; - - $this->view->users = $this->user->getPairs('nodeleted'); - $this->view->bug = $bug; - $this->view->bugID = $bugID; - $this->view->actions = $this->action->getList('bug', $bugID); - $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->users = $this->user->getPairs('noletter'); - $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 - * @param string $id the id of the select control. - * @access public - * @return string - */ - public function ajaxGetUserBugs($account = '', $id = '') - { - if($account == '') $account = $this->app->user->account; - $bugs = $this->bug->getUserBugPairs($account); - - if($id) die(html::select("bugs[$id]", $bugs, '', 'class="select-1 f-left"')); - 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('QD'); - die($owner); - } - - /** - * AJAX: get assignedTo list, make sure the members of the project at the first. - * - * @param int $projectID - * @param string $selectedUser - * @access public - * @return string - */ - public function ajaxLoadAssignedTo($projectID, $selectedUser = '') - { - $allUsers = $this->loadModel('user')->getPairs('nodeleted, devfirst'); - $projectMembers = $this->loadModel('project')->getTeamMemberPairs($projectID); - $assignedToList = array_merge($projectMembers, $allUsers); - - die(html::select('assignedTo', $assignedToList, $selectedUser, 'class="select-3"')); - } - - /** - * Send email. - * - * @param int $bugID - * @param int $actionID - * @access public - * @return void - */ - public 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. */ - if($action->action == 'opened') $action->comment = ''; - $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)->where($this->session->bugQueryCondition) - ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() - ->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->post->set('kind', 'bug'); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +class bug extends control +{ + public $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. */ + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug', $browseType == 'needconfirm' ? false : true); + + /* 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->loadModel('search')->setSearchParams($this->config->bug->search); + + $users = $this->user->getPairs('noletter'); + + /* Process the openedBuild and resolvedBuild fields. */ + $productIdList = array(); + foreach($bugs as $bug) $productIdList[$bug->id] = $bug->product; + $builds = $this->loadModel('build')->getProductBuildPairs(array_unique($productIdList)); + foreach($bugs as $key => $bug) + { + $openBuildIdList = explode(',', $bug->openedBuild); + $openedBuild = ''; + foreach($openBuildIdList as $buildID) + { + $openedBuild .= isset($builds[$buildID]) ? $builds[$buildID] : $buildID; + $openedBuild .= ','; + } + $bug->openedBuild = rtrim($openedBuild, ','); + $bug->resolvedBuild = isset($builds[$bug->resolvedBuild]) ? $builds[$bug->resolvedBuild] : $bug->resolvedBuild; + } + + $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,devfirst'); + 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->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); + $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, true); + if(!$bug) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Update action. */ + if($bug->assignedTo == $this->app->user->account) $this->loadModel('action')->read('bug', $bugID); + + /* 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 = "BUG #$bug->id $bug->title - " . $this->products[$productID]; + $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('bug', $bugID); + + $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->bug->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(); + } + + /** + * Batch edit bug. + * + * @param string $from example:bugBrowse, bugBatchEdit. + * @param int $productID + * @param string $orderBy + * @access public + * @return void + */ + public function batchEdit($from = '', $productID = 0, $orderBy = '') + { + if($from == 'bugBrowse') + { + /* Initialize vars.*/ + if(!$orderBy) $orderBy = $this->cookie->qaBugOrder ? $this->cookie->qaBugOrder : 'id_desc'; + $editedBugs = array(); + $allBugs = $this->dao->select('*')->from(TABLE_BUG)->alias('t1')->where($this->session->bugQueryCondition)->orderBy($orderBy)->fetchAll('id'); + $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array(); + $product = $this->product->getByID($productID); + $columns = 9; + $showSuhosinInfo = false; + + /* Set product menu. */ + $this->bug->setMenu($this->products, $productID); + + /* Initialize the tasks whose need to edited. */ + foreach($allBugs as $bug) if(in_array($bug->id, $bugIDList)) $editedBugs[$bug->id] = $bug; + + /* Judge whether the editedTasks is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedBugs), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->bug->batchEdit; + $this->view->position[] = html::a($this->createLink('bug', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->bug->common; + $this->view->position[] = $this->lang->bug->batchEdit; + + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->productID = $productID; + $this->view->editedBugs = $editedBugs; + $this->view->users = $this->user->getPairs('nodeleted,devfirst'); + + $this->display(); + } + elseif($from == 'bugBatchEdit') + { + $allChanges = $this->bug->batchUpdate(); + + foreach($allChanges as $bugID => $changes) + { + $actionID = $this->action->create('bug', $bugID, 'Edited'); + $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->bug->remindTask, $bug->task), $confirmURL, $cancelURL, 'parent', 'parent')); + } + } + } + } + die(js::locate($this->session->bugList, 'parent')); + } + } + + /** + * Update assign of bug. + * + * @param int $bugID + * @access public + * @return void + */ + public function assignTo($bugID) + { + $bug = $this->bug->getById($bugID); + + /* Set menu. */ + $this->bug->setMenu($this->products, $bug->product); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->bug->assign($bugID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('bug', $bugID, 'Assigned', $this->post->comment, $this->post->assignedTo); + $this->action->logHistory($actionID, $changes); + $this->sendmail($bugID, $actionID); + + die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent')); + } + + $this->view->header->title = $this->products[$bug->product] . $this->lang->colon . $this->lang->bug->assignedTo; + $this->view->position[] = $this->lang->bug->assignedTo; + + $this->view->users = $this->user->getPairs('nodeleted'); + $this->view->bug = $bug; + $this->view->bugID = $bugID; + $this->view->actions = $this->action->getList('bug', $bugID); + $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->users = $this->user->getPairs('noletter'); + $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 + * @param string $id the id of the select control. + * @access public + * @return string + */ + public function ajaxGetUserBugs($account = '', $id = '') + { + if($account == '') $account = $this->app->user->account; + $bugs = $this->bug->getUserBugPairs($account); + + if($id) die(html::select("bugs[$id]", $bugs, '', 'class="select-1 f-left"')); + 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('QD'); + die($owner); + } + + /** + * AJAX: get assignedTo list, make sure the members of the project at the first. + * + * @param int $projectID + * @param string $selectedUser + * @access public + * @return string + */ + public function ajaxLoadAssignedTo($projectID, $selectedUser = '') + { + $allUsers = $this->loadModel('user')->getPairs('nodeleted, devfirst'); + $projectMembers = $this->loadModel('project')->getTeamMemberPairs($projectID); + $assignedToList = array_merge($projectMembers, $allUsers); + + die(html::select('assignedTo', $assignedToList, $selectedUser, 'class="select-3"')); + } + + /** + * Send email. + * + * @param int $bugID + * @param int $actionID + * @access public + * @return void + */ + public 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. */ + if($action->action == 'opened') $action->comment = ''; + $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)->where($this->session->bugQueryCondition) + ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() + ->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->post->set('kind', 'bug'); + $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 621622db5f..17a189d6bd 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -1,361 +1,361 @@ - - * @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'; -$lang->bug->fromCase = 'From case'; -$lang->bug->toCase = 'To case'; - -/* Actions. */ -$lang->bug->index = 'Index'; -$lang->bug->create = 'Create Bug'; -$lang->bug->confirmBug = 'Confirm Bug'; -$lang->bug->edit = 'Edit Bug'; -$lang->bug->batchEdit = 'Batch edit'; -$lang->bug->assignTo = 'Assign'; -$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->buttonAssign = 'Assgin'; -$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 = new stdclass(); -$lang->bug->report->common = 'Report'; -$lang->bug->report->select = 'Select'; -$lang->bug->report->create = 'Create'; - -$lang->bug->report->charts['bugsPerProject'] = 'Project bugs'; -$lang->bug->report->charts['bugsPerBuild'] = 'Build 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 = new stdclass(); -$lang->bug->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->bug->report->bugsPerBuild = new stdclass(); -$lang->bug->report->bugsPerModule = new stdclass(); -$lang->bug->report->openedBugsPerDay = new stdclass(); -$lang->bug->report->resolvedBugsPerDay = new stdclass(); -$lang->bug->report->closedBugsPerDay = new stdclass(); -$lang->bug->report->openedBugsPerUser = new stdclass(); -$lang->bug->report->resolvedBugsPerUser = new stdclass(); -$lang->bug->report->closedBugsPerUser = new stdclass(); -$lang->bug->report->bugsPerSeverity = new stdclass(); -$lang->bug->report->bugsPerResolution = new stdclass(); -$lang->bug->report->bugsPerStatus = new stdclass(); -$lang->bug->report->bugsPerActivatedCount = new stdclass(); -$lang->bug->report->bugsPerType = new stdclass(); -$lang->bug->report->bugsPerAssignedTo = new stdclass(); -$lang->bug->report->bugLiveDays = new stdclass(); -$lang->bug->report->bugHistories = new stdclass(); - -$lang->bug->report->bugsPerProject->graph = new stdclass(); -$lang->bug->report->bugsPerBuild->graph = new stdclass(); -$lang->bug->report->bugsPerModule->graph = new stdclass(); -$lang->bug->report->openedBugsPerDay->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); -$lang->bug->report->closedBugsPerDay->graph = new stdclass(); -$lang->bug->report->openedBugsPerUser->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); -$lang->bug->report->closedBugsPerUser->graph = new stdclass(); -$lang->bug->report->bugsPerSeverity->graph = new stdclass(); -$lang->bug->report->bugsPerResolution->graph = new stdclass(); -$lang->bug->report->bugsPerStatus->graph = new stdclass(); -$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); -$lang->bug->report->bugsPerType->graph = new stdclass(); -$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); -$lang->bug->report->bugLiveDays->graph = new stdclass(); -$lang->bug->report->bugHistories->graph = new stdclass(); - -$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project'; -$lang->bug->report->bugsPerBuild->graph->xAxisName = 'Build'; -$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 = new stdclass(); -$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.'); - -$lang->bug->placeholder = new stdclass(); -$lang->bug->placeholder->mailto = 'you can input the user account to select users to mail to.'; -$lang->bug->placeholder->keywords = 'keywords'; + + * @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'; +$lang->bug->fromCase = 'From case'; +$lang->bug->toCase = 'To case'; + +/* Actions. */ +$lang->bug->index = 'Index'; +$lang->bug->create = 'Create Bug'; +$lang->bug->confirmBug = 'Confirm Bug'; +$lang->bug->edit = 'Edit Bug'; +$lang->bug->batchEdit = 'Batch edit'; +$lang->bug->assignTo = 'Assign'; +$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->buttonAssign = 'Assgin'; +$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 = new stdclass(); +$lang->bug->report->common = 'Report'; +$lang->bug->report->select = 'Select'; +$lang->bug->report->create = 'Create'; + +$lang->bug->report->charts['bugsPerProject'] = 'Project bugs'; +$lang->bug->report->charts['bugsPerBuild'] = 'Build 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 = new stdclass(); +$lang->bug->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->bug->report->bugsPerBuild = new stdclass(); +$lang->bug->report->bugsPerModule = new stdclass(); +$lang->bug->report->openedBugsPerDay = new stdclass(); +$lang->bug->report->resolvedBugsPerDay = new stdclass(); +$lang->bug->report->closedBugsPerDay = new stdclass(); +$lang->bug->report->openedBugsPerUser = new stdclass(); +$lang->bug->report->resolvedBugsPerUser = new stdclass(); +$lang->bug->report->closedBugsPerUser = new stdclass(); +$lang->bug->report->bugsPerSeverity = new stdclass(); +$lang->bug->report->bugsPerResolution = new stdclass(); +$lang->bug->report->bugsPerStatus = new stdclass(); +$lang->bug->report->bugsPerActivatedCount = new stdclass(); +$lang->bug->report->bugsPerType = new stdclass(); +$lang->bug->report->bugsPerAssignedTo = new stdclass(); +$lang->bug->report->bugLiveDays = new stdclass(); +$lang->bug->report->bugHistories = new stdclass(); + +$lang->bug->report->bugsPerProject->graph = new stdclass(); +$lang->bug->report->bugsPerBuild->graph = new stdclass(); +$lang->bug->report->bugsPerModule->graph = new stdclass(); +$lang->bug->report->openedBugsPerDay->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); +$lang->bug->report->closedBugsPerDay->graph = new stdclass(); +$lang->bug->report->openedBugsPerUser->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); +$lang->bug->report->closedBugsPerUser->graph = new stdclass(); +$lang->bug->report->bugsPerSeverity->graph = new stdclass(); +$lang->bug->report->bugsPerResolution->graph = new stdclass(); +$lang->bug->report->bugsPerStatus->graph = new stdclass(); +$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); +$lang->bug->report->bugsPerType->graph = new stdclass(); +$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); +$lang->bug->report->bugLiveDays->graph = new stdclass(); +$lang->bug->report->bugHistories->graph = new stdclass(); + +$lang->bug->report->bugsPerProject->graph->xAxisName = 'Project'; +$lang->bug->report->bugsPerBuild->graph->xAxisName = 'Build'; +$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 = new stdclass(); +$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.'); + +$lang->bug->placeholder = new stdclass(); +$lang->bug->placeholder->mailto = 'you can input the user account to select users to mail to.'; +$lang->bug->placeholder->keywords = 'keywords'; diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index b5f2e3e88c..1288d98108 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -1,360 +1,360 @@ - - * @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 = '重复ID'; -$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->fromCase = '来源用例'; -$lang->bug->toCase = '生成用例'; - -/* 方法列表。*/ -$lang->bug->index = '首页'; -$lang->bug->create = '提Bug'; -$lang->bug->confirmBug = '确认'; -$lang->bug->edit = '编辑'; -$lang->bug->batchEdit = '批量编辑'; -$lang->bug->assignTo = '指派'; -$lang->bug->browse = 'Bug列表'; -$lang->bug->view = 'Bug详情'; -$lang->bug->resolve = '解决'; -$lang->bug->close = '关闭'; -$lang->bug->activate = '激活Bug'; -$lang->bug->reportChart = '报表统计'; -$lang->bug->export = '导出'; -$lang->bug->delete = '删除'; -$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 = '所有'; -$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->buttonAssign = '指派'; -$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 = new stdclass(); -$lang->bug->report->common = '报表'; -$lang->bug->report->select = '请选择报表类型'; -$lang->bug->report->create = '生成报表'; - -$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量'; -$lang->bug->report->charts['bugsPerBuild'] = '版本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 = new stdclass(); -$lang->bug->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->bug->report->bugsPerBuild = new stdclass(); -$lang->bug->report->bugsPerModule = new stdclass(); -$lang->bug->report->openedBugsPerDay = new stdclass(); -$lang->bug->report->resolvedBugsPerDay = new stdclass(); -$lang->bug->report->closedBugsPerDay = new stdclass(); -$lang->bug->report->openedBugsPerUser = new stdclass(); -$lang->bug->report->resolvedBugsPerUser = new stdclass(); -$lang->bug->report->closedBugsPerUser = new stdclass(); -$lang->bug->report->bugsPerSeverity = new stdclass(); -$lang->bug->report->bugsPerResolution = new stdclass(); -$lang->bug->report->bugsPerStatus = new stdclass(); -$lang->bug->report->bugsPerActivatedCount = new stdclass(); -$lang->bug->report->bugsPerType = new stdclass(); -$lang->bug->report->bugsPerAssignedTo = new stdclass(); -$lang->bug->report->bugLiveDays = new stdclass(); -$lang->bug->report->bugHistories = new stdclass(); - -$lang->bug->report->bugsPerProject->graph = new stdclass(); -$lang->bug->report->bugsPerBuild->graph = new stdclass(); -$lang->bug->report->bugsPerModule->graph = new stdclass(); -$lang->bug->report->openedBugsPerDay->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); -$lang->bug->report->closedBugsPerDay->graph = new stdclass(); -$lang->bug->report->openedBugsPerUser->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); -$lang->bug->report->closedBugsPerUser->graph = new stdclass(); -$lang->bug->report->bugsPerSeverity->graph = new stdclass(); -$lang->bug->report->bugsPerResolution->graph = new stdclass(); -$lang->bug->report->bugsPerStatus->graph = new stdclass(); -$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); -$lang->bug->report->bugsPerType->graph = new stdclass(); -$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); -$lang->bug->report->bugLiveDays->graph = new stdclass(); -$lang->bug->report->bugHistories->graph = new stdclass(); - -$lang->bug->report->bugsPerProject->graph->xAxisName = '项目'; -$lang->bug->report->bugsPerBuild->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 = new stdclass(); -$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。'); - -$lang->bug->placeholder = new stdclass(); -$lang->bug->placeholder->mailto = '输入用户名自动选择'; + + * @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 = '重复ID'; +$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->fromCase = '来源用例'; +$lang->bug->toCase = '生成用例'; + +/* 方法列表。*/ +$lang->bug->index = '首页'; +$lang->bug->create = '提Bug'; +$lang->bug->confirmBug = '确认'; +$lang->bug->edit = '编辑'; +$lang->bug->batchEdit = '批量编辑'; +$lang->bug->assignTo = '指派'; +$lang->bug->browse = 'Bug列表'; +$lang->bug->view = 'Bug详情'; +$lang->bug->resolve = '解决'; +$lang->bug->close = '关闭'; +$lang->bug->activate = '激活Bug'; +$lang->bug->reportChart = '报表统计'; +$lang->bug->export = '导出'; +$lang->bug->delete = '删除'; +$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 = '所有'; +$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->buttonAssign = '指派'; +$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 = new stdclass(); +$lang->bug->report->common = '报表'; +$lang->bug->report->select = '请选择报表类型'; +$lang->bug->report->create = '生成报表'; + +$lang->bug->report->charts['bugsPerProject'] = '项目Bug数量'; +$lang->bug->report->charts['bugsPerBuild'] = '版本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 = new stdclass(); +$lang->bug->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->bug->report->bugsPerBuild = new stdclass(); +$lang->bug->report->bugsPerModule = new stdclass(); +$lang->bug->report->openedBugsPerDay = new stdclass(); +$lang->bug->report->resolvedBugsPerDay = new stdclass(); +$lang->bug->report->closedBugsPerDay = new stdclass(); +$lang->bug->report->openedBugsPerUser = new stdclass(); +$lang->bug->report->resolvedBugsPerUser = new stdclass(); +$lang->bug->report->closedBugsPerUser = new stdclass(); +$lang->bug->report->bugsPerSeverity = new stdclass(); +$lang->bug->report->bugsPerResolution = new stdclass(); +$lang->bug->report->bugsPerStatus = new stdclass(); +$lang->bug->report->bugsPerActivatedCount = new stdclass(); +$lang->bug->report->bugsPerType = new stdclass(); +$lang->bug->report->bugsPerAssignedTo = new stdclass(); +$lang->bug->report->bugLiveDays = new stdclass(); +$lang->bug->report->bugHistories = new stdclass(); + +$lang->bug->report->bugsPerProject->graph = new stdclass(); +$lang->bug->report->bugsPerBuild->graph = new stdclass(); +$lang->bug->report->bugsPerModule->graph = new stdclass(); +$lang->bug->report->openedBugsPerDay->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); +$lang->bug->report->closedBugsPerDay->graph = new stdclass(); +$lang->bug->report->openedBugsPerUser->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); +$lang->bug->report->closedBugsPerUser->graph = new stdclass(); +$lang->bug->report->bugsPerSeverity->graph = new stdclass(); +$lang->bug->report->bugsPerResolution->graph = new stdclass(); +$lang->bug->report->bugsPerStatus->graph = new stdclass(); +$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); +$lang->bug->report->bugsPerType->graph = new stdclass(); +$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); +$lang->bug->report->bugLiveDays->graph = new stdclass(); +$lang->bug->report->bugHistories->graph = new stdclass(); + +$lang->bug->report->bugsPerProject->graph->xAxisName = '项目'; +$lang->bug->report->bugsPerBuild->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 = new stdclass(); +$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。'); + +$lang->bug->placeholder = new stdclass(); +$lang->bug->placeholder->mailto = '输入用户名自动选择'; diff --git a/module/bug/lang/zh-tw.php b/module/bug/lang/zh-tw.php index de43502e37..83abcc7aec 100644 --- a/module/bug/lang/zh-tw.php +++ b/module/bug/lang/zh-tw.php @@ -1,360 +1,360 @@ - - * @package bug - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @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 = '重複ID'; -$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->fromCase = '來源用例'; -$lang->bug->toCase = '生成用例'; - -/* 方法列表。*/ -$lang->bug->index = '首頁'; -$lang->bug->create = '創建'; -$lang->bug->confirmBug = '確認'; -$lang->bug->edit = '編輯'; -$lang->bug->batchEdit = '批量編輯'; -$lang->bug->assignTo = '指派'; -$lang->bug->browse = 'Bug列表'; -$lang->bug->view = 'Bug詳情'; -$lang->bug->resolve = '解決'; -$lang->bug->close = '關閉'; -$lang->bug->activate = '激活Bug'; -$lang->bug->reportChart = '報表統計'; -$lang->bug->export = '導出'; -$lang->bug->delete = '刪除'; -$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 = '所有'; -$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->buttonAssign = '指派'; -$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 = new stdclass(); -$lang->bug->report->common = '報表'; -$lang->bug->report->select = '請選擇報表類型'; -$lang->bug->report->create = '生成報表'; - -$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量'; -$lang->bug->report->charts['bugsPerBuild'] = '版本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 = new stdclass(); -$lang->bug->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->bug->report->bugsPerBuild = new stdclass(); -$lang->bug->report->bugsPerModule = new stdclass(); -$lang->bug->report->openedBugsPerDay = new stdclass(); -$lang->bug->report->resolvedBugsPerDay = new stdclass(); -$lang->bug->report->closedBugsPerDay = new stdclass(); -$lang->bug->report->openedBugsPerUser = new stdclass(); -$lang->bug->report->resolvedBugsPerUser = new stdclass(); -$lang->bug->report->closedBugsPerUser = new stdclass(); -$lang->bug->report->bugsPerSeverity = new stdclass(); -$lang->bug->report->bugsPerResolution = new stdclass(); -$lang->bug->report->bugsPerStatus = new stdclass(); -$lang->bug->report->bugsPerActivatedCount = new stdclass(); -$lang->bug->report->bugsPerType = new stdclass(); -$lang->bug->report->bugsPerAssignedTo = new stdclass(); -$lang->bug->report->bugLiveDays = new stdclass(); -$lang->bug->report->bugHistories = new stdclass(); - -$lang->bug->report->bugsPerProject->graph = new stdclass(); -$lang->bug->report->bugsPerBuild->graph = new stdclass(); -$lang->bug->report->bugsPerModule->graph = new stdclass(); -$lang->bug->report->openedBugsPerDay->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); -$lang->bug->report->closedBugsPerDay->graph = new stdclass(); -$lang->bug->report->openedBugsPerUser->graph = new stdclass(); -$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); -$lang->bug->report->closedBugsPerUser->graph = new stdclass(); -$lang->bug->report->bugsPerSeverity->graph = new stdclass(); -$lang->bug->report->bugsPerResolution->graph = new stdclass(); -$lang->bug->report->bugsPerStatus->graph = new stdclass(); -$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); -$lang->bug->report->bugsPerType->graph = new stdclass(); -$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); -$lang->bug->report->bugLiveDays->graph = new stdclass(); -$lang->bug->report->bugHistories->graph = new stdclass(); - -$lang->bug->report->bugsPerProject->graph->xAxisName = '項目'; -$lang->bug->report->bugsPerBuild->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 = new stdclass(); -$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。'); - -$lang->bug->placeholder = new stdclass(); -$lang->bug->placeholder->mailto = '輸入用戶名自動選擇'; + + * @package bug + * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ + * @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 = '重複ID'; +$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->fromCase = '來源用例'; +$lang->bug->toCase = '生成用例'; + +/* 方法列表。*/ +$lang->bug->index = '首頁'; +$lang->bug->create = '創建'; +$lang->bug->confirmBug = '確認'; +$lang->bug->edit = '編輯'; +$lang->bug->batchEdit = '批量編輯'; +$lang->bug->assignTo = '指派'; +$lang->bug->browse = 'Bug列表'; +$lang->bug->view = 'Bug詳情'; +$lang->bug->resolve = '解決'; +$lang->bug->close = '關閉'; +$lang->bug->activate = '激活Bug'; +$lang->bug->reportChart = '報表統計'; +$lang->bug->export = '導出'; +$lang->bug->delete = '刪除'; +$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 = '所有'; +$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->buttonAssign = '指派'; +$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 = new stdclass(); +$lang->bug->report->common = '報表'; +$lang->bug->report->select = '請選擇報表類型'; +$lang->bug->report->create = '生成報表'; + +$lang->bug->report->charts['bugsPerProject'] = '項目Bug數量'; +$lang->bug->report->charts['bugsPerBuild'] = '版本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 = new stdclass(); +$lang->bug->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->bug->report->bugsPerBuild = new stdclass(); +$lang->bug->report->bugsPerModule = new stdclass(); +$lang->bug->report->openedBugsPerDay = new stdclass(); +$lang->bug->report->resolvedBugsPerDay = new stdclass(); +$lang->bug->report->closedBugsPerDay = new stdclass(); +$lang->bug->report->openedBugsPerUser = new stdclass(); +$lang->bug->report->resolvedBugsPerUser = new stdclass(); +$lang->bug->report->closedBugsPerUser = new stdclass(); +$lang->bug->report->bugsPerSeverity = new stdclass(); +$lang->bug->report->bugsPerResolution = new stdclass(); +$lang->bug->report->bugsPerStatus = new stdclass(); +$lang->bug->report->bugsPerActivatedCount = new stdclass(); +$lang->bug->report->bugsPerType = new stdclass(); +$lang->bug->report->bugsPerAssignedTo = new stdclass(); +$lang->bug->report->bugLiveDays = new stdclass(); +$lang->bug->report->bugHistories = new stdclass(); + +$lang->bug->report->bugsPerProject->graph = new stdclass(); +$lang->bug->report->bugsPerBuild->graph = new stdclass(); +$lang->bug->report->bugsPerModule->graph = new stdclass(); +$lang->bug->report->openedBugsPerDay->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerDay->graph = new stdclass(); +$lang->bug->report->closedBugsPerDay->graph = new stdclass(); +$lang->bug->report->openedBugsPerUser->graph = new stdclass(); +$lang->bug->report->resolvedBugsPerUser->graph = new stdclass(); +$lang->bug->report->closedBugsPerUser->graph = new stdclass(); +$lang->bug->report->bugsPerSeverity->graph = new stdclass(); +$lang->bug->report->bugsPerResolution->graph = new stdclass(); +$lang->bug->report->bugsPerStatus->graph = new stdclass(); +$lang->bug->report->bugsPerActivatedCount->graph = new stdclass(); +$lang->bug->report->bugsPerType->graph = new stdclass(); +$lang->bug->report->bugsPerAssignedTo->graph = new stdclass(); +$lang->bug->report->bugLiveDays->graph = new stdclass(); +$lang->bug->report->bugHistories->graph = new stdclass(); + +$lang->bug->report->bugsPerProject->graph->xAxisName = '項目'; +$lang->bug->report->bugsPerBuild->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 = new stdclass(); +$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。'); + +$lang->bug->placeholder = new stdclass(); +$lang->bug->placeholder->mailto = '輸入用戶名自動選擇'; diff --git a/module/bug/model.php b/module/bug/model.php index a633757505..bd1c6b201e 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1,1214 +1,1214 @@ - - * @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 : $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 - * @param bool $setImgSize - * @access public - * @return object - */ - public function getById($bugID, $setImgSize = false) - { - $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; - - if($setImgSize) $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->toCases = array(); - $toCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('`fromBug`')->eq($bugID)->fetchAll(); - foreach($toCases as $toCase) $bug->toCases[$toCase->id] = $toCase->title; - - $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); - } - - /** - * Batch update bugs. - * - * @access public - * @return array - */ - public function batchUpdate() - { - $bugs = array(); - $allChanges = array(); - $now = helper::now(); - $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $bugIDList. */ - if($this->session->showSuhosinInfo) array_pop($bugIDList); - - if(!empty($bugIDList)) - { - /* Initialize bugs from the post data.*/ - foreach($bugIDList as $bugID) - { - $oldBug = $this->getByID($bugID); - - $bug->lastEditedBy = $this->app->user->account; - $bug->lastEditedDate = $now; - $bug->type = $this->post->types[$bugID]; - $bug->severity = $this->post->severities[$bugID]; - $bug->pri = $this->post->pris[$bugID]; - $bug->status = $this->post->statuses[$bugID]; - $bug->title = htmlspecialchars($this->post->titles[$bugID]); - $bug->assignedTo = $this->post->assignedTos[$bugID]; - $bug->resolvedBy = $this->post->resolvedBys[$bugID]; - $bug->resolution = $this->post->resolutions[$bugID]; - $bug->duplicateBug = $this->post->duplicateBugs[$bugID] ? $this->post->duplicateBugs[$bugID] : $oldBug->duplicateBug; - - if($bug->assignedTo != $oldBug->assignedTo) $bug->assignedDate = $now; - if($bug->resolvedBy != '' or $bug->resolution != '') $bug->resolvedDate = $now; - if($bug->resolution != '' and $bug->resolvedBy == '') $bug->resolvedBy = $this->app->user->account; - if($bug->resolution != '') - { - $bug->status = 'resolved'; - $bug->confirmed = 1; - } - if($bug->resolution != '' and $bug->assignedTo == '') - { - $bug->assignedTo = $oldBug->openedBy; - $bug->assignedDate = $now; - } - - $bugs[$bugID] = $bug; - unset($bug); - } - - /* Update bugs. */ - foreach($bugs as $bugID => $bug) - { - $oldBug = $this->getByID($bugID); - - $this->dao->update(TABLE_BUG)->data($bug) - ->autoCheck() - ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') - ->checkIF($bug->resolvedBy, 'resolution', 'notempty') - ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') - ->where('id')->eq((int)$bugID) - ->exec(); - - if(!dao::isError()) - { - $allChanges[$bugID] = common::createChanges($oldBug, $bug); - } - else - { - die(js::error('bug#' . $bugID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - /** - * Assign a bug to a user again. - * - * @param int $bugID - * @access public - * @return void - */ - public function assign($bugID) - { - $now = helper::now(); - $oldBug = $this->getById($bugID); - $bug = fixer::input('post') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) - ->remove('comment') - ->get(); - - $this->dao->update(TABLE_BUG) - ->data($bug) - ->autoCheck() - ->where('id')->eq($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(); - $oldBug = $this->getById($bugID); - $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) - { - $bugs = $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(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); - - return $bugs; - } - - /** - * Get bugs according to buildID and productID. - * - * @param int $buildID - * @param int $productID - * @access public - * @return object - */ - public function getReleaseBugs($buildID, $productID) - { - $project = $this->dao->select('t1.begin') - ->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_BUILD)->alias('t2') - ->on('t1.id = t2.project') - ->where('t2.id')->eq($buildID) - ->fetch(); - $bugs = $this->dao->select('*')->from(TABLE_BUG) - ->where('resolvedDate')->ge($project->begin) - ->andWhere('product')->eq($productID) - ->orderBy('openedDate ASC') - ->fetchAll(); - return $bugs; - } - - /** - * 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->reportCondition())->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 build. - * - * @access public - * @return void - */ - public function getDataOfBugsPerBuild() - { - $datas = $this->dao->select('openedBuild as name, count(openedBuild) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('openedBuild')->orderBy('value DESC')->fetchAll('name'); - if(!$datas) return array(); - $builds = $this->loadModel('build')->getProductBuildPairs($this->session->product); - - /* Deal with the situation that a bug maybe associate more than one openedBuild. */ - foreach($datas as $buildIDList => $data) - { - $openBuildIDList = explode(',', $buildIDList); - if(count($openBuildIDList) > 1) - { - foreach($openBuildIDList as $buildID) - { - if(isset($datas[$buildID])) - { - $datas[$buildID]->value++; - } - else - { - $datas[$buildID]->name = $buildID; - $datas[$buildID]->value = 1; - } - } - unset($datas[$buildIDList]); - } - } - - foreach($datas as $buildID => $data) - { - $data->name = isset($builds[$buildID]) ? $builds[$buildID] : $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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition())->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->reportCondition()) - ->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition()) - ->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) - { - $bugs = $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(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); - - return $bugs; - } - - /** - * 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.product')->eq($productID) - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t2.version > t1.storyVersion') - ->andWhere('t1.project')->in(array_keys($projects)) - ->orderBy($orderBy) - ->page($pager) - ->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. - $bugQuery = $this->loadModel('search')->replaceDynamic($bugQuery); - $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; - } - - /** - * Adjust the action is clickable. - * - * @param string $bug - * @param string $action - * @access public - * @return void - */ - public function isClickable($object, $action) - { - $action = strtolower($action); - - if($action == 'confirmbug') return $object->status == 'active' and $object->confirmed == 0; - if($action == 'resolve') return $object->status == 'active'; - if($action == 'close') return $object->status == 'resolved'; - if($action == 'activate') return $object->status != 'active'; - if($action == 'tostory') return $object->status == 'active'; - - return true; - } - - /** - * Get report condition from session. - * - * @access public - * @return void - */ - public function reportCondition() - { - if(!$this->session->bugOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->bugQueryCondition) . ')'; - return $this->session->bugQueryCondition; - } -} + + * @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 : $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 + * @param bool $setImgSize + * @access public + * @return object + */ + public function getById($bugID, $setImgSize = false) + { + $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; + + if($setImgSize) $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->toCases = array(); + $toCases = $this->dao->select('id, title')->from(TABLE_CASE)->where('`fromBug`')->eq($bugID)->fetchAll(); + foreach($toCases as $toCase) $bug->toCases[$toCase->id] = $toCase->title; + + $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); + } + + /** + * Batch update bugs. + * + * @access public + * @return array + */ + public function batchUpdate() + { + $bugs = array(); + $allChanges = array(); + $now = helper::now(); + $bugIDList = $this->post->bugIDList ? $this->post->bugIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $bugIDList. */ + if($this->session->showSuhosinInfo) array_pop($bugIDList); + + if(!empty($bugIDList)) + { + /* Initialize bugs from the post data.*/ + foreach($bugIDList as $bugID) + { + $oldBug = $this->getByID($bugID); + + $bug->lastEditedBy = $this->app->user->account; + $bug->lastEditedDate = $now; + $bug->type = $this->post->types[$bugID]; + $bug->severity = $this->post->severities[$bugID]; + $bug->pri = $this->post->pris[$bugID]; + $bug->status = $this->post->statuses[$bugID]; + $bug->title = htmlspecialchars($this->post->titles[$bugID]); + $bug->assignedTo = $this->post->assignedTos[$bugID]; + $bug->resolvedBy = $this->post->resolvedBys[$bugID]; + $bug->resolution = $this->post->resolutions[$bugID]; + $bug->duplicateBug = $this->post->duplicateBugs[$bugID] ? $this->post->duplicateBugs[$bugID] : $oldBug->duplicateBug; + + if($bug->assignedTo != $oldBug->assignedTo) $bug->assignedDate = $now; + if($bug->resolvedBy != '' or $bug->resolution != '') $bug->resolvedDate = $now; + if($bug->resolution != '' and $bug->resolvedBy == '') $bug->resolvedBy = $this->app->user->account; + if($bug->resolution != '') + { + $bug->status = 'resolved'; + $bug->confirmed = 1; + } + if($bug->resolution != '' and $bug->assignedTo == '') + { + $bug->assignedTo = $oldBug->openedBy; + $bug->assignedDate = $now; + } + + $bugs[$bugID] = $bug; + unset($bug); + } + + /* Update bugs. */ + foreach($bugs as $bugID => $bug) + { + $oldBug = $this->getByID($bugID); + + $this->dao->update(TABLE_BUG)->data($bug) + ->autoCheck() + ->batchCheck($this->config->bug->edit->requiredFields, 'notempty') + ->checkIF($bug->resolvedBy, 'resolution', 'notempty') + ->checkIF($bug->resolution == 'duplicate', 'duplicateBug', 'notempty') + ->where('id')->eq((int)$bugID) + ->exec(); + + if(!dao::isError()) + { + $allChanges[$bugID] = common::createChanges($oldBug, $bug); + } + else + { + die(js::error('bug#' . $bugID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + /** + * Assign a bug to a user again. + * + * @param int $bugID + * @access public + * @return void + */ + public function assign($bugID) + { + $now = helper::now(); + $oldBug = $this->getById($bugID); + $bug = fixer::input('post') + ->setDefault('lastEditedBy', $this->app->user->account) + ->setDefault('lastEditedDate', $now) + ->remove('comment') + ->get(); + + $this->dao->update(TABLE_BUG) + ->data($bug) + ->autoCheck() + ->where('id')->eq($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(); + $oldBug = $this->getById($bugID); + $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) + { + $bugs = $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(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); + + return $bugs; + } + + /** + * Get bugs according to buildID and productID. + * + * @param int $buildID + * @param int $productID + * @access public + * @return object + */ + public function getReleaseBugs($buildID, $productID) + { + $project = $this->dao->select('t1.begin') + ->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_BUILD)->alias('t2') + ->on('t1.id = t2.project') + ->where('t2.id')->eq($buildID) + ->fetch(); + $bugs = $this->dao->select('*')->from(TABLE_BUG) + ->where('resolvedDate')->ge($project->begin) + ->andWhere('product')->eq($productID) + ->orderBy('openedDate ASC') + ->fetchAll(); + return $bugs; + } + + /** + * 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->reportCondition())->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 build. + * + * @access public + * @return void + */ + public function getDataOfBugsPerBuild() + { + $datas = $this->dao->select('openedBuild as name, count(openedBuild) as value')->from(TABLE_BUG)->where($this->reportCondition())->groupBy('openedBuild')->orderBy('value DESC')->fetchAll('name'); + if(!$datas) return array(); + $builds = $this->loadModel('build')->getProductBuildPairs($this->session->product); + + /* Deal with the situation that a bug maybe associate more than one openedBuild. */ + foreach($datas as $buildIDList => $data) + { + $openBuildIDList = explode(',', $buildIDList); + if(count($openBuildIDList) > 1) + { + foreach($openBuildIDList as $buildID) + { + if(isset($datas[$buildID])) + { + $datas[$buildID]->value++; + } + else + { + $datas[$buildID]->name = $buildID; + $datas[$buildID]->value = 1; + } + } + unset($datas[$buildIDList]); + } + } + + foreach($datas as $buildID => $data) + { + $data->name = isset($builds[$buildID]) ? $builds[$buildID] : $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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition())->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->reportCondition()) + ->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->reportCondition())->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->reportCondition())->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->reportCondition())->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->reportCondition()) + ->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) + { + $bugs = $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(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); + + return $bugs; + } + + /** + * 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.product')->eq($productID) + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.version > t1.storyVersion') + ->andWhere('t1.project')->in(array_keys($projects)) + ->orderBy($orderBy) + ->page($pager) + ->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. + $bugQuery = $this->loadModel('search')->replaceDynamic($bugQuery); + $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; + } + + /** + * Adjust the action is clickable. + * + * @param string $bug + * @param string $action + * @access public + * @return void + */ + public function isClickable($object, $action) + { + $action = strtolower($action); + + if($action == 'confirmbug') return $object->status == 'active' and $object->confirmed == 0; + if($action == 'resolve') return $object->status == 'active'; + if($action == 'close') return $object->status == 'resolved'; + if($action == 'activate') return $object->status != 'active'; + if($action == 'tostory') return $object->status == 'active'; + + return true; + } + + /** + * Get report condition from session. + * + * @access public + * @return void + */ + public function reportCondition() + { + if(!$this->session->bugOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->bugQueryCondition) . ')'; + return $this->session->bugQueryCondition; + } +} diff --git a/module/bug/view/activate.html.php b/module/bug/view/activate.html.php index 8d056326c9..b8cab88ac8 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/assignto.html.php b/module/bug/view/assignto.html.php index 10b8f35672..843b432b78 100644 --- a/module/bug/view/assignto.html.php +++ b/module/bug/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 - */ -?> - -
- - - - - - - - - - - - - -
title;?>
bug->assignedTo;?>
comment;?>
goback, $this->server->http_referer);?>
- -
- + + * @package task + * @version $Id: complete.html.php 935 2010-07-06 07:49:24Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + +
+ + + + + + + + + + + + + +
title;?>
bug->assignedTo;?>
comment;?>
goback, $this->server->http_referer);?>
+ +
+ diff --git a/module/bug/view/batchedit.html.php b/module/bug/view/batchedit.html.php index d1f2d7da59..0e91e4752f 100644 --- a/module/bug/view/batchedit.html.php +++ b/module/bug/view/batchedit.html.php @@ -1,59 +1,59 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
"> - - - - - - - - - - - - - - - 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']); - ?> - - - - - - - - - - - - - - - - -
bug->common . $lang->colon . $lang->bug->batchEdit;?>
idAB;?>bug->type;?>bug->severityAB;?>bug->pri;?> bug->title;?>bug->assignedTo;?>bug->status;?>bug->resolvedByAB;?>bug->resolutionAB;?>
id . html::hidden("bugIDList[$bug->id]", $bug->id);?>id]", $lang->bug->typeList, $bug->type, 'class=select-1');?>id]", (array)$lang->bug->severityList, $bug->severity, 'class=select-1');?>id]", (array)$lang->bug->priList, $bug->pri, 'class=select-1');?>id]", $bug->title, 'class=text-1'); echo "*";?>id]", $users, $bug->assignedTo, 'class=select-1');?>id]", (array)$lang->bug->statusList, $bug->status, 'class=select-1');?>id]", $users, $bug->resolvedBy, 'class=select-1');?> -
id]", $this->lang->bug->resolutionList, $bug->resolution, "class=w-80px onchange=setDuplicate(this.value,$bug->id)");?>
-
id;?>' resolution != 'duplicate') echo "style='display:none'";?>>id]", '', "class=w-40px placeholder='{$lang->bug->duplicateBug}'");?>
-
-
- + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
"> + + + + + + + + + + + + + + + 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']); + ?> + + + + + + + + + + + + + + + + +
bug->common . $lang->colon . $lang->bug->batchEdit;?>
idAB;?>bug->type;?>bug->severityAB;?>bug->pri;?> bug->title;?>bug->assignedTo;?>bug->status;?>bug->resolvedByAB;?>bug->resolutionAB;?>
id . html::hidden("bugIDList[$bug->id]", $bug->id);?>id]", $lang->bug->typeList, $bug->type, 'class=select-1');?>id]", (array)$lang->bug->severityList, $bug->severity, 'class=select-1');?>id]", (array)$lang->bug->priList, $bug->pri, 'class=select-1');?>id]", $bug->title, 'class=text-1'); echo "*";?>id]", $users, $bug->assignedTo, 'class=select-1');?>id]", (array)$lang->bug->statusList, $bug->status, 'class=select-1');?>id]", $users, $bug->resolvedBy, 'class=select-1');?> +
id]", $this->lang->bug->resolutionList, $bug->resolution, "class=w-80px onchange=setDuplicate(this.value,$bug->id)");?>
+
id;?>' resolution != 'duplicate') echo "style='display:none'";?>>id]", '', "class=w-40px placeholder='{$lang->bug->duplicateBug}'");?>
+
+
+ diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index ac6693bbd5..a9b7211e10 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -1,183 +1,183 @@ - - * @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} "; - ?> -
-
- -
-
-
'>
- - - -
'> - - - - - - -
-
-
- -
- tree->manage);?> - tree->fix, 'hiddenwin');?> -
-
-
- recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - id");?> - - - - - - confirmed;?> - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - cookie->windowWidth >= $this->config->wideSize):?> - - - - - - - - - - - cookie->windowWidth >= $this->config->wideSize ? 12 : 9; - if($browseType == 'needconfirm') $columns = $this->cookie->windowWidth >= $this->config->wideSize ? 7 : 6; - ?> - - - -
idAB);?> bug->severityAB);?> priAB);?>bug->title);?>bug->statusAB);?>bug->story);?>actions;?>openedByAB);?> bug->openedDateAB);?>assignedToAB);?>bug->resolvedByAB);?>bug->resolutionAB);?> bug->resolvedDateAB);?>actions;?>
- - id));?> - severity;?>'>severity;?>bug->priList[$bug->pri];?>'>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');?>bug->confirmStoryChange = $lang->confirm; common::printIcon('bug', 'confirmStoryChange', "bugID=$bug->id", '', 'list', '', 'hiddenwin')?>openedBy];?>openedDate, 5, 11)?>assignedTo == $this->app->user->account) echo 'class="red"';?>>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>resolvedDate, 5, 11)?> - id"; - common::printIcon('bug', 'resolve', $params, $bug, 'list'); - common::printIcon('bug', 'close', $params, $bug, 'list'); - common::printIcon('bug', 'edit', $params, $bug, 'list'); - common::printIcon('bug', 'create', "product=$bug->product&extra=bugID=$bug->id", $bug, 'list', 'copy'); - ?> -
- -
- bug->batchEdit); - ?> -
- -
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} "; + ?> +
+
+ +
+
+
'>
+ + + +
'> + + + + + + +
+
+
+ +
+ tree->manage);?> + tree->fix, 'hiddenwin');?> +
+
+
+ recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + id");?> + + + + + + confirmed;?> + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + cookie->windowWidth >= $this->config->wideSize):?> + + + + + + + + + + + cookie->windowWidth >= $this->config->wideSize ? 12 : 9; + if($browseType == 'needconfirm') $columns = $this->cookie->windowWidth >= $this->config->wideSize ? 7 : 6; + ?> + + + +
idAB);?> bug->severityAB);?> priAB);?>bug->title);?>bug->statusAB);?>bug->story);?>actions;?>openedByAB);?> bug->openedDateAB);?>assignedToAB);?>bug->resolvedByAB);?>bug->resolutionAB);?> bug->resolvedDateAB);?>actions;?>
+ + id));?> + severity;?>'>severity;?>bug->priList[$bug->pri];?>'>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');?>bug->confirmStoryChange = $lang->confirm; common::printIcon('bug', 'confirmStoryChange', "bugID=$bug->id", '', 'list', '', 'hiddenwin')?>openedBy];?>openedDate, 5, 11)?>assignedTo == $this->app->user->account) echo 'class="red"';?>>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>resolvedDate, 5, 11)?> + id"; + common::printIcon('bug', 'resolve', $params, $bug, 'list'); + common::printIcon('bug', 'close', $params, $bug, 'list'); + common::printIcon('bug', 'edit', $params, $bug, 'list'); + common::printIcon('bug', 'create', "product=$bug->product&extra=bugID=$bug->id", $bug, 'list', 'copy'); + ?> +
+ +
+ bug->batchEdit); + ?> +
+ +
show();?>
+
+
+
+ diff --git a/module/bug/view/close.html.php b/module/bug/view/close.html.php index 678f8e599c..cf452f2f25 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 d3c562b5fe..a3fd0b6c7a 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 3b89729b70..f035a74a9d 100644 --- a/module/bug/view/create.html.php +++ b/module/bug/view/create.html.php @@ -1,112 +1,112 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> -bug->placeholder, 'json'); -js::set('userList', array_keys($users), 'json'); -js::set('page', 'create'); -?> - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bug->create;?>
bug->lblProductAndModule;?> - - -
bug->project;?>
bug->openedBuild;?> - - build->notice;?> -
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->placeholder, 'json'); +js::set('userList', array_keys($users), 'json'); +js::set('page', 'create'); +?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bug->create;?>
bug->lblProductAndModule;?> + + +
bug->project;?>
bug->openedBuild;?> + + build->notice;?> +
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 bcef9b5dbe..7ad89572b7 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 6e454288fe..4d055bce3f 100644 --- a/module/bug/view/edit.html.php +++ b/module/bug/view/edit.html.php @@ -1,205 +1,205 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> -bug->confirmChangeProduct); -js::set('oldProjectID' , $bug->project); -js::set('oldStoryID' , $bug->story); -js::set('oldTaskID' , $bug->task); -js::set('oldOpenedBuild' , $bug->openedBuild); -js::set('oldResolvedBuild' , $bug->resolvedBuild); -js::set('userList' , array_keys($users), 'json'); -?> - -
-
-
- 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->confirmChangeProduct); +js::set('oldProjectID' , $bug->project); +js::set('oldStoryID' , $bug->story); +js::set('oldTaskID' , $bug->task); +js::set('oldOpenedBuild' , $bug->openedBuild); +js::set('oldResolvedBuild' , $bug->resolvedBuild); +js::set('userList' , array_keys($users), 'json'); +?> + + +
+
+ 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 3f1bb625f8..1c2af170e3 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 d2ae5eb9ae..c509f50417 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;?>
-
createLink('bug', 'browse', "productID=$productID&browseType=$browseType&moduleID=$moduleID")); ?>
-
- - - - - - - -
-
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;?>
+
createLink('bug', 'browse', "productID=$productID&browseType=$browseType&moduleID=$moduleID")); ?>
+
+ + + + + + + +
+
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 dd080dbd70..fe9fdf4524 100644 --- a/module/bug/view/resolve.html.php +++ b/module/bug/view/resolve.html.php @@ -1,51 +1,51 @@ - - * @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->resolvedDate;?>
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->resolvedDate;?>
bug->assignedTo;?>openedBy, 'class=select-3');?>
comment;?>
+ + +
+ +
+ diff --git a/module/bug/view/sendmail.html.php b/module/bug/view/sendmail.html.php index faa4c96b61..849af86b24 100644 --- a/module/bug/view/sendmail.html.php +++ b/module/bug/view/sendmail.html.php @@ -1,39 +1,39 @@ - - * @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);?> -
-
- bug->legendSteps;?> -
- steps, 'src="data/upload')) - { - $bug->steps = str_replace('server->http_host . $this->config->webRoot, $bug->steps); - $bug->steps = str_replace('server->http_host . $this->config->webRoot, $bug->steps); - } - echo $bug->steps; - ?> -
-
-
+ + * @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);?> +
+
+ bug->legendSteps;?> +
+ steps, 'src="data/upload')) + { + $bug->steps = str_replace('server->http_host . $this->config->webRoot, $bug->steps); + $bug->steps = str_replace('server->http_host . $this->config->webRoot, $bug->steps); + } + echo $bug->steps; + ?> +
+
+
diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index 6d526e2882..81de9cbd0f 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -1,286 +1,286 @@ - - * @package bug - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
-
deleted) echo "class='deleted'";?>>BUG #id . ' ' . $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) - { - ob_start(); - common::printIcon('bug', 'confirmBug', $params, $bug); - common::printIcon('bug', 'assignTo', $params); - common::printIcon('bug', 'resolve', $params, $bug); - common::printIcon('bug', 'close', $params, $bug); - common::printIcon('bug', 'activate', $params, $bug); - - common::printIcon('bug', 'toStory', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $bug, 'button', 'toStory'); - common::printIcon('bug', 'createCase', $convertParams, '', 'button', 'createCase'); - - common::printDivider(); - common::printIcon('bug', 'edit', $params); - common::printCommentIcon('bug'); - common::printIcon('bug', 'create', $copyParams, '', 'button', 'copy'); - common::printIcon('bug', 'delete', $params, '', 'button', '', 'hiddenwin'); - - common::printDivider(); - common::printRPN($browseLink, $preAndNext); - - $actionLinks = ob_get_contents(); - ob_end_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
-
- - - - - - - -
-
- bug->legendSteps;?> -
[', '

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

-
- fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?> - - - -
-
- 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->case;?> - - - - - - - - - -
bug->fromCase;?>case) echo html::a($this->createLink('case', 'view', "caseID=$bug->case"), $bug->caseTitle);?>
bug->toCase;?> - toCases as $caseID => $case) - { - echo '

' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '

'; - } - ?> -
-
- -
- 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->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('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
-
-
- - + + * @package bug + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
deleted) echo "class='deleted'";?>>BUG #id . ' ' . $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) + { + ob_start(); + common::printIcon('bug', 'confirmBug', $params, $bug); + common::printIcon('bug', 'assignTo', $params); + common::printIcon('bug', 'resolve', $params, $bug); + common::printIcon('bug', 'close', $params, $bug); + common::printIcon('bug', 'activate', $params, $bug); + + common::printIcon('bug', 'toStory', "product=$bug->product&module=0&story=0&project=0&bugID=$bug->id", $bug, 'button', 'toStory'); + common::printIcon('bug', 'createCase', $convertParams, '', 'button', 'createCase'); + + common::printDivider(); + common::printIcon('bug', 'edit', $params); + common::printCommentIcon('bug'); + common::printIcon('bug', 'create', $copyParams, '', 'button', 'copy'); + common::printIcon('bug', 'delete', $params, '', 'button', '', 'hiddenwin'); + + common::printDivider(); + common::printRPN($browseLink, $preAndNext); + + $actionLinks = ob_get_contents(); + ob_end_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
+
+ + + + + + + +
+
+ bug->legendSteps;?> +
[', '

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

+
+ fetch('file', 'printFiles', array('files' => $bug->files, 'fieldset' => 'true'));?> + + + +
+
+ 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->case;?> + + + + + + + + + +
bug->fromCase;?>case) echo html::a($this->createLink('case', 'view', "caseID=$bug->case"), $bug->caseTitle);?>
bug->toCase;?> + toCases as $caseID => $case) + { + echo '

' . html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case) . '

'; + } + ?> +
+
+ +
+ 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->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('task', 'view', "taskID=$bug->toTask"), "#$bug->toTask $bug->toTaskTitle", '_blank');?>
+
+
+ + diff --git a/module/build/control.php b/module/build/control.php index ca45408850..f7fef037bc 100644 --- a/module/build/control.php +++ b/module/build/control.php @@ -1,192 +1,192 @@ - - * @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->bug->getProjectBugs($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->bug->getProjectBugs($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, true); - if(!$build) die(js::error($this->lang->notFound) . js::locate('back')); - - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll(); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll(); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); - - $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project); - - /* Assign. */ - $projects = $this->project->getPairs(); - $this->view->header->title = "BUILD #$build->id $build->name - " . $projects[$build->project]; - $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')); - if($varName == 'testTaskBuild') die(html::select('build', $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->bug->getProjectBugs($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->bug->getProjectBugs($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, true); + if(!$build) die(js::error($this->lang->notFound) . js::locate('back')); + + $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($build->stories)->fetchAll(); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + + $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->fetchAll(); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); + + $this->loadModel('project')->setMenu($this->project->getPairs(), $build->project); + + /* Assign. */ + $projects = $this->project->getPairs(); + $this->view->header->title = "BUILD #$build->id $build->name - " . $projects[$build->project]; + $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')); + if($varName == 'testTaskBuild') die(html::select('build', $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 3f38c5da77..d1d5cb0daf 100644 --- a/module/build/lang/en.php +++ b/module/build/lang/en.php @@ -1,42 +1,42 @@ - - * @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->basicInfo='Basic Info'; - -$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'; - -$lang->build->finishStories = 'The total demand for a complete %s'; -$lang->build->resolvedBugs = 'The total solution of bug%s'; - -$lang->build->notice = "Please create a build in project view's build page."; + + * @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->basicInfo='Basic Info'; + +$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'; + +$lang->build->finishStories = 'The total demand for a complete %s'; +$lang->build->resolvedBugs = 'The total solution of bug%s'; + +$lang->build->notice = "Please create a build in project view's build page."; diff --git a/module/build/lang/zh-cn.php b/module/build/lang/zh-cn.php index 8ee155d78a..daa005bb4a 100644 --- a/module/build/lang/zh-cn.php +++ b/module/build/lang/zh-cn.php @@ -1,42 +1,42 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->build->common = "Build"; -$lang->build->create = "创建版本"; -$lang->build->edit = "编辑版本"; -$lang->build->delete = "删除版本"; -$lang->build->view = "版本详情"; -$lang->build->ajaxGetProductBuilds = '接口:产品版本列表'; -$lang->build->ajaxGetProjectBuilds = '接口:项目版本列表'; - -$lang->build->confirmDelete = "您确认删除该版本吗?"; - -$lang->build->basicInfo ='基本信息'; - -$lang->build->id = 'ID'; -$lang->build->product = '产品'; -$lang->build->project = '项目'; -$lang->build->name = '名称编号'; -$lang->build->date = '打包日期'; -$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'; - -$lang->build->finishStories = '本次共完成需求%s个'; -$lang->build->resolvedBugs = '本次共解决Bug%s个'; - -$lang->build->notice = '版本请到[项目视图]-[版本]创建。'; + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->build->common = "Build"; +$lang->build->create = "创建版本"; +$lang->build->edit = "编辑版本"; +$lang->build->delete = "删除版本"; +$lang->build->view = "版本详情"; +$lang->build->ajaxGetProductBuilds = '接口:产品版本列表'; +$lang->build->ajaxGetProjectBuilds = '接口:项目版本列表'; + +$lang->build->confirmDelete = "您确认删除该版本吗?"; + +$lang->build->basicInfo ='基本信息'; + +$lang->build->id = 'ID'; +$lang->build->product = '产品'; +$lang->build->project = '项目'; +$lang->build->name = '名称编号'; +$lang->build->date = '打包日期'; +$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'; + +$lang->build->finishStories = '本次共完成需求%s个'; +$lang->build->resolvedBugs = '本次共解决Bug%s个'; + +$lang->build->notice = '版本请到[项目视图]-[版本]创建。'; diff --git a/module/build/lang/zh-tw.php b/module/build/lang/zh-tw.php index a03b301f37..912f63a657 100644 --- a/module/build/lang/zh-tw.php +++ b/module/build/lang/zh-tw.php @@ -1,42 +1,42 @@ - - * @package build - * @version $Id: zh-tw.php 3309 2012-07-03 02:53:55Z wwccss $ - * @link http://www.zentao.net - */ -$lang->build->common = "Build"; -$lang->build->create = "創建版本"; -$lang->build->edit = "編輯版本"; -$lang->build->delete = "刪除版本"; -$lang->build->view = "版本詳情"; -$lang->build->ajaxGetProductBuilds = '介面:產品版本列表'; -$lang->build->ajaxGetProjectBuilds = '介面:項目版本列表'; - -$lang->build->confirmDelete = "您確認刪除該版本嗎?"; - -$lang->build->basicInfo ='基本信息'; - -$lang->build->id = 'ID'; -$lang->build->product = '產品'; -$lang->build->project = '項目'; -$lang->build->name = '名稱編號'; -$lang->build->date = '打包日期'; -$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'; - -$lang->build->finishStories = '本次共完成需求%s個'; -$lang->build->resolvedBugs = '本次共解決Bug%s個'; - -$lang->build->notice = '版本請到[項目視圖]-[版本]創建。'; + + * @package build + * @version $Id: zh-tw.php 3309 2012-07-03 02:53:55Z wwccss $ + * @link http://www.zentao.net + */ +$lang->build->common = "Build"; +$lang->build->create = "創建版本"; +$lang->build->edit = "編輯版本"; +$lang->build->delete = "刪除版本"; +$lang->build->view = "版本詳情"; +$lang->build->ajaxGetProductBuilds = '介面:產品版本列表'; +$lang->build->ajaxGetProjectBuilds = '介面:項目版本列表'; + +$lang->build->confirmDelete = "您確認刪除該版本嗎?"; + +$lang->build->basicInfo ='基本信息'; + +$lang->build->id = 'ID'; +$lang->build->product = '產品'; +$lang->build->project = '項目'; +$lang->build->name = '名稱編號'; +$lang->build->date = '打包日期'; +$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'; + +$lang->build->finishStories = '本次共完成需求%s個'; +$lang->build->resolvedBugs = '本次共解決Bug%s個'; + +$lang->build->notice = '版本請到[項目視圖]-[版本]創建。'; diff --git a/module/build/model.php b/module/build/model.php index f03c75a983..cda6824d56 100644 --- a/module/build/model.php +++ b/module/build/model.php @@ -1,154 +1,154 @@ - - * @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) - ->fetch(); - if(!$build) return false; - if($setImgSize) $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 mix $products int|array - * @param string $params noempty|notrunk, can be a set of them - * @access public - * @return string - */ - public function getProductBuildPairs($products, $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')->in($products) - ->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', ',') - ->remove('allchecker') - ->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', ',') - ->remove('allchecker') - ->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) + ->fetch(); + if(!$build) return false; + if($setImgSize) $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 mix $products int|array + * @param string $params noempty|notrunk, can be a set of them + * @access public + * @return string + */ + public function getProductBuildPairs($products, $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')->in($products) + ->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', ',') + ->remove('allchecker') + ->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', ',') + ->remove('allchecker') + ->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 4358abdd74..52cfdfd683 100644 --- a/module/build/view/create.html.php +++ b/module/build/view/create.html.php @@ -1,132 +1,132 @@ - - * @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->linkStories;?>
idAB;?>story->title;?>statusAB;?>story->stageAB;?>
-
-
- - $story):?> - createLink('story', 'view', "storyID=$story->id"); - ?> - - - - - - - -
- stage == 'developed' or $story->status == 'closed') echo 'checked';?>> id);?> - title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
-
-
-
- -
- - - - - - - -
- - - - - - - -
build->linkBugs;?>
idAB;?>bug->title;?>bug->status;?>
-
-
- - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - -
- status == 'resolved' or $bug->status == 'closed') echo "checked";?>> id);?> - title, '', "class='preview'");?>bug->statusList[$bug->status];?>
-
-
-
- -
-
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->linkStories;?>
idAB;?>story->title;?>statusAB;?>story->stageAB;?>
+
+
+ + $story):?> + createLink('story', 'view', "storyID=$story->id"); + ?> + + + + + + + +
+ stage == 'developed' or $story->status == 'closed') echo 'checked';?>> id);?> + title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
+
+
+
+ +
+ + + + + + + +
+ + + + + + + +
build->linkBugs;?>
idAB;?>bug->title;?>bug->status;?>
+
+
+ + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + +
+ status == 'resolved' or $bug->status == 'closed') echo "checked";?>> id);?> + title, '', "class='preview'");?>bug->statusList[$bug->status];?>
+
+
+
+ +
+
build->desc;?>
+
+ diff --git a/module/build/view/edit.html.php b/module/build/view/edit.html.php index 8b9d6dce05..a31eb1f038 100644 --- a/module/build/view/edit.html.php +++ b/module/build/view/edit.html.php @@ -1,126 +1,126 @@ - - * @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->linkStories;?>
idAB;?>story->title;?>statusAB;?>story->stageAB;?>
-
-
- - $story):?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - -
stories . ',', ',' . $story->id . ',') !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
-
-
-
- -
- - - - - - - -
- - - - - - - -
build->linkBugs;?>
idAB;?>bug->title;?>bug->status;?>
-
-
- - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - -
bugs . ',', ',' . $bug->id . ',') !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>
-
-
-
- -
-
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->linkStories;?>
idAB;?>story->title;?>statusAB;?>story->stageAB;?>
+
+
+ + $story):?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + +
stories . ',', ',' . $story->id . ',') !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
+
+
+
+ +
+ + + + + + + +
+ + + + + + + +
build->linkBugs;?>
idAB;?>bug->title;?>bug->status;?>
+
+
+ + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + +
bugs . ',', ',' . $bug->id . ',') !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>bug->statusList[$bug->status];?>
+
+
+
+ +
+
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 32736b6a54..530da83f7a 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -1,119 +1,119 @@ - - * @package build - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
'>BUILD #id . ' ' . $build->name;?>
-
- build->desc;?> -
desc;?>
-
- -
- session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project"); - if(!$build->deleted) - { - common::printIcon('build', 'edit', "buildID=$build->id"); - common::printIcon('build', 'delete', "buildID=$build->id", '', 'button', '', 'hiddenwin'); - } - echo common::printRPN($browseLink); - ?> -
- - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - - - - - -
build->stories;?>
idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
id);?>story->priList[$story->pri]?>'>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
build->finishStories, count($stories));?>
- - - - - - - - - - - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - - - - - - -
build->bugs;?>
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->resolvedBugs, count($bugs));?>
-
-
- build->basicInfo?> - - - - - - - - - - - - - - - - - - - - - - - - - -
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);?>
-
-
- + + * @package build + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
'>BUILD #id . ' ' . $build->name;?>
+
+ build->desc;?> +
desc;?>
+
+ +
+ session->buildList ? $this->session->buildList : $this->createLink('project', 'build', "projectID=$build->project"); + if(!$build->deleted) + { + common::printIcon('build', 'edit', "buildID=$build->id"); + common::printIcon('build', 'delete', "buildID=$build->id", '', 'button', '', 'hiddenwin'); + } + echo common::printRPN($browseLink); + ?> +
+ + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + + + + + +
build->stories;?>
idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
id);?>story->priList[$story->pri]?>'>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
build->finishStories, count($stories));?>
+ + + + + + + + + + + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + + + + + + +
build->bugs;?>
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->resolvedBugs, count($bugs));?>
+
+
+ build->basicInfo?> + + + + + + + + + + + + + + + + + + + + + + + + + +
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);?>
+
+
+ diff --git a/module/common/control.php b/module/common/control.php index c330e625ee..7a6ffeb040 100644 --- a/module/common/control.php +++ b/module/common/control.php @@ -1,414 +1,414 @@ - - * @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->common->loadConfigFromDB(); - $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 - * @param bool $newline - * @static - * @access public - * @return bool - */ - public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false) - { - if(!common::hasPriv($module, $method)) return false; - echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline); - return true; - } - - /** - * Print icon of split line. - * - * @static - * @access public - * @return void - */ - public static function printDivider() - { - echo "    "; - } - - /** - * Print icon of comment. - * - * @param string $module - * @static - * @access public - * @return void - */ - public static function printCommentIcon($module) - { - global $lang; - - if(!common::hasPriv($module, 'edit')) return false; - echo ""; - echo html::a('#comment', ' ', '', "class='icon-green-common-comment' title='$lang->comment' onclick='setComment()'"); - echo ""; - } - - /** - * Print link icon. - * - * @param string $module - * @param string $method - * @param string $vars - * @param object $object - * @param string $type button|list - * @param string $icon - * @param string $target - * @static - * @access public - * @return void - */ - public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false) - { - global $app, $lang; - - /* Judge the $method of $module clickable or not, default is clickable. */ - $clickable = true; - if(is_object($object)) - { - if($app->getModuleName() != $module) $app->control->loadModel($module); - $modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model"; - if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable'))) - { - $clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method)); - } - } - - /* Set module and method, then create link to it. */ - if(strtolower($module) == 'testcase' and strtolower($method) == 'createbug') ($module = 'bug') and ($method = 'create'); - if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create'); - if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create'); - if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create'); - if(!common::hasPriv($module, $method)) return false; - $link = helper::createLink($module, $method, $vars, '', $onlyBody); - - /* Set the icon title, try search the $method defination in $module's lang or $common's lang. */ - $title = $method; - if($method == 'create' and $icon == 'copy') $method = 'copy'; - if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method; - if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method)) - { - $title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method; - } - if($icon == 'toStory') $title = $lang->bug->toStory; - if($icon == 'createBug') $title = $lang->testtask->createBug; - - /* set the class. */ - if(!$icon) $icon = $method; - if(strpos(',edit,copy,report,export,delete,', ",$icon,") !== false) $module = 'common'; - $color = $type == 'button' ? 'green' : ($clickable ? 'green' : 'gray'); - $extraClass = strpos(',export,customFields,runCase,results,', ",$method,") !== false ? $method : $extraClass; - $class = $extraClass ? "icon-$color-$module-$icon $extraClass" : "icon-$color-$module-$icon"; - - /* Create the icon link. */ - if($clickable) - { - if($type == 'button') - { - echo ""; - echo html::a($link, ' ', $target, "class='$class' title='$title'", true); - if($method != 'edit' and $method != 'copy' and $method != 'delete') - { - echo html::a($link, $title, $target, "class='$extraClass'", true); - } - echo ""; - } - else - { - echo html::a($link, ' ', $target, "class='$class' title='$title'", false); - } - } - else - { - if($type == 'list') - { - echo " "; - } - } - } - - /** - * Print backLink and preLink and nextLink. - * - * @param string $backLink - * @param object $preAndNext - * @access public - * @return void - */ - public function printRPN($backLink, $preAndNext = '') - { - global $lang; - - echo ""; - echo html::a($backLink, ' ', '', "class='icon-goback' title={$lang->goback}"); - echo ""; - - if(isset($preAndNext->pre) and $preAndNext->pre) - { - $title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name; - $title = '#' . $preAndNext->pre->id . ' ' . $title; - echo ""; - echo html::a($this->inLink('view', "ID={$preAndNext->pre->id}"), ' ', '', "id='pre' class='icon-pre' title='{$title}'"); - echo ""; - } - if(isset($preAndNext->next) and $preAndNext->next) - { - $title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name; - $title = '#' . $preAndNext->next->id . ' ' . $title; - echo ""; - echo html::a($this->inLink('view', "ID={$preAndNext->next->id}"), ' ', '', "id='next' class='icon-next' title='$title'"); - echo ""; - } - } - - /** - * 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 != stripslashes($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,verify', 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->common->loadConfigFromDB(); + $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 + * @param bool $newline + * @static + * @access public + * @return bool + */ + public static function printLink($module, $method, $vars = '', $label, $target = '', $misc = '', $newline = true, $onlyBody = false) + { + if(!common::hasPriv($module, $method)) return false; + echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline); + return true; + } + + /** + * Print icon of split line. + * + * @static + * @access public + * @return void + */ + public static function printDivider() + { + echo "    "; + } + + /** + * Print icon of comment. + * + * @param string $module + * @static + * @access public + * @return void + */ + public static function printCommentIcon($module) + { + global $lang; + + if(!common::hasPriv($module, 'edit')) return false; + echo ""; + echo html::a('#comment', ' ', '', "class='icon-green-common-comment' title='$lang->comment' onclick='setComment()'"); + echo ""; + } + + /** + * Print link icon. + * + * @param string $module + * @param string $method + * @param string $vars + * @param object $object + * @param string $type button|list + * @param string $icon + * @param string $target + * @static + * @access public + * @return void + */ + public static function printIcon($module, $method, $vars = '', $object = '', $type = 'button', $icon = '', $target = '', $extraClass = '', $onlyBody = false) + { + global $app, $lang; + + /* Judge the $method of $module clickable or not, default is clickable. */ + $clickable = true; + if(is_object($object)) + { + if($app->getModuleName() != $module) $app->control->loadModel($module); + $modelClass = class_exists("ext{$module}Model") ? "ext{$module}Model" : $module . "Model"; + if(class_exists($modelClass) and is_callable(array($modelClass, 'isClickable'))) + { + $clickable = call_user_func_array(array($modelClass, 'isClickable'), array('object' => $object, 'method' => $method)); + } + } + + /* Set module and method, then create link to it. */ + if(strtolower($module) == 'testcase' and strtolower($method) == 'createbug') ($module = 'bug') and ($method = 'create'); + if(strtolower($module) == 'story' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create'); + if(strtolower($module) == 'bug' and strtolower($method) == 'tostory') ($module = 'story') and ($method = 'create'); + if(strtolower($module) == 'bug' and strtolower($method) == 'createcase') ($module = 'testcase') and ($method = 'create'); + if(!common::hasPriv($module, $method)) return false; + $link = helper::createLink($module, $method, $vars, '', $onlyBody); + + /* Set the icon title, try search the $method defination in $module's lang or $common's lang. */ + $title = $method; + if($method == 'create' and $icon == 'copy') $method = 'copy'; + if(isset($lang->$method) and is_string($lang->$method)) $title = $lang->$method; + if((isset($lang->$module->$method) or $app->loadLang($module)) and isset($lang->$module->$method)) + { + $title = $method == 'report' ? $lang->$module->$method->common : $lang->$module->$method; + } + if($icon == 'toStory') $title = $lang->bug->toStory; + if($icon == 'createBug') $title = $lang->testtask->createBug; + + /* set the class. */ + if(!$icon) $icon = $method; + if(strpos(',edit,copy,report,export,delete,', ",$icon,") !== false) $module = 'common'; + $color = $type == 'button' ? 'green' : ($clickable ? 'green' : 'gray'); + $extraClass = strpos(',export,customFields,runCase,results,', ",$method,") !== false ? $method : $extraClass; + $class = $extraClass ? "icon-$color-$module-$icon $extraClass" : "icon-$color-$module-$icon"; + + /* Create the icon link. */ + if($clickable) + { + if($type == 'button') + { + echo ""; + echo html::a($link, ' ', $target, "class='$class' title='$title'", true); + if($method != 'edit' and $method != 'copy' and $method != 'delete') + { + echo html::a($link, $title, $target, "class='$extraClass'", true); + } + echo ""; + } + else + { + echo html::a($link, ' ', $target, "class='$class' title='$title'", false); + } + } + else + { + if($type == 'list') + { + echo " "; + } + } + } + + /** + * Print backLink and preLink and nextLink. + * + * @param string $backLink + * @param object $preAndNext + * @access public + * @return void + */ + public function printRPN($backLink, $preAndNext = '') + { + global $lang; + + echo ""; + echo html::a($backLink, ' ', '', "class='icon-goback' title={$lang->goback}"); + echo ""; + + if(isset($preAndNext->pre) and $preAndNext->pre) + { + $title = isset($preAndNext->pre->title) ? $preAndNext->pre->title : $preAndNext->pre->name; + $title = '#' . $preAndNext->pre->id . ' ' . $title; + echo ""; + echo html::a($this->inLink('view', "ID={$preAndNext->pre->id}"), ' ', '', "id='pre' class='icon-pre' title='{$title}'"); + echo ""; + } + if(isset($preAndNext->next) and $preAndNext->next) + { + $title = isset($preAndNext->next->title) ? $preAndNext->next->title : $preAndNext->next->name; + $title = '#' . $preAndNext->next->id . ' ' . $title; + echo ""; + echo html::a($this->inLink('view', "ID={$preAndNext->next->id}"), ' ', '', "id='next' class='icon-next' title='$title'"); + echo ""; + } + } + + /** + * 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 != stripslashes($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,verify', 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 b750dcdb98..ae77c6d4a8 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -1,395 +1,395 @@ - - * @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->exportType = 'Exprot Type'; -$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->selectReverse = 'Select Reverse'; -$lang->notFound = 'Sorry, the object not found.'; -$lang->showAll = '++ Show All ++'; -$lang->hideClosed = '-- Show Progressing --'; - -$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 = new stdclass(); -$lang->common->common = 'Common module'; - -/* The main menu. */ -$lang->menu = new stdclass(); -$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->report = 'Report|report|index'; -$lang->menu->webapp = 'Web App|webapp|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(ctrl+g)'; - -/* Encode list of impot. */ -$lang->importEncodeList['gbk'] = 'GBK'; -$lang->importEncodeList['big5'] = 'BIG5'; -$lang->importEncodeList['utf-8'] = 'UTF-8'; - -/* File type of export. */ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -$lang->exportTypeList['all'] = 'Export ALL'; -$lang->exportTypeList['selected'] = 'Export Checked'; - -/* Support charset. */ -$lang->exportEncodeList['gbk'] = 'GBK'; -$lang->exportEncodeList['big5'] = 'BIG5'; -$lang->exportEncodeList['utf-8'] = 'UTF-8'; - -/* Themes. */ -$lang->themes['default'] = 'Default'; -$lang->themes['green'] = 'Green'; -$lang->themes['red'] = 'Red'; -$lang->themes['classblue'] = 'Blue'; - -/* Index mododule menu. */ -$lang->index = new stdclass(); -$lang->index->menu = new stdclass(); - -$lang->index->menu->product = 'Products|product|browse'; -$lang->index->menu->project = 'Projects|project|browse'; - -/* Dashboard menu. */ -$lang->my = new stdclass(); -$lang->my->menu = new stdclass(); - -$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 = array('link' => 'Test|my|testtask|', 'alias' => 'testcase'); -$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->my->menu->changePassword = 'Change Password|my|changepassword|'; - -$lang->todo = new stdclass(); -$lang->todo->menu = $lang->my->menu; - -/* Product menu. */ -$lang->product = new stdclass(); -$lang->product->menu = new stdclass(); - -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => 'Manage|product|view|productID=%s', 'alias' => 'edit'); -$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story'; -$lang->product->menu->project = 'Projects|product|project|status=all&productID=%s'; -$lang->product->menu->order = 'Order|product|order|productID=%s'; -$lang->product->menu->create = array('link' => ' New|product|create', 'float' => 'right'); -$lang->product->menu->all = array('link' => ' All|product|index|locate=no&productID=%s', 'float' => 'right'); - -$lang->story = new stdclass(); -$lang->productplan = new stdclass(); -$lang->release = new stdclass(); - -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* Project menu. */ -$lang->project = new stdclass(); -$lang->project->menu = new stdclass(); - -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,importbug,burn'); -$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); -$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->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 = array('link' => 'Product|project|manageproducts|projectID=%s', 'alias' => 'edit,start,suspend,delay,close'); -$lang->project->menu->view = 'Manage|project|view|projectID=%s'; -$lang->project->menu->order = 'Order|project|order|projectID=%s'; -$lang->project->menu->create = array('link' => ' New|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => ' Projects|project|index|locate=no&status=all&projectID=%s', 'float' => 'right'); - -$lang->task = new stdclass(); -$lang->build = new stdclass(); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA menu. */ -$lang->bug = new stdclass(); -$lang->bug->menu = new stdclass(); - -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', '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 = new stdclass(); -$lang->testcase->menu = new stdclass(); - -$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,batchedit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -$lang->testtask = new stdclass(); -$lang->testtask->menu = $lang->testcase->menu; - -/* Doc menu. */ -$lang->doc = new stdclass(); -$lang->doc->menu = new stdclass(); - -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s', 'alias' => 'view,create,edit'); -$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'); - -/* Report menu. */ -$lang->report = new stdclass(); -$lang->report->menu = new stdclass(); - -$lang->report->menu->product = array('link' => 'Product|report|productinfo'); -$lang->report->menu->prj = array('link' => 'Project|report|projectdeviation'); -$lang->report->menu->test = array('link' => 'Test|report|bugsummary', 'alias' => 'bugassign'); -$lang->report->menu->staff = array('link' => 'Company|report|workload'); - -/* Resource menu. */ -$lang->webapp = new stdclass(); -$lang->webapp->menu = new stdclass(); -$lang->webapp->menu->obtain = array('link' => 'App Store|webapp|obtain'); - -/* Company menu. */ -$lang->company = new stdclass(); -$lang->company->menu = new stdclass(); -$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->batchAddUser = array('link' => ' Batch Add|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => ' Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right'); - -$lang->dept = new stdclass(); -$lang->group = new stdclass(); -$lang->user = new stdclass(); - -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; -$lang->user->menu = $lang->company->menu; - -/* Admin menu. */ -$lang->admin = new stdclass(); -$lang->admin->menu = new stdclass(); -$lang->admin->menu->index = array('link' => 'Index|admin|index'); -$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension'); -$lang->admin->menu->editor = array('link' => 'Scaffold|editor|index', 'subModule' => 'editor'); -$lang->admin->menu->mail = array('link' => 'Email|mail|index', '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 = new stdclass(); -$lang->upgrade = new stdclass(); -$lang->action = new stdclass(); -$lang->extension = new stdclass(); -$lang->editor = new stdclass(); -$lang->mail = new stdclass(); - -$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 = new stdclass(); -$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 = new stdclass(); -$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. If you are sure this record has been deleted, you can restore it in admin panel, trash page."; -$lang->error->gt = "『%s』must greater than『%s』."; -$lang->error->ge = "『%s』must greater than or equal『%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 = new stdclass(); -$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->proVersion = "Try pro version! "; -$lang->downNotify = "Down notify"; - -$lang->suhosinInfo = "Warming:data is too large! Please enlarge the setting of sohusin.post.max_vars and sohusin.request.max_vars in php.ini. Otherwise partial data can't be saved."; - -$lang->noResultsMatch = "No results match"; - -/* 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'); - -/* datepicker 时间*/ -$lang->datepicker = new stdclass(); - -$lang->datepicker->dpText = new stdclass(); -$lang->datepicker->dpText->TEXT_OR = 'Or '; -$lang->datepicker->dpText->TEXT_PREV_YEAR = 'Last year'; -$lang->datepicker->dpText->TEXT_PREV_MONTH = 'Last month'; -$lang->datepicker->dpText->TEXT_PREV_WEEK = 'Last week'; -$lang->datepicker->dpText->TEXT_YESTERDAY = 'Yesterday'; -$lang->datepicker->dpText->TEXT_THIS_MONTH = 'This month'; -$lang->datepicker->dpText->TEXT_THIS_WEEK = 'This week'; -$lang->datepicker->dpText->TEXT_TODAY = 'Today'; -$lang->datepicker->dpText->TEXT_NEXT_YEAR = 'Next year'; -$lang->datepicker->dpText->TEXT_NEXT_MONTH = 'Next month'; -$lang->datepicker->dpText->TEXT_CLOSE = 'Close'; -$lang->datepicker->dpText->TEXT_DATE = 'Please select date range'; -$lang->datepicker->dpText->TEXT_CHOOSE_DATE = 'Choose date'; - -$lang->datepicker->dayNames = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); -$lang->datepicker->abbrDayNames = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); -$lang->datepicker->monthNames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); - -include (dirname(__FILE__) . '/menuOrder.php'); + + * @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->exportType = 'Exprot Type'; +$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->selectReverse = 'Select Reverse'; +$lang->notFound = 'Sorry, the object not found.'; +$lang->showAll = '++ Show All ++'; +$lang->hideClosed = '-- Show Progressing --'; + +$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 = new stdclass(); +$lang->common->common = 'Common module'; + +/* The main menu. */ +$lang->menu = new stdclass(); +$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->report = 'Report|report|index'; +$lang->menu->webapp = 'Web App|webapp|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(ctrl+g)'; + +/* Encode list of impot. */ +$lang->importEncodeList['gbk'] = 'GBK'; +$lang->importEncodeList['big5'] = 'BIG5'; +$lang->importEncodeList['utf-8'] = 'UTF-8'; + +/* File type of export. */ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +$lang->exportTypeList['all'] = 'Export ALL'; +$lang->exportTypeList['selected'] = 'Export Checked'; + +/* Support charset. */ +$lang->exportEncodeList['gbk'] = 'GBK'; +$lang->exportEncodeList['big5'] = 'BIG5'; +$lang->exportEncodeList['utf-8'] = 'UTF-8'; + +/* Themes. */ +$lang->themes['default'] = 'Default'; +$lang->themes['green'] = 'Green'; +$lang->themes['red'] = 'Red'; +$lang->themes['classblue'] = 'Blue'; + +/* Index mododule menu. */ +$lang->index = new stdclass(); +$lang->index->menu = new stdclass(); + +$lang->index->menu->product = 'Products|product|browse'; +$lang->index->menu->project = 'Projects|project|browse'; + +/* Dashboard menu. */ +$lang->my = new stdclass(); +$lang->my->menu = new stdclass(); + +$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 = array('link' => 'Test|my|testtask|', 'alias' => 'testcase'); +$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->my->menu->changePassword = 'Change Password|my|changepassword|'; + +$lang->todo = new stdclass(); +$lang->todo->menu = $lang->my->menu; + +/* Product menu. */ +$lang->product = new stdclass(); +$lang->product->menu = new stdclass(); + +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => 'Story|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => 'Manage|product|view|productID=%s', 'alias' => 'edit'); +$lang->product->menu->module = 'Modules|tree|browse|productID=%s&view=story'; +$lang->product->menu->project = 'Projects|product|project|status=all&productID=%s'; +$lang->product->menu->order = 'Order|product|order|productID=%s'; +$lang->product->menu->create = array('link' => ' New|product|create', 'float' => 'right'); +$lang->product->menu->all = array('link' => ' All|product|index|locate=no&productID=%s', 'float' => 'right'); + +$lang->story = new stdclass(); +$lang->productplan = new stdclass(); +$lang->release = new stdclass(); + +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* Project menu. */ +$lang->project = new stdclass(); +$lang->project->menu = new stdclass(); + +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => 'Task|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,importbug,burn'); +$lang->project->menu->story = array('link' => 'Story|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); +$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->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 = array('link' => 'Product|project|manageproducts|projectID=%s', 'alias' => 'edit,start,suspend,delay,close'); +$lang->project->menu->view = 'Manage|project|view|projectID=%s'; +$lang->project->menu->order = 'Order|project|order|projectID=%s'; +$lang->project->menu->create = array('link' => ' New|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => ' Projects|project|index|locate=no&status=all&projectID=%s', 'float' => 'right'); + +$lang->task = new stdclass(); +$lang->build = new stdclass(); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA menu. */ +$lang->bug = new stdclass(); +$lang->bug->menu = new stdclass(); + +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', '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 = new stdclass(); +$lang->testcase->menu = new stdclass(); + +$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,batchedit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => 'Test Task|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +$lang->testtask = new stdclass(); +$lang->testtask->menu = $lang->testcase->menu; + +/* Doc menu. */ +$lang->doc = new stdclass(); +$lang->doc->menu = new stdclass(); + +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => 'Doc|doc|browse|libID=%s', 'alias' => 'view,create,edit'); +$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'); + +/* Report menu. */ +$lang->report = new stdclass(); +$lang->report->menu = new stdclass(); + +$lang->report->menu->product = array('link' => 'Product|report|productinfo'); +$lang->report->menu->prj = array('link' => 'Project|report|projectdeviation'); +$lang->report->menu->test = array('link' => 'Test|report|bugsummary', 'alias' => 'bugassign'); +$lang->report->menu->staff = array('link' => 'Company|report|workload'); + +/* Resource menu. */ +$lang->webapp = new stdclass(); +$lang->webapp->menu = new stdclass(); +$lang->webapp->menu->obtain = array('link' => 'App Store|webapp|obtain'); + +/* Company menu. */ +$lang->company = new stdclass(); +$lang->company->menu = new stdclass(); +$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->batchAddUser = array('link' => ' Batch Add|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => ' Add User|user|create|dept=%s&from=company', 'subModule' => 'user', 'float' => 'right'); + +$lang->dept = new stdclass(); +$lang->group = new stdclass(); +$lang->user = new stdclass(); + +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; +$lang->user->menu = $lang->company->menu; + +/* Admin menu. */ +$lang->admin = new stdclass(); +$lang->admin->menu = new stdclass(); +$lang->admin->menu->index = array('link' => 'Index|admin|index'); +$lang->admin->menu->extension = array('link' => 'Extension|extension|browse', 'subModule' => 'extension'); +$lang->admin->menu->editor = array('link' => 'Scaffold|editor|index', 'subModule' => 'editor'); +$lang->admin->menu->mail = array('link' => 'Email|mail|index', '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 = new stdclass(); +$lang->upgrade = new stdclass(); +$lang->action = new stdclass(); +$lang->extension = new stdclass(); +$lang->editor = new stdclass(); +$lang->mail = new stdclass(); + +$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 = new stdclass(); +$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 = new stdclass(); +$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. If you are sure this record has been deleted, you can restore it in admin panel, trash page."; +$lang->error->gt = "『%s』must greater than『%s』."; +$lang->error->ge = "『%s』must greater than or equal『%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 = new stdclass(); +$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->proVersion = "Try pro version! "; +$lang->downNotify = "Down notify"; + +$lang->suhosinInfo = "Warming:data is too large! Please enlarge the setting of sohusin.post.max_vars and sohusin.request.max_vars in php.ini. Otherwise partial data can't be saved."; + +$lang->noResultsMatch = "No results match"; + +/* 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'); + +/* datepicker 时间*/ +$lang->datepicker = new stdclass(); + +$lang->datepicker->dpText = new stdclass(); +$lang->datepicker->dpText->TEXT_OR = 'Or '; +$lang->datepicker->dpText->TEXT_PREV_YEAR = 'Last year'; +$lang->datepicker->dpText->TEXT_PREV_MONTH = 'Last month'; +$lang->datepicker->dpText->TEXT_PREV_WEEK = 'Last week'; +$lang->datepicker->dpText->TEXT_YESTERDAY = 'Yesterday'; +$lang->datepicker->dpText->TEXT_THIS_MONTH = 'This month'; +$lang->datepicker->dpText->TEXT_THIS_WEEK = 'This week'; +$lang->datepicker->dpText->TEXT_TODAY = 'Today'; +$lang->datepicker->dpText->TEXT_NEXT_YEAR = 'Next year'; +$lang->datepicker->dpText->TEXT_NEXT_MONTH = 'Next month'; +$lang->datepicker->dpText->TEXT_CLOSE = 'Close'; +$lang->datepicker->dpText->TEXT_DATE = 'Please select date range'; +$lang->datepicker->dpText->TEXT_CHOOSE_DATE = 'Choose date'; + +$lang->datepicker->dayNames = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); +$lang->datepicker->abbrDayNames = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); +$lang->datepicker->monthNames = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'); + +include (dirname(__FILE__) . '/menuOrder.php'); diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 37474d3c0c..e3ff4a42bd 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -1,395 +1,395 @@ - - * @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->exportType = '导出类型'; -$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->selectReverse = '反选'; -$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 = new stdclass(); -$lang->common->common = '公有模块'; - -/* 主导航菜单。*/ -$lang->menu = new stdclass(); -$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->report = '统计|report|index'; -$lang->menu->webapp = '应用|webapp|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:版本'; -$lang->searchObjects['release'] = 'R:发布'; -$lang->searchObjects['productplan'] = 'P:产品计划'; -$lang->searchObjects['testtask'] = 'T:测试任务'; -$lang->searchObjects['doc'] = 'D:文档'; -$lang->searchTips = '编号(ctrl+g)'; - -/* 导入支持的编码格式。*/ -$lang->importEncodeList['gbk'] = 'GBK'; -$lang->importEncodeList['big5'] = 'BIG5'; -$lang->importEncodeList['utf-8'] = 'UTF-8'; - -/* 导出文件的类型列表。*/ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -$lang->exportTypeList['all'] = '导出全部'; -$lang->exportTypeList['selected'] = '导出选中'; - -/* 支持的编码格式。*/ -$lang->exportEncodeList['gbk'] = 'GBK'; -$lang->exportEncodeList['big5'] = 'BIG5'; -$lang->exportEncodeList['utf-8'] = 'UTF-8'; - -/* 风格列表。*/ -$lang->themes['default'] = '默认'; -$lang->themes['green'] = '绿色'; -$lang->themes['red'] = '红色'; -$lang->themes['classblue'] = '经典蓝'; - -/* 首页菜单设置。*/ -$lang->index = new stdclass(); -$lang->index->menu = new stdclass(); - -$lang->index->menu->product = '浏览产品|product|browse'; -$lang->index->menu->project = '浏览项目|project|browse'; - -/* 我的地盘菜单设置。*/ -$lang->my = new stdclass(); -$lang->my->menu = new stdclass(); - -$lang->my->menu->account = ' %s' . $lang->arrow; -$lang->my->menu->index = '首页|my|index'; -$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo'); -$lang->my->menu->task = '任务|my|task|'; -$lang->my->menu->bug = 'Bug|my|bug|'; -$lang->my->menu->testtask = array('link' => '测试|my|testtask|', 'alias' => 'testcase'); -$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->my->menu->changePassword = '密码|my|changepassword|'; - -$lang->todo = new stdclass(); -$lang->todo->menu = $lang->my->menu; - -/* 产品视图设置。*/ -$lang->product = new stdclass(); -$lang->product->menu = new stdclass(); - -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => '维护|product|view|productID=%s', 'alias' => 'edit'); -$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; -$lang->product->menu->project = '项目|product|project|status=all&productID=%s'; -$lang->product->menu->order = '排序|product|order|productID=%s'; -$lang->product->menu->create = array('link' => ' 添加产品|product|create', 'float' => 'right'); -$lang->product->menu->all = array('link' => ' 所有产品|product|index|locate=no&productID=%s', 'float' => 'right'); - -$lang->story = new stdclass(); -$lang->productplan = new stdclass(); -$lang->release = new stdclass(); - -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* 项目视图菜单设置。*/ -$lang->project = new stdclass(); -$lang->project->menu = new stdclass(); - -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = '测试|project|testtask|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->view = array('link' => '维护|project|view|projectID=%s', 'alias' => 'edit,start,suspend,delay,close'); -$lang->project->menu->order = '排序|project|order|projectID=%s'; -$lang->project->menu->create = array('link' => ' 添加项目|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => ' 所有项目|project|index|locate=no&status=all&projectID=%s', 'float' => 'right'); - -$lang->task = new stdclass(); -$lang->build = new stdclass(); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA视图菜单设置。*/ -$lang->bug = new stdclass(); -$lang->bug->menu = new stdclass(); - -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', '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 = new stdclass(); -$lang->testcase->menu = new stdclass(); - -$lang->testcase->menu->product = '%s'; -$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); -$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -$lang->testtask = new stdclass(); -$lang->testtask->menu = $lang->testcase->menu; - -/* 文档视图菜单设置。*/ -$lang->doc = new stdclass(); -$lang->doc->menu = new stdclass(); - -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => '文档|doc|browse|libID=%s', 'alias' => 'view,create,edit'); -$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->report = new stdclass(); -$lang->report->menu = new stdclass(); - -$lang->report->menu->product = array('link' => '产品|report|productinfo'); -$lang->report->menu->prj = array('link' => '项目|report|projectdeviation'); -$lang->report->menu->test = array('link' => '测试|report|bugsummary', 'alias' => 'bugassign'); -$lang->report->menu->staff = array('link' => '组织|report|workload'); - -/* 资源视图菜单设置。*/ -$lang->webapp = new stdclass(); -$lang->webapp->menu = new stdclass(); -$lang->webapp->menu->obtain = array('link' => '应用商店|webapp|obtain', 'float' => 'right'); - -/* 组织结构视图菜单设置。*/ -$lang->company = new stdclass(); -$lang->company->menu = new stdclass(); -$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->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => ' 添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); - -$lang->dept = new stdclass(); -$lang->group = new stdclass(); -$lang->user = new stdclass(); - -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; -$lang->user->menu = $lang->company->menu; - -/* 后台管理菜单设置。*/ -$lang->admin = new stdclass(); -$lang->admin->menu = new stdclass(); -$lang->admin->menu->index = array('link' => '首页|admin|index'); -$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' => '发信|mail|index', 'subModule' => 'mail'); -$lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert'); -$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); - -$lang->convert = new stdclass(); -$lang->upgrade = new stdclass(); -$lang->action = new stdclass(); -$lang->extension = new stdclass(); -$lang->editor = new stdclass(); -$lang->mail = new stdclass(); - -$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 = new stdclass(); -$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 = new stdclass(); -$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->ge = "『%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 = new stdclass(); -$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->proVersion = "购买专业版(特惠)! "; -$lang->downNotify = "下载桌面提醒"; - -$lang->suhosinInfo = "警告:数据太多,请在php.ini中修改sohusin.post.max_varssohusin.request.max_vars(设置更大的数)。 保存并重新启动apache,否则会造成部分数据无法保存。"; - -$lang->noResultsMatch = "没有匹配结果"; - -/* 时间格式设置。*/ -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'); - -/* datepicker 时间*/ -$lang->datepicker = new stdclass(); - -$lang->datepicker->dpText = new stdclass(); -$lang->datepicker->dpText->TEXT_OR = '或 '; -$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年'; -$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月'; -$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周'; -$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天'; -$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月'; -$lang->datepicker->dpText->TEXT_THIS_WEEK = '本周'; -$lang->datepicker->dpText->TEXT_TODAY = '今天'; -$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年'; -$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月'; -$lang->datepicker->dpText->TEXT_CLOSE = '关闭'; -$lang->datepicker->dpText->TEXT_DATE = '选择时间段'; -$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '选择日期'; - -$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六'); -$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六'); -$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'); - -include (dirname(__FILE__) . '/menuOrder.php'); + + * @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->exportType = '导出类型'; +$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->selectReverse = '反选'; +$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 = new stdclass(); +$lang->common->common = '公有模块'; + +/* 主导航菜单。*/ +$lang->menu = new stdclass(); +$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->report = '统计|report|index'; +$lang->menu->webapp = '应用|webapp|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:版本'; +$lang->searchObjects['release'] = 'R:发布'; +$lang->searchObjects['productplan'] = 'P:产品计划'; +$lang->searchObjects['testtask'] = 'T:测试任务'; +$lang->searchObjects['doc'] = 'D:文档'; +$lang->searchTips = '编号(ctrl+g)'; + +/* 导入支持的编码格式。*/ +$lang->importEncodeList['gbk'] = 'GBK'; +$lang->importEncodeList['big5'] = 'BIG5'; +$lang->importEncodeList['utf-8'] = 'UTF-8'; + +/* 导出文件的类型列表。*/ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +$lang->exportTypeList['all'] = '导出全部'; +$lang->exportTypeList['selected'] = '导出选中'; + +/* 支持的编码格式。*/ +$lang->exportEncodeList['gbk'] = 'GBK'; +$lang->exportEncodeList['big5'] = 'BIG5'; +$lang->exportEncodeList['utf-8'] = 'UTF-8'; + +/* 风格列表。*/ +$lang->themes['default'] = '默认'; +$lang->themes['green'] = '绿色'; +$lang->themes['red'] = '红色'; +$lang->themes['classblue'] = '经典蓝'; + +/* 首页菜单设置。*/ +$lang->index = new stdclass(); +$lang->index->menu = new stdclass(); + +$lang->index->menu->product = '浏览产品|product|browse'; +$lang->index->menu->project = '浏览项目|project|browse'; + +/* 我的地盘菜单设置。*/ +$lang->my = new stdclass(); +$lang->my->menu = new stdclass(); + +$lang->my->menu->account = ' %s' . $lang->arrow; +$lang->my->menu->index = '首页|my|index'; +$lang->my->menu->todo = array('link' => '待办|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->task = '任务|my|task|'; +$lang->my->menu->bug = 'Bug|my|bug|'; +$lang->my->menu->testtask = array('link' => '测试|my|testtask|', 'alias' => 'testcase'); +$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->my->menu->changePassword = '密码|my|changepassword|'; + +$lang->todo = new stdclass(); +$lang->todo->menu = $lang->my->menu; + +/* 产品视图设置。*/ +$lang->product = new stdclass(); +$lang->product->menu = new stdclass(); + +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => '维护|product|view|productID=%s', 'alias' => 'edit'); +$lang->product->menu->module = '模块|tree|browse|productID=%s&view=story'; +$lang->product->menu->project = '项目|product|project|status=all&productID=%s'; +$lang->product->menu->order = '排序|product|order|productID=%s'; +$lang->product->menu->create = array('link' => ' 添加产品|product|create', 'float' => 'right'); +$lang->product->menu->all = array('link' => ' 所有产品|product|index|locate=no&productID=%s', 'float' => 'right'); + +$lang->story = new stdclass(); +$lang->productplan = new stdclass(); +$lang->release = new stdclass(); + +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* 项目视图菜单设置。*/ +$lang->project = new stdclass(); +$lang->project->menu = new stdclass(); + +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => '任务|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '动态|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = '测试|project|testtask|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->view = array('link' => '维护|project|view|projectID=%s', 'alias' => 'edit,start,suspend,delay,close'); +$lang->project->menu->order = '排序|project|order|projectID=%s'; +$lang->project->menu->create = array('link' => ' 添加项目|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => ' 所有项目|project|index|locate=no&status=all&projectID=%s', 'float' => 'right'); + +$lang->task = new stdclass(); +$lang->build = new stdclass(); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA视图菜单设置。*/ +$lang->bug = new stdclass(); +$lang->bug->menu = new stdclass(); + +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => 'Bug|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit,confirmbug,assignto', '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 = new stdclass(); +$lang->testcase->menu = new stdclass(); + +$lang->testcase->menu->product = '%s'; +$lang->testcase->menu->bug = array('link' => 'Bug|bug|browse|productID=%s'); +$lang->testcase->menu->testcase = array('link' => '用例|testcase|browse|productID=%s', 'alias' => 'view,create,batchcreate,edit,batchedit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => '测试任务|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +$lang->testtask = new stdclass(); +$lang->testtask->menu = $lang->testcase->menu; + +/* 文档视图菜单设置。*/ +$lang->doc = new stdclass(); +$lang->doc->menu = new stdclass(); + +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => '文档|doc|browse|libID=%s', 'alias' => 'view,create,edit'); +$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->report = new stdclass(); +$lang->report->menu = new stdclass(); + +$lang->report->menu->product = array('link' => '产品|report|productinfo'); +$lang->report->menu->prj = array('link' => '项目|report|projectdeviation'); +$lang->report->menu->test = array('link' => '测试|report|bugsummary', 'alias' => 'bugassign'); +$lang->report->menu->staff = array('link' => '组织|report|workload'); + +/* 资源视图菜单设置。*/ +$lang->webapp = new stdclass(); +$lang->webapp->menu = new stdclass(); +$lang->webapp->menu->obtain = array('link' => '应用商店|webapp|obtain', 'float' => 'right'); + +/* 组织结构视图菜单设置。*/ +$lang->company = new stdclass(); +$lang->company->menu = new stdclass(); +$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->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => ' 添加用户|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); + +$lang->dept = new stdclass(); +$lang->group = new stdclass(); +$lang->user = new stdclass(); + +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; +$lang->user->menu = $lang->company->menu; + +/* 后台管理菜单设置。*/ +$lang->admin = new stdclass(); +$lang->admin->menu = new stdclass(); +$lang->admin->menu->index = array('link' => '首页|admin|index'); +$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' => '发信|mail|index', 'subModule' => 'mail'); +$lang->admin->menu->convert = array('link' => '导入|convert|index', 'subModule' => 'convert'); +$lang->admin->menu->trashes = array('link' => '回收站|action|trash', 'subModule' => 'action'); + +$lang->convert = new stdclass(); +$lang->upgrade = new stdclass(); +$lang->action = new stdclass(); +$lang->extension = new stdclass(); +$lang->editor = new stdclass(); +$lang->mail = new stdclass(); + +$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 = new stdclass(); +$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 = new stdclass(); +$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->ge = "『%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 = new stdclass(); +$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->proVersion = "购买专业版(特惠)! "; +$lang->downNotify = "下载桌面提醒"; + +$lang->suhosinInfo = "警告:数据太多,请在php.ini中修改sohusin.post.max_varssohusin.request.max_vars(设置更大的数)。 保存并重新启动apache,否则会造成部分数据无法保存。"; + +$lang->noResultsMatch = "没有匹配结果"; + +/* 时间格式设置。*/ +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'); + +/* datepicker 时间*/ +$lang->datepicker = new stdclass(); + +$lang->datepicker->dpText = new stdclass(); +$lang->datepicker->dpText->TEXT_OR = '或 '; +$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年'; +$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月'; +$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周'; +$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天'; +$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月'; +$lang->datepicker->dpText->TEXT_THIS_WEEK = '本周'; +$lang->datepicker->dpText->TEXT_TODAY = '今天'; +$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年'; +$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月'; +$lang->datepicker->dpText->TEXT_CLOSE = '关闭'; +$lang->datepicker->dpText->TEXT_DATE = '选择时间段'; +$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '选择日期'; + +$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六'); +$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六'); +$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'); + +include (dirname(__FILE__) . '/menuOrder.php'); diff --git a/module/common/lang/zh-tw.php b/module/common/lang/zh-tw.php index e18080cfc1..8deed1300f 100644 --- a/module/common/lang/zh-tw.php +++ b/module/common/lang/zh-tw.php @@ -1,396 +1,396 @@ - - * @package ZenTaoPMS - * @version $Id: zh-tw.php 3864 2012-12-20 08:00:07Z wyd621@gmail.com $ - * @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->exportType = '導出類型'; -$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->selectReverse = '反選'; -$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 = new stdclass(); -$lang->common->common = '公有模組'; - -/* 主導航菜單。*/ -$lang->menu = new stdclass(); -$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->report = '統計|report|index'; -//$lang->menu->webapp = '應用中心|webapp|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:版本'; -$lang->searchObjects['release'] = 'R:發佈'; -$lang->searchObjects['productplan'] = 'P:產品計劃'; -$lang->searchObjects['testtask'] = 'T:測試任務'; -$lang->searchObjects['doc'] = 'D:文檔'; -$lang->searchTips = '編號(ctrl+g)'; - -/* 導入支持的編碼格式。*/ -$lang->importEncodeList['gbk'] = 'GBK'; -$lang->importEncodeList['big5'] = 'BIG5'; -$lang->importEncodeList['utf-8'] = 'UTF-8'; - -/* 導出檔案的類型列表。*/ -$lang->exportFileTypeList['csv'] = 'csv'; -$lang->exportFileTypeList['xml'] = 'xml'; -$lang->exportFileTypeList['html'] = 'html'; - -$lang->exportTypeList['all'] = '導出全部'; -$lang->exportTypeList['selected'] = '導出選中'; - -/* 支持的編碼格式。*/ -$lang->exportEncodeList['gbk'] = 'GBK'; -$lang->exportEncodeList['big5'] = 'BIG5'; -$lang->exportEncodeList['utf-8'] = 'UTF-8'; - -/* 風格列表。*/ -$lang->themes['default'] = '預設'; -$lang->themes['green'] = '綠色'; -$lang->themes['red'] = '紅色'; -$lang->themes['classblue'] = '經典藍'; - -/* 首頁菜單設置。*/ -$lang->index = new stdclass(); -$lang->index->menu = new stdclass(); - -$lang->index->menu->product = '瀏覽產品|product|browse'; -$lang->index->menu->project = '瀏覽項目|project|browse'; - -/* 我的地盤菜單設置。*/ -$lang->my = new stdclass(); -$lang->my->menu = new stdclass(); - -$lang->my->menu->account = ' %s' . $lang->arrow; -$lang->my->menu->index = '首頁|my|index'; -$lang->my->menu->todo = array('link' => '待辦|my|todo|', 'subModule' => 'todo'); -$lang->my->menu->task = '任務|my|task|'; -$lang->my->menu->bug = '缺陷|my|bug|'; -$lang->my->menu->testtask = array('link' => '測試|my|testtask|', 'alias' => 'testcase'); -$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->my->menu->changePassword = '密碼|my|changepassword|'; - -$lang->todo = new stdclass(); -$lang->todo->menu = $lang->my->menu; - -/* 產品視圖設置。*/ -$lang->product = new stdclass(); -$lang->product->menu = new stdclass(); - -$lang->product->menu->list = '%s'; -$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => '維護|product|view|productID=%s', 'alias' => 'edit'); -$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; -$lang->product->menu->project = '項目|product|project|status=all&productID=%s'; -$lang->product->menu->order = '排序|product|order|productID=%s'; -$lang->product->menu->create = array('link' => ' 新增產品|product|create', 'float' => 'right'); -$lang->product->menu->all = array('link' => ' 所有產品|product|index|locate=no&productID=%s', 'float' => 'right'); - -$lang->story = new stdclass(); -$lang->productplan = new stdclass(); -$lang->release = new stdclass(); - -$lang->story->menu = $lang->product->menu; -$lang->productplan->menu = $lang->product->menu; -$lang->release->menu = $lang->product->menu; - -/* 項目視圖菜單設置。*/ -$lang->project = new stdclass(); -$lang->project->menu = new stdclass(); - -$lang->project->menu->list = '%s'; -$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug'); -$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); -$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; -$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; -$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); -$lang->project->menu->testtask = '測試|project|testtask|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->view = array('link' => '維護|project|view|projectID=%s', 'alias' => 'edit'); -$lang->project->menu->order = '排序|project|order|projectID=%s'; -$lang->project->menu->create = array('link' => ' 新增項目|project|create', 'float' => 'right'); -$lang->project->menu->all = array('link' => ' 所有項目|project|index|locate=no&status=undone&projectID=%s', 'float' => 'right'); - -$lang->task = new stdclass(); -$lang->build = new stdclass(); -$lang->task->menu = $lang->project->menu; -$lang->build->menu = $lang->project->menu; - -/* QA視圖菜單設置。*/ -$lang->bug = new stdclass(); -$lang->bug->menu = new stdclass(); - -$lang->bug->menu->product = '%s'; -$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit', '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 = new stdclass(); -$lang->testcase->menu = new stdclass(); - -$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,batchedit', 'subModule' => 'tree'); -$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); - -$lang->testtask = new stdclass(); -$lang->testtask->menu = $lang->testcase->menu; - -/* 文檔視圖菜單設置。*/ -$lang->doc = new stdclass(); -$lang->doc->menu = new stdclass(); - -$lang->doc->menu->list = '%s'; -$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s', 'alias' => 'view,create,edit'); -$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->report = new stdclass(); -$lang->report->menu = new stdclass(); - -$lang->report->menu->product = array('link' => '產品|report|productinfo'); -$lang->report->menu->prj = array('link' => '項目|report|projectdeviation'); -$lang->report->menu->test = array('link' => '測試|report|bugsummary', 'alias' => 'bugassign'); -$lang->report->menu->staff = array('link' => '組織|report|workload'); - -/* 資源視圖菜單設置。*/ -$lang->webapp = new stdclass(); -$lang->webapp->menu = new stdclass(); -//$lang->webapp->menu->obtain = array('link' => '應用商店|webapp|obtain', 'float' => 'right'); - -/* 組織結構視圖菜單設置。*/ -$lang->company = new stdclass(); -$lang->company->menu = new stdclass(); -$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->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); -$lang->company->menu->addUser = array('link' => ' 添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); - -$lang->dept = new stdclass(); -$lang->group = new stdclass(); -$lang->user = new stdclass(); - -$lang->dept->menu = $lang->company->menu; -$lang->group->menu = $lang->company->menu; -$lang->user->menu = $lang->company->menu; - -/* 後台管理菜單設置。*/ -$lang->admin = new stdclass(); -$lang->admin->menu = new stdclass(); -$lang->admin->menu->index = array('link' => '首頁|admin|index'); -$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' => '發信|mail|index', 'subModule' => 'mail'); -$lang->admin->menu->clearData = array('link' => '重置|admin|cleardata'); -$lang->admin->menu->convert = array('link' => '導入|convert|index', 'subModule' => 'convert'); -$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action'); - -$lang->convert = new stdclass(); -$lang->upgrade = new stdclass(); -$lang->action = new stdclass(); -$lang->extension = new stdclass(); -$lang->editor = new stdclass(); -$lang->mail = new stdclass(); - -$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 = new stdclass(); -$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 = new stdclass(); -$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->ge = "『%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 = new stdclass(); -$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->proVersion = "購買專業版(特惠)! "; -$lang->downNotify = "下載桌面提醒"; - -$lang->suhosinInfo = "警告:數據太多,請在php.ini中修改sohusin.post.max_varssohusin.request.max_vars(設置更大的數)。 保存並重新啟動apache,否則會造成部分數據無法保存。"; - -$lang->noResultsMatch = "沒有匹配結果"; - -/* 時間格式設置。*/ -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'); - -/* datepicker 時間*/ -$lang->datepicker = new stdclass(); - -$lang->datepicker->dpText = new stdclass(); -$lang->datepicker->dpText->TEXT_OR = '或 '; -$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年'; -$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月'; -$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周'; -$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天'; -$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月'; -$lang->datepicker->dpText->TEXT_THIS_WEEK = '本週'; -$lang->datepicker->dpText->TEXT_TODAY = '今天'; -$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年'; -$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月'; -$lang->datepicker->dpText->TEXT_CLOSE = '關閉'; -$lang->datepicker->dpText->TEXT_DATE = '選擇時間段'; -$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '選擇日期'; - -$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六'); -$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六'); -$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'); - -include (dirname(__FILE__) . '/menuOrder.php'); + + * @package ZenTaoPMS + * @version $Id: zh-tw.php 3864 2012-12-20 08:00:07Z wyd621@gmail.com $ + * @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->exportType = '導出類型'; +$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->selectReverse = '反選'; +$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 = new stdclass(); +$lang->common->common = '公有模組'; + +/* 主導航菜單。*/ +$lang->menu = new stdclass(); +$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->report = '統計|report|index'; +//$lang->menu->webapp = '應用中心|webapp|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:版本'; +$lang->searchObjects['release'] = 'R:發佈'; +$lang->searchObjects['productplan'] = 'P:產品計劃'; +$lang->searchObjects['testtask'] = 'T:測試任務'; +$lang->searchObjects['doc'] = 'D:文檔'; +$lang->searchTips = '編號(ctrl+g)'; + +/* 導入支持的編碼格式。*/ +$lang->importEncodeList['gbk'] = 'GBK'; +$lang->importEncodeList['big5'] = 'BIG5'; +$lang->importEncodeList['utf-8'] = 'UTF-8'; + +/* 導出檔案的類型列表。*/ +$lang->exportFileTypeList['csv'] = 'csv'; +$lang->exportFileTypeList['xml'] = 'xml'; +$lang->exportFileTypeList['html'] = 'html'; + +$lang->exportTypeList['all'] = '導出全部'; +$lang->exportTypeList['selected'] = '導出選中'; + +/* 支持的編碼格式。*/ +$lang->exportEncodeList['gbk'] = 'GBK'; +$lang->exportEncodeList['big5'] = 'BIG5'; +$lang->exportEncodeList['utf-8'] = 'UTF-8'; + +/* 風格列表。*/ +$lang->themes['default'] = '預設'; +$lang->themes['green'] = '綠色'; +$lang->themes['red'] = '紅色'; +$lang->themes['classblue'] = '經典藍'; + +/* 首頁菜單設置。*/ +$lang->index = new stdclass(); +$lang->index->menu = new stdclass(); + +$lang->index->menu->product = '瀏覽產品|product|browse'; +$lang->index->menu->project = '瀏覽項目|project|browse'; + +/* 我的地盤菜單設置。*/ +$lang->my = new stdclass(); +$lang->my->menu = new stdclass(); + +$lang->my->menu->account = ' %s' . $lang->arrow; +$lang->my->menu->index = '首頁|my|index'; +$lang->my->menu->todo = array('link' => '待辦|my|todo|', 'subModule' => 'todo'); +$lang->my->menu->task = '任務|my|task|'; +$lang->my->menu->bug = '缺陷|my|bug|'; +$lang->my->menu->testtask = array('link' => '測試|my|testtask|', 'alias' => 'testcase'); +$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->my->menu->changePassword = '密碼|my|changepassword|'; + +$lang->todo = new stdclass(); +$lang->todo->menu = $lang->my->menu; + +/* 產品視圖設置。*/ +$lang->product = new stdclass(); +$lang->product->menu = new stdclass(); + +$lang->product->menu->list = '%s'; +$lang->product->menu->story = array('link' => '需求|product|browse|productID=%s', 'alias' => 'batchedit', '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 = array('link' => '維護|product|view|productID=%s', 'alias' => 'edit'); +$lang->product->menu->module = '模組|tree|browse|productID=%s&view=story'; +$lang->product->menu->project = '項目|product|project|status=all&productID=%s'; +$lang->product->menu->order = '排序|product|order|productID=%s'; +$lang->product->menu->create = array('link' => ' 新增產品|product|create', 'float' => 'right'); +$lang->product->menu->all = array('link' => ' 所有產品|product|index|locate=no&productID=%s', 'float' => 'right'); + +$lang->story = new stdclass(); +$lang->productplan = new stdclass(); +$lang->release = new stdclass(); + +$lang->story->menu = $lang->product->menu; +$lang->productplan->menu = $lang->product->menu; +$lang->release->menu = $lang->product->menu; + +/* 項目視圖菜單設置。*/ +$lang->project = new stdclass(); +$lang->project->menu = new stdclass(); + +$lang->project->menu->list = '%s'; +$lang->project->menu->task = array('link' => '任務|project|task|projectID=%s', 'subModule' => 'task', 'alias' => 'grouptask,importtask,burn,importbug'); +$lang->project->menu->story = array('link' => '需求|project|story|projectID=%s', 'subModule' => 'story', 'alias' => 'linkstory'); +$lang->project->menu->bug = 'Bug|project|bug|projectID=%s'; +$lang->project->menu->dynamic = '動態|project|dynamic|projectID=%s'; +$lang->project->menu->build = array('link' => '版本|project|build|projectID=%s', 'subModule' => 'build'); +$lang->project->menu->testtask = '測試|project|testtask|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->view = array('link' => '維護|project|view|projectID=%s', 'alias' => 'edit'); +$lang->project->menu->order = '排序|project|order|projectID=%s'; +$lang->project->menu->create = array('link' => ' 新增項目|project|create', 'float' => 'right'); +$lang->project->menu->all = array('link' => ' 所有項目|project|index|locate=no&status=undone&projectID=%s', 'float' => 'right'); + +$lang->task = new stdclass(); +$lang->build = new stdclass(); +$lang->task->menu = $lang->project->menu; +$lang->build->menu = $lang->project->menu; + +/* QA視圖菜單設置。*/ +$lang->bug = new stdclass(); +$lang->bug->menu = new stdclass(); + +$lang->bug->menu->product = '%s'; +$lang->bug->menu->bug = array('link' => '缺陷管理|bug|browse|productID=%s', 'alias' => 'view,create,edit,resolve,close,activate,report,batchedit', '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 = new stdclass(); +$lang->testcase->menu = new stdclass(); + +$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,batchedit', 'subModule' => 'tree'); +$lang->testcase->menu->testtask = array('link' => '測試任務|testtask|browse|productID=%s', 'alias' => 'view,create,edit,linkcase,cases'); + +$lang->testtask = new stdclass(); +$lang->testtask->menu = $lang->testcase->menu; + +/* 文檔視圖菜單設置。*/ +$lang->doc = new stdclass(); +$lang->doc->menu = new stdclass(); + +$lang->doc->menu->list = '%s'; +$lang->doc->menu->browse = array('link' => '文檔列表|doc|browse|libID=%s', 'alias' => 'view,create,edit'); +$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->report = new stdclass(); +$lang->report->menu = new stdclass(); + +$lang->report->menu->product = array('link' => '產品|report|productinfo'); +$lang->report->menu->prj = array('link' => '項目|report|projectdeviation'); +$lang->report->menu->test = array('link' => '測試|report|bugsummary', 'alias' => 'bugassign'); +$lang->report->menu->staff = array('link' => '組織|report|workload'); + +/* 資源視圖菜單設置。*/ +$lang->webapp = new stdclass(); +$lang->webapp->menu = new stdclass(); +//$lang->webapp->menu->obtain = array('link' => '應用商店|webapp|obtain', 'float' => 'right'); + +/* 組織結構視圖菜單設置。*/ +$lang->company = new stdclass(); +$lang->company->menu = new stdclass(); +$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->batchAddUser = array('link' => ' 批量添加|user|batchCreate', 'subModule' => 'user', 'float' => 'right'); +$lang->company->menu->addUser = array('link' => ' 添加用戶|user|create|dept=%s', 'subModule' => 'user', 'float' => 'right'); + +$lang->dept = new stdclass(); +$lang->group = new stdclass(); +$lang->user = new stdclass(); + +$lang->dept->menu = $lang->company->menu; +$lang->group->menu = $lang->company->menu; +$lang->user->menu = $lang->company->menu; + +/* 後台管理菜單設置。*/ +$lang->admin = new stdclass(); +$lang->admin->menu = new stdclass(); +$lang->admin->menu->index = array('link' => '首頁|admin|index'); +$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' => '發信|mail|index', 'subModule' => 'mail'); +$lang->admin->menu->clearData = array('link' => '重置|admin|cleardata'); +$lang->admin->menu->convert = array('link' => '導入|convert|index', 'subModule' => 'convert'); +$lang->admin->menu->trashes = array('link' => '資源回收筒|action|trash', 'subModule' => 'action'); + +$lang->convert = new stdclass(); +$lang->upgrade = new stdclass(); +$lang->action = new stdclass(); +$lang->extension = new stdclass(); +$lang->editor = new stdclass(); +$lang->mail = new stdclass(); + +$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 = new stdclass(); +$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 = new stdclass(); +$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->ge = "『%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 = new stdclass(); +$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->proVersion = "購買專業版(特惠)! "; +$lang->downNotify = "下載桌面提醒"; + +$lang->suhosinInfo = "警告:數據太多,請在php.ini中修改sohusin.post.max_varssohusin.request.max_vars(設置更大的數)。 保存並重新啟動apache,否則會造成部分數據無法保存。"; + +$lang->noResultsMatch = "沒有匹配結果"; + +/* 時間格式設置。*/ +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'); + +/* datepicker 時間*/ +$lang->datepicker = new stdclass(); + +$lang->datepicker->dpText = new stdclass(); +$lang->datepicker->dpText->TEXT_OR = '或 '; +$lang->datepicker->dpText->TEXT_PREV_YEAR = '去年'; +$lang->datepicker->dpText->TEXT_PREV_MONTH = '上月'; +$lang->datepicker->dpText->TEXT_PREV_WEEK = '上周'; +$lang->datepicker->dpText->TEXT_YESTERDAY = '昨天'; +$lang->datepicker->dpText->TEXT_THIS_MONTH = '本月'; +$lang->datepicker->dpText->TEXT_THIS_WEEK = '本週'; +$lang->datepicker->dpText->TEXT_TODAY = '今天'; +$lang->datepicker->dpText->TEXT_NEXT_YEAR = '明年'; +$lang->datepicker->dpText->TEXT_NEXT_MONTH = '下月'; +$lang->datepicker->dpText->TEXT_CLOSE = '關閉'; +$lang->datepicker->dpText->TEXT_DATE = '選擇時間段'; +$lang->datepicker->dpText->TEXT_CHOOSE_DATE = '選擇日期'; + +$lang->datepicker->dayNames = array('日', '一', '二', '三', '四', '五', '六'); +$lang->datepicker->abbrDayNames = array('日', '一', '二', '三', '四', '五', '六'); +$lang->datepicker->monthNames = array('一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'); + +include (dirname(__FILE__) . '/menuOrder.php'); diff --git a/module/common/model.php b/module/common/model.php index 84f902590c..e97ff2b958 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1,620 +1,620 @@ - - * @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->role = 'guest'; - $user->rights = $this->loadModel('user')->authorize('guest'); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - } - } - - /** - * Load configs from database and save it to config->system and config->personal. - * - * @access public - * @return void - */ - public function loadConfigFromDB() - { - /* Get configs of system and current user. */ - $account = isset($this->app->user->account) ? $this->app->user->account : ''; - $config = $this->loadModel('setting')->getSysAndPersonalConfig($account); - $this->config->system = isset($config['system']) ? $config['system'] : array(); - $this->config->personal = isset($config[$account]) ? $config[$account] : array(); - - /* Overide the items defined in config/config.php and config/my.php. */ - if(isset($this->config->system->common)) - { - foreach($this->config->system->common as $record) - { - if($record->section) - { - if(!isset($this->config->{$record->section})) $this->config->{$record->section} = new stdclass(); - $this->config->{$record->section}->{$record->key} = $record->value; - } - else - { - if(!$record->section) $this->config->{$record->key} = $record->value; - } - } - } - } - - /** - * 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($this->loadModel('user')->isLogon()) - { - if(stripos($method, 'ajax') !== false) return true; - if(stripos($method, 'downnotify') !== false) return true; - } - - if($module == 'misc' and $method == 'about') return true; - if($module == 'misc' and $method == 'checkupdate') 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_DATE4)); - if(isset($app->user)) echo $app->user->realname . ' '; - if(isset($app->user) and $app->user->account != 'guest') - { - echo html::a(helper::createLink('user', 'logout'), $lang->logout); - } - else - { - echo html::a(helper::createLink('user', 'login'), $lang->login); - } - - echo ' |  '; - echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'"); - echo $lang->agileTraining; - echo $lang->donate; - - echo ' | '; - echo html::select('', $app->config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"'); - echo html::select('', $app->lang->themes, $app->cookie->theme, 'onchange="selectTheme(this.value)"'); - } - - /** - * 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; - - /* Sort menu according to menuOrder. */ - if(isset($lang->menuOrder)) - { - $menus = $lang->menu; - $lang->menu = new stdclass(); - - ksort($lang->menuOrder, SORT_ASC); - foreach($lang->menuOrder as $key) - { - $menu = $menus->$key; - unset($menus->$key); - $lang->menu->$key = $menu; - } - foreach($menus as $key => $menu) - { - $lang->menu->$key = $menu; - } - } - - /* 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(); - - /* Sort the subMenu according to menuOrder. */ - if(isset($lang->$moduleName->menuOrder)) - { - $menus = $submenus; - $submenus = new stdclass(); - - ksort($lang->$moduleName->menuOrder, SORT_ASC); - if(isset($menus->list)) - { - $submenus->list = $menus->list; - unset($menus->list); - } - foreach($lang->$moduleName->menuOrder as $order) - { - if(($order != 'list') && isset($menus->$order)) - { - $subOrder = $menus->$order; - unset($menus->$order); - $submenus->$order = $subOrder; - } - } - foreach($menus as $key => $menu) - { - $submenus->$key = $menu; - } - } - - /* 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 and $float != 'right') $active = 'active'; - if($module == $currentModule and ($method == $currentMethod or strpos(",$alias,", ",$currentMethod,") !== false) and $float != 'right') $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; - } - } - - /** - * Print the link for notify file. - * - * @static - * @access public - * @return void - */ - public static function printNotifyLink() - { - if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false) - { - global $app, $lang; - $notifyFile = $app->getBasePath() . 'www/data/notify/notify.zip'; - - if(!file_exists($notifyFile)) return false; - echo html::a(helper::createLink('misc', 'downNotify'), $lang->downNotify); - } - } - - /** - * 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); - } - - /** - * Judge Suhosin Setting whether the actual size of post data is large than the setting size. - * - * @param int $numberOfItems - * @param int $columns - * @access public - * @return void - */ - public function judgeSuhosinSetting($numberOfItems, $columns) - { - if(extension_loaded('suhosin')) - { - $maxPostVars = ini_get('suhosin.post.max_vars'); - $maxRequestVars = ini_get('suhosin.request.max_vars'); - if($numberOfItems * $columns > $maxPostVars or $numberOfItems * $columns > $maxRequestVars) return true; - } - - return false; - } - - /** - * Get the previous and next object. - * - * @param string $type story|task|bug|case - * @param string $objectIDs - * @param string $objectID - * @access public - * @return void - */ - public function getPreAndNextObject($type, $objectID) - { - $preAndNextObject = new stdClass(); - - if(strpos('story, task, bug, testcase, doc', $type) === false) return $preAndNextObject; - $table = $this->config->objectTables[$type]; - - $typeIDs = $type . 'IDs'; - if($this->session->$typeIDs and strpos($this->session->$typeIDs, ',' . $objectID . ',') !== false) - { - $objectIDs = $this->session->$typeIDs; - $this->session->set($typeIDs, ''); - } - else - { - /* Get objectIDs. */ - $queryCondition = $type . 'QueryCondition'; - $typeOnlyCondition = $type . 'OnlyCondition'; - $queryCondition = $this->session->$queryCondition; - $orderBy = $type . 'OrderBy'; - $orderBy = $this->session->$orderBy; - $orderBy = str_replace('`left`', 'left', $orderBy); // process the `left` to left. - - if(empty($queryCondition) or $this->session->$typeOnlyCondition) - { - $objects = $this->dao->select('*')->from($table) - ->beginIF($queryCondition != false)->where($queryCondition)->fi() - ->beginIF($orderBy != false)->orderBy($orderBy)->fi() - ->fetchAll(); - } - else - { - $objects = $this->dbh->query($queryCondition . " ORDER BY $orderBy")->fetchAll(); - } - - $tmpObjectIDs = array(); - foreach($objects as $object) $tmpObjectIDs[$object->id] = (!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) ? $object->case : $object->id; - $objectIDs = ',' . implode(',', $tmpObjectIDs) . ','; - $this->session->set($type . 'IDs', $objectIDs); - } - - /* Current object. */ - $currentStart = strpos($objectIDs, ',' . $objectID . ',') + 1; - $currentEnd = $currentStart + strlen($objectID) - 1; - - /* Get the previous object. */ - $tmp = substr($objectIDs, 0, $currentStart - 1); - $preStart = strrpos($tmp, ',', 0) + 1; - $preEnd = $currentStart - 2; - if($preEnd - $preStart < 0) - { - $preAndNextObject->pre = ''; - } - else - { - $preID = substr($objectIDs, $preStart, $preEnd - $preStart + 1); - $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preID)->fetch(); - } - - /* Get the next object. */ - $nextStart = $currentEnd + 2; - $nextEnd = strlen($objectIDs) > $nextStart ? strpos($objectIDs, ',', $nextStart) - 1 : 0; - if($nextEnd - $nextStart < 0) - { - $preAndNextObject->next = ''; - } - else - { - $nextID = substr($objectIDs, $nextStart, $nextEnd - $nextStart + 1); - $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($nextID)->fetch(); - } - - return $preAndNextObject; - } - - /** - * Save one executed query. - * - * @param string $sql - * @param string $objectType story|task|bug|testcase - * @access public - * @return void - */ - public function saveQueryCondition($sql, $objectType, $onlyCondition = true) - { - /* Set the query condition session. */ - if($onlyCondition) - { - $queryCondition = explode('WHERE', $sql); - $queryCondition = explode('ORDER', $queryCondition[1]); - $queryCondition = str_replace('t1.', '', $queryCondition[0]); - } - else - { - $queryCondition = explode('ORDER', $sql); - $queryCondition = $queryCondition[0]; - } - - $this->session->set($objectType . 'QueryCondition', $queryCondition); - $this->session->set($objectType . 'OnlyCondition', $onlyCondition); - - /* Set the query condition session. */ - $orderBy = explode('ORDER BY', $sql); - if(isset($orderBy[1])) - { - $orderBy = explode('limit', $orderBy[1]); - $orderBy = str_replace('t1.', '', $orderBy[0]); - $this->session->set($objectType . 'OrderBy', $orderBy); - } - else - { - $this->session->set($objectType . 'OrderBy', ''); - } - } -} + + * @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->role = 'guest'; + $user->rights = $this->loadModel('user')->authorize('guest'); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + } + } + + /** + * Load configs from database and save it to config->system and config->personal. + * + * @access public + * @return void + */ + public function loadConfigFromDB() + { + /* Get configs of system and current user. */ + $account = isset($this->app->user->account) ? $this->app->user->account : ''; + $config = $this->loadModel('setting')->getSysAndPersonalConfig($account); + $this->config->system = isset($config['system']) ? $config['system'] : array(); + $this->config->personal = isset($config[$account]) ? $config[$account] : array(); + + /* Overide the items defined in config/config.php and config/my.php. */ + if(isset($this->config->system->common)) + { + foreach($this->config->system->common as $record) + { + if($record->section) + { + if(!isset($this->config->{$record->section})) $this->config->{$record->section} = new stdclass(); + $this->config->{$record->section}->{$record->key} = $record->value; + } + else + { + if(!$record->section) $this->config->{$record->key} = $record->value; + } + } + } + } + + /** + * 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($this->loadModel('user')->isLogon()) + { + if(stripos($method, 'ajax') !== false) return true; + if(stripos($method, 'downnotify') !== false) return true; + } + + if($module == 'misc' and $method == 'about') return true; + if($module == 'misc' and $method == 'checkupdate') 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_DATE4)); + if(isset($app->user)) echo $app->user->realname . ' '; + if(isset($app->user) and $app->user->account != 'guest') + { + echo html::a(helper::createLink('user', 'logout'), $lang->logout); + } + else + { + echo html::a(helper::createLink('user', 'login'), $lang->login); + } + + echo ' |  '; + echo html::a(helper::createLink('misc', 'about'), $lang->aboutZenTao, '', "class='about'"); + echo $lang->agileTraining; + echo $lang->donate; + + echo ' | '; + echo html::select('', $app->config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"'); + echo html::select('', $app->lang->themes, $app->cookie->theme, 'onchange="selectTheme(this.value)"'); + } + + /** + * 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; + + /* Sort menu according to menuOrder. */ + if(isset($lang->menuOrder)) + { + $menus = $lang->menu; + $lang->menu = new stdclass(); + + ksort($lang->menuOrder, SORT_ASC); + foreach($lang->menuOrder as $key) + { + $menu = $menus->$key; + unset($menus->$key); + $lang->menu->$key = $menu; + } + foreach($menus as $key => $menu) + { + $lang->menu->$key = $menu; + } + } + + /* 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(); + + /* Sort the subMenu according to menuOrder. */ + if(isset($lang->$moduleName->menuOrder)) + { + $menus = $submenus; + $submenus = new stdclass(); + + ksort($lang->$moduleName->menuOrder, SORT_ASC); + if(isset($menus->list)) + { + $submenus->list = $menus->list; + unset($menus->list); + } + foreach($lang->$moduleName->menuOrder as $order) + { + if(($order != 'list') && isset($menus->$order)) + { + $subOrder = $menus->$order; + unset($menus->$order); + $submenus->$order = $subOrder; + } + } + foreach($menus as $key => $menu) + { + $submenus->$key = $menu; + } + } + + /* 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 and $float != 'right') $active = 'active'; + if($module == $currentModule and ($method == $currentMethod or strpos(",$alias,", ",$currentMethod,") !== false) and $float != 'right') $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; + } + } + + /** + * Print the link for notify file. + * + * @static + * @access public + * @return void + */ + public static function printNotifyLink() + { + if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false) + { + global $app, $lang; + $notifyFile = $app->getBasePath() . 'www/data/notify/notify.zip'; + + if(!file_exists($notifyFile)) return false; + echo html::a(helper::createLink('misc', 'downNotify'), $lang->downNotify); + } + } + + /** + * 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); + } + + /** + * Judge Suhosin Setting whether the actual size of post data is large than the setting size. + * + * @param int $numberOfItems + * @param int $columns + * @access public + * @return void + */ + public function judgeSuhosinSetting($numberOfItems, $columns) + { + if(extension_loaded('suhosin')) + { + $maxPostVars = ini_get('suhosin.post.max_vars'); + $maxRequestVars = ini_get('suhosin.request.max_vars'); + if($numberOfItems * $columns > $maxPostVars or $numberOfItems * $columns > $maxRequestVars) return true; + } + + return false; + } + + /** + * Get the previous and next object. + * + * @param string $type story|task|bug|case + * @param string $objectIDs + * @param string $objectID + * @access public + * @return void + */ + public function getPreAndNextObject($type, $objectID) + { + $preAndNextObject = new stdClass(); + + if(strpos('story, task, bug, testcase, doc', $type) === false) return $preAndNextObject; + $table = $this->config->objectTables[$type]; + + $typeIDs = $type . 'IDs'; + if($this->session->$typeIDs and strpos($this->session->$typeIDs, ',' . $objectID . ',') !== false) + { + $objectIDs = $this->session->$typeIDs; + $this->session->set($typeIDs, ''); + } + else + { + /* Get objectIDs. */ + $queryCondition = $type . 'QueryCondition'; + $typeOnlyCondition = $type . 'OnlyCondition'; + $queryCondition = $this->session->$queryCondition; + $orderBy = $type . 'OrderBy'; + $orderBy = $this->session->$orderBy; + $orderBy = str_replace('`left`', 'left', $orderBy); // process the `left` to left. + + if(empty($queryCondition) or $this->session->$typeOnlyCondition) + { + $objects = $this->dao->select('*')->from($table) + ->beginIF($queryCondition != false)->where($queryCondition)->fi() + ->beginIF($orderBy != false)->orderBy($orderBy)->fi() + ->fetchAll(); + } + else + { + $objects = $this->dbh->query($queryCondition . " ORDER BY $orderBy")->fetchAll(); + } + + $tmpObjectIDs = array(); + foreach($objects as $object) $tmpObjectIDs[$object->id] = (!$this->session->$typeOnlyCondition and $type == 'testcase' and isset($object->case)) ? $object->case : $object->id; + $objectIDs = ',' . implode(',', $tmpObjectIDs) . ','; + $this->session->set($type . 'IDs', $objectIDs); + } + + /* Current object. */ + $currentStart = strpos($objectIDs, ',' . $objectID . ',') + 1; + $currentEnd = $currentStart + strlen($objectID) - 1; + + /* Get the previous object. */ + $tmp = substr($objectIDs, 0, $currentStart - 1); + $preStart = strrpos($tmp, ',', 0) + 1; + $preEnd = $currentStart - 2; + if($preEnd - $preStart < 0) + { + $preAndNextObject->pre = ''; + } + else + { + $preID = substr($objectIDs, $preStart, $preEnd - $preStart + 1); + $preAndNextObject->pre = $this->dao->select('*')->from($table)->where('id')->eq($preID)->fetch(); + } + + /* Get the next object. */ + $nextStart = $currentEnd + 2; + $nextEnd = strlen($objectIDs) > $nextStart ? strpos($objectIDs, ',', $nextStart) - 1 : 0; + if($nextEnd - $nextStart < 0) + { + $preAndNextObject->next = ''; + } + else + { + $nextID = substr($objectIDs, $nextStart, $nextEnd - $nextStart + 1); + $preAndNextObject->next = $this->dao->select('*')->from($table)->where('id')->eq($nextID)->fetch(); + } + + return $preAndNextObject; + } + + /** + * Save one executed query. + * + * @param string $sql + * @param string $objectType story|task|bug|testcase + * @access public + * @return void + */ + public function saveQueryCondition($sql, $objectType, $onlyCondition = true) + { + /* Set the query condition session. */ + if($onlyCondition) + { + $queryCondition = explode('WHERE', $sql); + $queryCondition = explode('ORDER', $queryCondition[1]); + $queryCondition = str_replace('t1.', '', $queryCondition[0]); + } + else + { + $queryCondition = explode('ORDER', $sql); + $queryCondition = $queryCondition[0]; + } + + $this->session->set($objectType . 'QueryCondition', $queryCondition); + $this->session->set($objectType . 'OnlyCondition', $onlyCondition); + + /* Set the query condition session. */ + $orderBy = explode('ORDER BY', $sql); + if(isset($orderBy[1])) + { + $orderBy = explode('limit', $orderBy[1]); + $orderBy = str_replace('t1.', '', $orderBy[0]); + $this->session->set($objectType . 'OrderBy', $orderBy); + } + else + { + $this->session->set($objectType . 'OrderBy', ''); + } + } +} diff --git a/module/company/control.php b/module/company/control.php index 1a87a91b2e..91f580d589 100644 --- a/module/company/control.php +++ b/module/company/control.php @@ -1,280 +1,280 @@ - - * @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->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($param = 0, $type = 'bydept', $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->loadModel('search'); - $this->lang->set('menugroup.company', 'company'); - - $deptID = $type == 'bydept' ? (int)$param : 0; - $this->company->setMenu($deptID); - - /* Set the pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* Build the search form. */ - $queryID = $type == 'bydept' ? 0 : (int)$param; - $this->config->company->browse->search['actionURL'] = $this->createLink('company', 'browse', "param=myQueryID&type=bysearch"); - $this->config->company->browse->search['queryID'] = $queryID; - $this->config->company->browse->search['params']['dept']['values'] = array('' => '') + $this->dept->getOptionMenu(); - - $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common; - $position[] = $this->lang->dept->common; - - if($type == 'bydept') - { - $childDeptIds = $this->dept->getAllChildID($deptID); - $users = $this->dept->getUsers($childDeptIds, $pager, $orderBy); - } - else - { - if($queryID) - { - $query = $this->search->getQuery($queryID); - if($query) - { - $this->session->set('userQuery', $query->sql); - $this->session->set('userForm', $query->form); - } - else - { - $this->session->set('userQuery', ' 1 = 1'); - } - } - $users = $this->loadModel('user')->getByQuery($this->session->userQuery, $pager, $orderBy); - } - - $this->view->header = $header; - $this->view->position = $position; - $this->view->users = $users; - $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->browse->search); - $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink')); - $this->view->parentDepts = $this->dept->getParents($deptID); - $this->view->orderBy = $orderBy; - $this->view->deptID = $deptID; - $this->view->pager = $pager; - $this->view->param = $param; - $this->view->type = $type; - - $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; - $this->lang->company->menuOrder = $this->lang->admin->menuOrder; - - $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())); - - /* reset company in session. */ - $company = $this->loadModel('company')->getByDomain(); - $this->session->set('company', $company); - - 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|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->loadModel('search')->setSearchParams($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->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($param = 0, $type = 'bydept', $orderBy = 'id', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->loadModel('search'); + $this->lang->set('menugroup.company', 'company'); + + $deptID = $type == 'bydept' ? (int)$param : 0; + $this->company->setMenu($deptID); + + /* Set the pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* Build the search form. */ + $queryID = $type == 'bydept' ? 0 : (int)$param; + $this->config->company->browse->search['actionURL'] = $this->createLink('company', 'browse', "param=myQueryID&type=bysearch"); + $this->config->company->browse->search['queryID'] = $queryID; + $this->config->company->browse->search['params']['dept']['values'] = array('' => '') + $this->dept->getOptionMenu(); + + $header['title'] = $this->lang->company->index . $this->lang->colon . $this->lang->dept->common; + $position[] = $this->lang->dept->common; + + if($type == 'bydept') + { + $childDeptIds = $this->dept->getAllChildID($deptID); + $users = $this->dept->getUsers($childDeptIds, $pager, $orderBy); + } + else + { + if($queryID) + { + $query = $this->search->getQuery($queryID); + if($query) + { + $this->session->set('userQuery', $query->sql); + $this->session->set('userForm', $query->form); + } + else + { + $this->session->set('userQuery', ' 1 = 1'); + } + } + $users = $this->loadModel('user')->getByQuery($this->session->userQuery, $pager, $orderBy); + } + + $this->view->header = $header; + $this->view->position = $position; + $this->view->users = $users; + $this->view->searchForm = $this->fetch('search', 'buildForm', $this->config->company->browse->search); + $this->view->deptTree = $this->dept->getTreeMenu($rooteDeptID = 0, array('deptModel', 'createMemberLink')); + $this->view->parentDepts = $this->dept->getParents($deptID); + $this->view->orderBy = $orderBy; + $this->view->deptID = $deptID; + $this->view->pager = $pager; + $this->view->param = $param; + $this->view->type = $type; + + $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; + $this->lang->company->menuOrder = $this->lang->admin->menuOrder; + + $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())); + + /* reset company in session. */ + $company = $this->loadModel('company')->getByDomain(); + $this->session->set('company', $company); + + 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|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->loadModel('search')->setSearchParams($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 667deabd55..21fcc0c3d7 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 40bc8e8001..f5b2621ba0 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 07cce8067a..ef8b8a4c09 100644 --- a/module/company/lang/zh-tw.php +++ b/module/company/lang/zh-tw.php @@ -1,40 +1,40 @@ - - * @package company - * @version $Id: zh-tw.php 3536 2012-09-21 03:09:38Z zhujinyonging@gmail.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->unlock = '解鎖'; - -$lang->company->guestList[0] = '不允許'; -$lang->company->guestList[1] = '允許'; + + * @package company + * @version $Id: zh-tw.php 3536 2012-09-21 03:09:38Z zhujinyonging@gmail.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->unlock = '解鎖'; + +$lang->company->guestList[0] = '不允許'; +$lang->company->guestList[1] = '允許'; diff --git a/module/company/model.php b/module/company/model.php index c7a0df4d20..0b285a9094 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 bc11e58240..9136945e65 100644 --- a/module/company/view/browse.html.php +++ b/module/company/view/browse.html.php @@ -1,92 +1,92 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
      -
      dept->common;?>
      -
      - -
      dept->manage);?>
      -
      -
      - - - - recTotal}&recPerPage={$pager->recPerPage}";?> - - - - - - - - - - - - - - - ' method='post' id='userListForm'> - - - - - - - - - - - - - - - - - - - - - -
      idAB);?>user->realname);?>user->account);?>user->role);?>user->email);?>user->gender);?>user->phone);?>user->join);?>user->last);?>user->visits);?>actions;?>
      account'> "; printf('%03d', $user->id);?>account", $user->realname)) echo $user->realname;?>account;?>user->roleList[$user->role];?>email);?>user->genderList[$user->gender])) echo $lang->user->genderList[$user->gender];?>phone;?>join;?>last);?>visits;?> - id&from=company", '', 'list'); - common::printIcon('user', 'delete', "userID=$user->id", '', 'list', '', "hiddenwin"); - if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) < $this->config->user->lockMinutes * 60) - { - common::printIcon('user', 'unlock', "userID=$user->account", '', 'list', '', "hiddenwin"); - } - ?> -
      - user->batchEdit, 'onclick=batchEdit()'); - echo html::submitButton($lang->user->contacts->manage, 'onclick=manageContacts()'); - $pager->show(); - ?> -
      -
      - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
      +
      dept->common;?>
      +
      + +
      dept->manage);?>
      +
      +
      + + + + recTotal}&recPerPage={$pager->recPerPage}";?> + + + + + + + + + + + + + + + ' method='post' id='userListForm'> + + + + + + + + + + + + + + + + + + + + + +
      idAB);?>user->realname);?>user->account);?>user->role);?>user->email);?>user->gender);?>user->phone);?>user->join);?>user->last);?>user->visits);?>actions;?>
      account'> "; printf('%03d', $user->id);?>account", $user->realname)) echo $user->realname;?>account;?>user->roleList[$user->role];?>email);?>user->genderList[$user->gender])) echo $lang->user->genderList[$user->gender];?>phone;?>join;?>last);?>visits;?> + id&from=company", '', 'list'); + common::printIcon('user', 'delete', "userID=$user->id", '', 'list', '', "hiddenwin"); + if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) < $this->config->user->lockMinutes * 60) + { + common::printIcon('user', 'unlock', "userID=$user->account", '', 'list', '', "hiddenwin"); + } + ?> +
      + user->batchEdit, 'onclick=batchEdit()'); + echo html::submitButton($lang->user->contacts->manage, 'onclick=manageContacts()'); + $pager->show(); + ?> +
      +
      + + diff --git a/module/company/view/create.html.php b/module/company/view/create.html.php index dd5fa42dd1..a6621f3e9b 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 77404a24f3..9cf4eaaf86 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-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]) ? $users[$action->actor] : $action->actor, 2);?>actionLabel;?>action->objectTypes[$action->objectType];?>objectID;?>objectLink, $action->objectName);?>
      show();?>
      - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2013 青岛易软天创网络科技有限公司 (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]) ? $users[$action->actor] : $action->actor, 2);?>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 d55865af17..320abe51e3 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 f2194a82f3..9425e893ba 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 e829fc4e80..f722f51a76 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 2e60b09fab..536f36bc35 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 acac3ab1c1..00abb21e44 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 50c1b0207a..00b4dffe68 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 87fec9d407..16bc68060e 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 2ec3c9e055..29faed68a4 100644 --- a/module/convert/lang/en.php +++ b/module/convert/lang/en.php @@ -1,124 +1,124 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->convert->common = 'Import'; -$lang->convert->index = 'Index'; -$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->setConfig = 'Source config'; -$lang->convert->setBugfree = 'Bugfree config'; -$lang->convert->setRedmine = 'Redmine config'; -$lang->convert->checkBugFree = 'Check Bugfree'; -$lang->convert->checkRedmine = 'Check Redmine'; -$lang->convert->convertRedmine = 'Convert Redmine'; -$lang->convert->convertBugFree = 'Convert BugFree'; - -$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 = new stdclass(); -$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 = new stdclass(); -$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->statusType = new stdclass(); -$lang->convert->priType = new stdclass(); - -$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 = new stdclass(); -$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->index = 'Index'; +$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->setConfig = 'Source config'; +$lang->convert->setBugfree = 'Bugfree config'; +$lang->convert->setRedmine = 'Redmine config'; +$lang->convert->checkBugFree = 'Check Bugfree'; +$lang->convert->checkRedmine = 'Check Redmine'; +$lang->convert->convertRedmine = 'Convert Redmine'; +$lang->convert->convertBugFree = 'Convert BugFree'; + +$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 = new stdclass(); +$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 = new stdclass(); +$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->statusType = new stdclass(); +$lang->convert->priType = new stdclass(); + +$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 = new stdclass(); +$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 cb5a2f7120..8c3311d6b7 100644 --- a/module/convert/lang/zh-cn.php +++ b/module/convert/lang/zh-cn.php @@ -1,124 +1,124 @@ - - * @package convert - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->convert->common = '从其他系统导入'; -$lang->convert->index = '首页'; -$lang->convert->next = '下一步'; -$lang->convert->pre = '返回'; -$lang->convert->reload = '刷新'; -$lang->convert->error = '错误 '; - -$lang->convert->start = '开始转换'; -$lang->convert->desc = <<欢迎使用系统转换向导,本程序会帮助您将其他系统的数据转换到禅道项目管理系统中。

      -转换存在一定的风险,转换之前,我们强烈建议您备份数据库及相应的数据文件,并保证转换的时候,没有其他人进行操作。 -EOT; - -$lang->convert->setConfig = '来源系统配置'; -$lang->convert->setBugfree = 'Bugfree配置'; -$lang->convert->setRedmine = 'Redmine配置'; -$lang->convert->checkBugFree = '检查Bugfree'; -$lang->convert->checkRedmine = '检查Redmine'; -$lang->convert->convertRedmine = '转换Redmine'; -$lang->convert->convertBugFree = '转换BugFree'; - -$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 = new stdclass(); -$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 = new stdclass(); -$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->statusType = new stdclass(); -$lang->convert->priType = new stdclass(); - -$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 = new stdclass(); -$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->index = '首页'; +$lang->convert->next = '下一步'; +$lang->convert->pre = '返回'; +$lang->convert->reload = '刷新'; +$lang->convert->error = '错误 '; + +$lang->convert->start = '开始转换'; +$lang->convert->desc = <<欢迎使用系统转换向导,本程序会帮助您将其他系统的数据转换到禅道项目管理系统中。

      +转换存在一定的风险,转换之前,我们强烈建议您备份数据库及相应的数据文件,并保证转换的时候,没有其他人进行操作。 +EOT; + +$lang->convert->setConfig = '来源系统配置'; +$lang->convert->setBugfree = 'Bugfree配置'; +$lang->convert->setRedmine = 'Redmine配置'; +$lang->convert->checkBugFree = '检查Bugfree'; +$lang->convert->checkRedmine = '检查Redmine'; +$lang->convert->convertRedmine = '转换Redmine'; +$lang->convert->convertBugFree = '转换BugFree'; + +$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 = new stdclass(); +$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 = new stdclass(); +$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->statusType = new stdclass(); +$lang->convert->priType = new stdclass(); + +$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 = new stdclass(); +$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 4c53536b96..cbd5309985 100644 --- a/module/convert/lang/zh-tw.php +++ b/module/convert/lang/zh-tw.php @@ -1,124 +1,124 @@ - - * @package convert - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @link http://www.zentao.net - */ -$lang->convert->common = '從其他系統導入'; -$lang->convert->index = '首頁'; -$lang->convert->next = '下一步'; -$lang->convert->pre = '返回'; -$lang->convert->reload = '刷新'; -$lang->convert->error = '錯誤 '; - -$lang->convert->start = '開始轉換'; -$lang->convert->desc = <<歡迎使用系統轉換嚮導,本程序會幫助您將其他系統的數據轉換到禪道項目管理系統中。

      -轉換存在一定的風險,轉換之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證轉換的時候,沒有其他人進行操作。 -EOT; - -$lang->convert->setConfig = '來源系統配置'; -$lang->convert->setBugfree = 'Bugfree配置'; -$lang->convert->setRedmine = 'Redmine配置'; -$lang->convert->checkBugFree = '檢查Bugfree'; -$lang->convert->checkRedmine = '檢查Redmine'; -$lang->convert->convertRedmine = '轉換Redmine'; -$lang->convert->convertBugFree = '轉換BugFree'; - -$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 = new stdclass(); -$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 = new stdclass(); -$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->statusType = new stdclass(); -$lang->convert->priType = new stdclass(); - -$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 = new stdclass(); -$lang->convert->issue->redmine = 'Redmine'; -$lang->convert->issue->zentao = '禪道'; -$lang->convert->issue->goto = '轉換為'; + + * @package convert + * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ + * @link http://www.zentao.net + */ +$lang->convert->common = '從其他系統導入'; +$lang->convert->index = '首頁'; +$lang->convert->next = '下一步'; +$lang->convert->pre = '返回'; +$lang->convert->reload = '刷新'; +$lang->convert->error = '錯誤 '; + +$lang->convert->start = '開始轉換'; +$lang->convert->desc = <<歡迎使用系統轉換嚮導,本程序會幫助您將其他系統的數據轉換到禪道項目管理系統中。

      +轉換存在一定的風險,轉換之前,我們強烈建議您備份資料庫及相應的數據檔案,並保證轉換的時候,沒有其他人進行操作。 +EOT; + +$lang->convert->setConfig = '來源系統配置'; +$lang->convert->setBugfree = 'Bugfree配置'; +$lang->convert->setRedmine = 'Redmine配置'; +$lang->convert->checkBugFree = '檢查Bugfree'; +$lang->convert->checkRedmine = '檢查Redmine'; +$lang->convert->convertRedmine = '轉換Redmine'; +$lang->convert->convertBugFree = '轉換BugFree'; + +$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 = new stdclass(); +$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 = new stdclass(); +$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->statusType = new stdclass(); +$lang->convert->priType = new stdclass(); + +$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 = new stdclass(); +$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 507c41841f..b87e7b8c8a 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 f9ffd9d97f..4372cc555a 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 6667ec2f3a..82989395e3 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 f1743268bd..5503d7b828 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 8a3a1bab7d..0390560278 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 f2b4621078..8c720cfa29 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 57576e9d69..31d8e608f2 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 = 10; - - /** - * 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($rootDeptID = 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 = 10; + + /** + * 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($rootDeptID = 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 00d716d8b6..61376a8e85 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 b5e808f4e4..349f875d0d 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 cff26d52b7..b7940d56e5 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 2605 2012-02-21 07:22:58Z wwccss $ - * @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 2605 2012-02-21 07:22:58Z wwccss $ + * @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 c71aea8280..c82c18fb01 100644 --- a/module/dept/model.php +++ b/module/dept/model.php @@ -1,308 +1,308 @@ - - * @package dept - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findById($deptID)->from(TABLE_DEPT)->fetch(); - } - - /** - * Build the query. - * - * @param int $rootDeptID - * @access public - * @return string - */ - public function buildMenuQuery($rootDeptID) - { - $rootDept = $this->getByID($rootDeptID); - if(!$rootDept) - { - $rootDept = new stdclass(); - $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, $pager = null, $orderBy = 'id') - { - return $this->dao->select('*')->from(TABLE_USER) - ->where('deleted')->eq(0) - ->beginIF($deptID)->andWhere('dept')->in($deptID)->fi() - ->orderBy($orderBy) - ->page($pager) - ->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 public + * @return string + */ + public function buildMenuQuery($rootDeptID) + { + $rootDept = $this->getByID($rootDeptID); + if(!$rootDept) + { + $rootDept = new stdclass(); + $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, $pager = null, $orderBy = 'id') + { + return $this->dao->select('*')->from(TABLE_USER) + ->where('deleted')->eq(0) + ->beginIF($deptID)->andWhere('dept')->in($deptID)->fi() + ->orderBy($orderBy) + ->page($pager) + ->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 ad08d47328..c0911ebb88 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 f53ab06ba4..13f54ee054 100644 --- a/module/doc/control.php +++ b/module/doc/control.php @@ -1,425 +1,425 @@ - - * @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. - $docQuery = $this->loadModel('search')->replaceDynamic($docQuery); - $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']; - $this->loadModel('search')->setSearchParams($this->config->doc->search); - - /* 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->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->lang->doc->menuOrder = $this->lang->product->menuOrder; - $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->lang->doc->menuOrder = $this->lang->project->menuOrder; - $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, true); - 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 = "DOC #$doc->id $doc->title - " . $this->libs[$doc->lib]; - $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,noletter'); - $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('doc', $docID); - $this->view->keTableCSS = $this->doc->extractKETableCSS($doc->content); - - $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. + $docQuery = $this->loadModel('search')->replaceDynamic($docQuery); + $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']; + $this->loadModel('search')->setSearchParams($this->config->doc->search); + + /* 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->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->lang->doc->menuOrder = $this->lang->product->menuOrder; + $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->lang->doc->menuOrder = $this->lang->project->menuOrder; + $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, true); + 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 = "DOC #$doc->id $doc->title - " . $this->libs[$doc->lib]; + $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,noletter'); + $this->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('doc', $docID); + $this->view->keTableCSS = $this->doc->extractKETableCSS($doc->content); + + $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 2a73a77090..ff9d677e16 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -1,71 +1,71 @@ - - * @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->basicInfo = 'Basic Info'; - -$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->manageType = 'Manage type'; - -$lang->doc->libName = 'Library name'; -$lang->doc->createLib = 'Create library'; -$lang->doc->editLib = 'Edit library'; -$lang->doc->deleteLib = 'Delete library'; - -/* 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"; - -$lang->doc->placeholder = new stdclass(); -$lang->doc->placeholder->url = 'url'; + + * @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->basicInfo = 'Basic Info'; + +$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->manageType = 'Manage type'; + +$lang->doc->libName = 'Library name'; +$lang->doc->createLib = 'Create library'; +$lang->doc->editLib = 'Edit library'; +$lang->doc->deleteLib = 'Delete library'; + +/* 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"; + +$lang->doc->placeholder = new stdclass(); +$lang->doc->placeholder->url = 'url'; diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index 4a51bcd68b..1d98a092b2 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -1,71 +1,71 @@ - - * @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->basicInfo = '基本信息'; - -$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->manageType = '维护分类'; - -$lang->doc->libName = '文档库名称'; -$lang->doc->createLib = '创建文档库'; -$lang->doc->editLib = '编辑文档库'; -$lang->doc->deleteLib = '删除文档库'; - -/* 查询条件列表 */ -$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 = "系统文档库无需修改。"; - -$lang->doc->placeholder = new stdclass(); -$lang->doc->placeholder->url = '相应的链接地址'; + + * @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->basicInfo = '基本信息'; + +$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->manageType = '维护分类'; + +$lang->doc->libName = '文档库名称'; +$lang->doc->createLib = '创建文档库'; +$lang->doc->editLib = '编辑文档库'; +$lang->doc->deleteLib = '删除文档库'; + +/* 查询条件列表 */ +$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 = "系统文档库无需修改。"; + +$lang->doc->placeholder = new stdclass(); +$lang->doc->placeholder->url = '相应的链接地址'; diff --git a/module/doc/lang/zh-tw.php b/module/doc/lang/zh-tw.php index 3f1306d50b..216d3fb1bf 100644 --- a/module/doc/lang/zh-tw.php +++ b/module/doc/lang/zh-tw.php @@ -1,71 +1,71 @@ - - * @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->basicInfo = '基本信息'; - -$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->manageType = '維護分類'; - -$lang->doc->libName = '文檔庫名稱'; -$lang->doc->createLib = '創建文檔庫'; -$lang->doc->editLib = '編輯文檔庫'; -$lang->doc->deleteLib = '刪除文檔庫'; - -/* 查詢條件列表 */ -$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 = "系統文檔庫無需修改。"; - -$lang->doc->placeholder = new stdclass(); -$lang->doc->placeholder->url = '相應的連結地址'; + + * @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->basicInfo = '基本信息'; + +$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->manageType = '維護分類'; + +$lang->doc->libName = '文檔庫名稱'; +$lang->doc->createLib = '創建文檔庫'; +$lang->doc->editLib = '編輯文檔庫'; +$lang->doc->deleteLib = '刪除文檔庫'; + +/* 查詢條件列表 */ +$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 = "系統文檔庫無需修改。"; + +$lang->doc->placeholder = new stdclass(); +$lang->doc->placeholder->url = '相應的連結地址'; diff --git a/module/doc/model.php b/module/doc/model.php index 8c8471d85f..59ab68b407 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1,319 +1,319 @@ - - * @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 - * @param bool $setImgSize - * @access public - * @return void - */ - public function getById($docID, $setImgSize = false) - { - $doc = $this->dao->select('*') - ->from(TABLE_DOC) - ->where('id')->eq((int)$docID) - ->fetch(); - if(!$doc) return false; - if($setImgSize) $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'); - } - - /** - * Extract css styles for tables created in kindeditor. - * - * Like this: - * - * @param string $content - * @access public - * @return void - */ - public function extractKETableCSS($content) - { - $css = ''; - $rule = '/
      + * @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 + * @param bool $setImgSize + * @access public + * @return void + */ + public function getById($docID, $setImgSize = false) + { + $doc = $this->dao->select('*') + ->from(TABLE_DOC) + ->where('id')->eq((int)$docID) + ->fetch(); + if(!$doc) return false; + if($setImgSize) $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'); + } + + /** + * Extract css styles for tables created in kindeditor. + * + * Like this:
      + * + * @param string $content + * @access public + * @return void + */ + public function extractKETableCSS($content) + { + $css = ''; + $rule = '/
      - * @package lib - * @version $Id: browse.html.php 958 2010-07-22 08:09:42Z wwccss $ - * @link http://www.zentao.net - */ -?> - - - - - -
      - -
      - doc->create);?> -
      -
      -
      '>
      - -
      - - - - - -
      -
      -
      - -
      - doc->manageType);?> - tree->fix, 'hiddenwin');?> -
      -
      -
      - - - - 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}"; - common::printIcon('doc', 'edit', $vars, '', 'list'); - common::printIcon('doc', 'delete', $vars, '', 'list', '', 'hiddenwin'); - ?> -
      show();?>
      -
      - + + * @package lib + * @version $Id: browse.html.php 958 2010-07-22 08:09:42Z wwccss $ + * @link http://www.zentao.net + */ +?> + + + + + +
      + +
      + doc->create);?> +
      +
      +
      '>
      + + + + + + + +
      +
      +
      + +
      + doc->manageType);?> + tree->fix, 'hiddenwin');?> +
      +
      +
      + + + + 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}"; + common::printIcon('doc', 'edit', $vars, '', 'list'); + common::printIcon('doc', 'delete', $vars, '', 'list', '', 'hiddenwin'); + ?> +
      show();?>
      +
      + diff --git a/module/doc/view/create.html.php b/module/doc/view/create.html.php index f3e7e18c8b..e60ece9464 100644 --- a/module/doc/view/create.html.php +++ b/module/doc/view/create.html.php @@ -1,71 +1,71 @@ - - * @package doc - * @version $Id: create.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - -doc->placeholder, 'json');?> -
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      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->placeholder, 'json');?> +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      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 da2f773981..69faeb88ff 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 7399dbd8b1..ee939529e4 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 72840811b5..ee073da941 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 55ebfab037..104c575308 100644 --- a/module/doc/view/view.html.php +++ b/module/doc/view/view.html.php @@ -1,110 +1,110 @@ - - * @package doc - * @version $Id: view.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ - * @link http://www.zentao.net - */ -?> - - -
      -
      deleted) echo "class='deleted'";?>>DOC #id . ' ' . $doc->title;?>
      -
      -
      - session->docList ? $this->session->docList : inlink('browse'); - $params = "docID=$doc->id"; - if(!$doc->deleted) - { - ob_start(); - common::printIcon('doc', 'edit', $params); - common::printIcon('doc', 'delete', $params, '', 'button', '', 'hiddenwin'); - common::printDivider(); - common::printRPN($browseLink, $preAndNext); - - $actionLinks = ob_get_contents(); - ob_end_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
      -
      -
      - - - - - - - -
      -
      - doc->digest;?> -
      digest;?>
      -
      -
      - doc->keywords;?> -
      keywords;?>
      -
      - type == 'url'):?> -
      - doc->url;?> -
      url), '', '_blank');?>
      -
      - - type == 'text'):?> -
      - doc->content;?> -
      content;?>
      -
      - - type == 'file'):?> - fetch('file', 'printFiles', array('files' => $doc->files, 'fieldset' => 'true'));?> - - - -
      -
      - doc->basicInfo;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      doc->lib;?>
      doc->module;?>moduleName ? $doc->moduleName : '/';?>
      doc->type;?>doc->types[$doc->type];?>
      doc->addedBy;?>addedBy];?>
      doc->addedDate;?>addedDate;?>
      doc->editedBy;?>editedBy];?>
      doc->editedDate;?>editedDate;?>
      -
      - - + + * @package doc + * @version $Id: view.html.php 975 2010-07-29 03:30:25Z jajacn@126.com $ + * @link http://www.zentao.net + */ +?> + + +
      +
      deleted) echo "class='deleted'";?>>DOC #id . ' ' . $doc->title;?>
      +
      +
      + session->docList ? $this->session->docList : inlink('browse'); + $params = "docID=$doc->id"; + if(!$doc->deleted) + { + ob_start(); + common::printIcon('doc', 'edit', $params); + common::printIcon('doc', 'delete', $params, '', 'button', '', 'hiddenwin'); + common::printDivider(); + common::printRPN($browseLink, $preAndNext); + + $actionLinks = ob_get_contents(); + ob_end_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
      +
      +
      + + + + + + + +
      +
      + doc->digest;?> +
      digest;?>
      +
      +
      + doc->keywords;?> +
      keywords;?>
      +
      + type == 'url'):?> +
      + doc->url;?> +
      url), '', '_blank');?>
      +
      + + type == 'text'):?> +
      + doc->content;?> +
      content;?>
      +
      + + type == 'file'):?> + fetch('file', 'printFiles', array('files' => $doc->files, 'fieldset' => 'true'));?> + + + +
      +
      + doc->basicInfo;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      doc->lib;?>
      doc->module;?>moduleName ? $doc->moduleName : '/';?>
      doc->type;?>doc->types[$doc->type];?>
      doc->addedBy;?>addedBy];?>
      doc->addedDate;?>addedDate;?>
      doc->editedBy;?>editedBy];?>
      doc->editedDate;?>editedDate;?>
      +
      + + diff --git a/module/editor/control.php b/module/editor/control.php index 8a7b605417..9869af882d 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 files and methods of the module. - * - * @param string $moduleDir - * @access public - * @return void - */ - public function extend($moduleDir = '') - { - $moduleFiles = $this->editor->getModuleFiles($moduleDir); - $this->view->module = $moduleDir; - $this->view->tree = $this->editor->printTree($moduleFiles); - $this->display(); - } - - /** - * Edit extend. - * - * @param string $filePath - * @param string $action - * @param string $isExtends - * @access public - * @return void - */ - public function edit($filePath = '', $action = '', $isExtends = '') - { - $this->view->safeFilePath = $filePath; - $fileContent = ''; - if($filePath) - { - $filePath = helper::safe64Decode($filePath); - if($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 files and methods of the module. + * + * @param string $moduleDir + * @access public + * @return void + */ + public function extend($moduleDir = '') + { + $moduleFiles = $this->editor->getModuleFiles($moduleDir); + $this->view->module = $moduleDir; + $this->view->tree = $this->editor->printTree($moduleFiles); + $this->display(); + } + + /** + * Edit extend. + * + * @param string $filePath + * @param string $action + * @param string $isExtends + * @access public + * @return void + */ + public function edit($filePath = '', $action = '', $isExtends = '') + { + $this->view->safeFilePath = $filePath; + $fileContent = ''; + if($filePath) + { + $filePath = helper::safe64Decode($filePath); + if($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 4bd2920edc..db24221cc2 100644 --- a/module/editor/model.php +++ b/module/editor/model.php @@ -1,568 +1,568 @@ - - * @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) - { - $module = basename(dirname(key($files))); - - $langFile = dirname(key($files)) . $this->pathFix . 'lang' . $this->pathFix . $this->cookie->lang. '.php'; - if(file_exists($langFile)) - { - if(!isset($lang)) $lang = new stdclass(); - if(!isset($lang->$module)) $lang->$module = new stdclass(); - include_once $langFile; - } - - 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) + { + $module = basename(dirname(key($files))); + + $langFile = dirname(key($files)) . $this->pathFix . 'lang' . $this->pathFix . $this->cookie->lang. '.php'; + if(file_exists($langFile)) + { + if(!isset($lang)) $lang = new stdclass(); + if(!isset($lang->$module)) $lang->$module = new stdclass(); + include_once $langFile; + } + + 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 ab51412c3c..8ea9dd64ee 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 - */ -?> - - -
          ' id='dataform'> - - - - - - - - - - - - - - - - -
          - {$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 + */ +?> + + +
          ' id='dataform'> + + + + + + + + + + + + + + + + +
          + {$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 5fae8ac265..7df223db83 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 873003bfef..a7a4cde84d 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 a0062c7b95..275d368f71 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 13f62812de..ea708a0532 100644 --- a/module/extension/control.php +++ b/module/extension/control.php @@ -1,387 +1,387 @@ - - * @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]; - $extension->viewLink = $release->viewLink; - if($extension->version != $release->latestRelease->releaseVersion and $this->extension->checkVersion($release->latestRelease->zentaoVersion)) - { - $upgradeLink = inlink('upgrade', "extension=$release->code&downLink=" . helper::safe64Encode($release->latestRelease->downLink) . "&md5={$release->latestRelease->md5}&type=$release->type"); - $upgradeLink = ($release->latestRelease->charge or !$release->latestRelease->public) ? $release->latestRelease->downLink : $upgradeLink; - $extension->upgradeLink = $upgradeLink; - } - } - } - } - - $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 - * @param int $upgrade - * @access public - * @return void - */ - public function install($extension, $downLink = '', $md5 = '', $type = '', $overridePackage = 'no', $ignoreCompatible = 'no', $overrideFile = 'no', $agreeLicense = 'no', $upgrade = 'no') - { - $this->view->error = ''; - $installTitle = $upgrade == 'no' ? $this->lang->extension->install : $this->lang->extension->upgrade; - $installType = $upgrade == 'no' ? $this->lang->extension->installExt : $this->lang->extension->upgradeExt; - $this->view->installType = $installType; - $this->view->upgrade = $upgrade; - $this->view->header->title = $installTitle . $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&upgrade=$upgrade"); - $this->view->error = sprintf($this->lang->extension->errorPackageFileExists, $packageFile, $installType, $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&overrideFile=$overrideFile&agreeLicense=$agreeLicense&upgrade=$upgrade"); - $returnLink = inlink('obtain'); - $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $installType, $ignoreLink, $installType, $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&agreeLicense=$agreeLicense&upgrade=$upgrade"); - $returnLink = inlink('obtain'); - $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, $returnLink); - die($this->display()); - } - } - - if($upgrade == 'yes') - { - $newInfo = $this->extension->parseExtensionCFG($extension); - $this->post->upgradeVersion = isset($newInfo->version) ? $newInfo->version : ''; - $oldInfo = $this->extension->getInfoFromDB($extension); - $this->post->installedVersion = $oldInfo ? $oldInfo->version : ''; - } - - /* 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&upgrade=$upgrade"); - $this->view->license = $license; - $this->view->author = $extensionInfo->author; - $this->view->agreeLink = $agreeLink; - die($this->display()); - } - - /* The preInstall hook file. */ - $hook = $upgrade == 'yes' ? 'preupgrade' : 'preinstall'; - if($preHookFile = $this->extension->getHookFile($extension, $hook)) include $preHookFile; - - /* 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($upgrade == 'no' and $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. */ - $hook = $upgrade == 'yes' ? 'postupgrade' : 'postinstall'; - if($postHookFile = $this->extension->getHookFile($extension, $hook)) include $postHookFile; - - $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"); - $info = $this->extension->getInfoFromDB($extension); - $type = $info->status == 'installed' ? 'upgrade' : 'install'; - $link = $type == 'install' ? inlink('install', "extension=$extension") : inlink('upgrade', "extension=$extension"); - $this->locate($link); - } - $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&overrideFile=no&agreeLicense=no&upgrade=yes")); - } - - /** - * Browse the structure of extension. - * - * @param int $extension - * @access public - * @return void - */ - public function structure($extension) - { - $this->view->extension = $this->extension->getInfoFromDB($extension); - $this->display(); - } -} + + * @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]; + $extension->viewLink = $release->viewLink; + if($extension->version != $release->latestRelease->releaseVersion and $this->extension->checkVersion($release->latestRelease->zentaoVersion)) + { + $upgradeLink = inlink('upgrade', "extension=$release->code&downLink=" . helper::safe64Encode($release->latestRelease->downLink) . "&md5={$release->latestRelease->md5}&type=$release->type"); + $upgradeLink = ($release->latestRelease->charge or !$release->latestRelease->public) ? $release->latestRelease->downLink : $upgradeLink; + $extension->upgradeLink = $upgradeLink; + } + } + } + } + + $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 + * @param int $upgrade + * @access public + * @return void + */ + public function install($extension, $downLink = '', $md5 = '', $type = '', $overridePackage = 'no', $ignoreCompatible = 'no', $overrideFile = 'no', $agreeLicense = 'no', $upgrade = 'no') + { + $this->view->error = ''; + $installTitle = $upgrade == 'no' ? $this->lang->extension->install : $this->lang->extension->upgrade; + $installType = $upgrade == 'no' ? $this->lang->extension->installExt : $this->lang->extension->upgradeExt; + $this->view->installType = $installType; + $this->view->upgrade = $upgrade; + $this->view->header->title = $installTitle . $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&upgrade=$upgrade"); + $this->view->error = sprintf($this->lang->extension->errorPackageFileExists, $packageFile, $installType, $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&overrideFile=$overrideFile&agreeLicense=$agreeLicense&upgrade=$upgrade"); + $returnLink = inlink('obtain'); + $this->view->error = sprintf($this->lang->extension->errorCheckIncompatible, $installType, $ignoreLink, $installType, $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&agreeLicense=$agreeLicense&upgrade=$upgrade"); + $returnLink = inlink('obtain'); + $this->view->error = sprintf($this->lang->extension->errorFileConflicted, $return->error, $overrideLink, $returnLink); + die($this->display()); + } + } + + if($upgrade == 'yes') + { + $newInfo = $this->extension->parseExtensionCFG($extension); + $this->post->upgradeVersion = isset($newInfo->version) ? $newInfo->version : ''; + $oldInfo = $this->extension->getInfoFromDB($extension); + $this->post->installedVersion = $oldInfo ? $oldInfo->version : ''; + } + + /* 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&upgrade=$upgrade"); + $this->view->license = $license; + $this->view->author = $extensionInfo->author; + $this->view->agreeLink = $agreeLink; + die($this->display()); + } + + /* The preInstall hook file. */ + $hook = $upgrade == 'yes' ? 'preupgrade' : 'preinstall'; + if($preHookFile = $this->extension->getHookFile($extension, $hook)) include $preHookFile; + + /* 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($upgrade == 'no' and $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. */ + $hook = $upgrade == 'yes' ? 'postupgrade' : 'postinstall'; + if($postHookFile = $this->extension->getHookFile($extension, $hook)) include $postHookFile; + + $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"); + $info = $this->extension->getInfoFromDB($extension); + $type = $info->status == 'installed' ? 'upgrade' : 'install'; + $link = $type == 'install' ? inlink('install', "extension=$extension") : inlink('upgrade', "extension=$extension"); + $this->locate($link); + } + $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&overrideFile=no&agreeLicense=no&upgrade=yes")); + } + + /** + * Browse the structure of extension. + * + * @param int $extension + * @access public + * @return void + */ + public function structure($extension) + { + $this->view->extension = $this->extension->getInfoFromDB($extension); + $this->display(); + } +} diff --git a/module/extension/lang/en.php b/module/extension/lang/en.php index af2485137d..7c0c30ef83 100644 --- a/module/extension/lang/en.php +++ b/module/extension/lang/en.php @@ -1,98 +1,98 @@ - - * @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 Extension'; -$lang->extension->agreeLicense = 'I agree the license'; - -$lang->extension->structure = 'Structure'; -$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 = '%s failed, the reason is:'; -$lang->extension->installFinished = 'Good, the extension has been %s 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->upgradeExt = 'Upgrade'; -$lang->extension->installExt = 'Install'; -$lang->extension->upgradeVersion = '(Upgrade from %s to %s)'; - -$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 %s 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 %s or Cancel

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

          You can Overide them or Cancel

          .'; -$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 Extension'; +$lang->extension->agreeLicense = 'I agree the license'; + +$lang->extension->structure = 'Structure'; +$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 = '%s failed, the reason is:'; +$lang->extension->installFinished = 'Good, the extension has been %s 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->upgradeExt = 'Upgrade'; +$lang->extension->installExt = 'Install'; +$lang->extension->upgradeVersion = '(Upgrade from %s to %s)'; + +$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 %s 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 %s or Cancel

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

          You can Overide them or Cancel

          .'; +$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 5eba7b3c9a..fed82fe118 100644 --- a/module/extension/lang/zh-cn.php +++ b/module/extension/lang/zh-cn.php @@ -1,98 +1,98 @@ - - * @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->structure = '目录结构'; -$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 = '%s失败,错误原因如下:'; -$lang->extension->installFinished = '恭喜您,插件顺利的%s成功!'; -$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->upgradeExt = '升级'; -$lang->extension->installExt = '安装'; -$lang->extension->upgradeVersion = '(从%s升级到%s)'; - -$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附件。

          重新%s,请点击此链接

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

          您可以选择 强制%s 或者 取消

          '; -$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->structure = '目录结构'; +$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 = '%s失败,错误原因如下:'; +$lang->extension->installFinished = '恭喜您,插件顺利的%s成功!'; +$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->upgradeExt = '升级'; +$lang->extension->installExt = '安装'; +$lang->extension->upgradeVersion = '(从%s升级到%s)'; + +$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附件。

          重新%s,请点击此链接

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

          您可以选择 强制%s 或者 取消

          '; +$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 c41ed9bef2..f6fae04653 100644 --- a/module/extension/lang/zh-tw.php +++ b/module/extension/lang/zh-tw.php @@ -1,98 +1,98 @@ - - * @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->structure = '目錄結構'; -$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 = '%s失敗,錯誤原因如下:'; -$lang->extension->installFinished = '恭喜您,插件順利的%s成功!'; -$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->upgradeExt = '升級'; -$lang->extension->installExt = '安裝'; -$lang->extension->upgradeVersion = '(從%s升級到%s)'; - -$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附件。

          重新%s,請點擊此連結

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

          您可以選擇 強制%s 或者 取消

          '; -$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->structure = '目錄結構'; +$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 = '%s失敗,錯誤原因如下:'; +$lang->extension->installFinished = '恭喜您,插件順利的%s成功!'; +$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->upgradeExt = '升級'; +$lang->extension->installExt = '安裝'; +$lang->extension->upgradeVersion = '(從%s升級到%s)'; + +$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附件。

          重新%s,請點擊此連結

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

          您可以選擇 強制%s 或者 取消

          '; +$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 3426a2b896..adf7fe3151 100644 --- a/module/extension/model.php +++ b/module/extension/model.php @@ -1,757 +1,757 @@ - - * @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('zfile'); - } - - /** - * 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)->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 = ''; - $data->type = ''; - - $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); - if($extension->type == 'patch') return true; - $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 = empty($type) ? $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('zfile'); + } + + /** + * 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)->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 = ''; + $data->type = ''; + + $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); + if($extension->type == 'patch') return true; + $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 = empty($type) ? $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 2e2335c3ba..573a4d97e6 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 63e12ce559..6779b9a29a 100644 --- a/module/extension/view/browse.html.php +++ b/module/extension/view/browse.html.php @@ -1,61 +1,61 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
          name";?>
          -
          desc;?>
          -
          - extension->version}: {$extension->version} "; - echo "{$lang->extension->author}: {$extension->author} "; - ?> -
          -
          - code"), $lang->extension->structure, '', "class='button-c iframe'"); - $deactivateCode = html::a(inlink('deactivate', "extension=$extension->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(isset($extension->viewLink)) - { - echo html::a($extension->viewLink, $lang->extension->view, '', "class='button-c extension'"); - } - if($extension->status == 'installed') - { - echo $structureCode; - } - 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->structure, '', "class='button-c iframe'"); + $deactivateCode = html::a(inlink('deactivate', "extension=$extension->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(isset($extension->viewLink)) + { + echo html::a($extension->viewLink, $lang->extension->view, '', "class='button-c extension'"); + } + if($extension->status == 'installed') + { + echo $structureCode; + } + 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 aed10a40ec..a7cd19658d 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 800fb2a4d8..d603f621c7 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 91994e1766..81ffad644a 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 6be0901b48..49f987a6a1 100644 --- a/module/extension/view/install.html.php +++ b/module/extension/view/install.html.php @@ -1,54 +1,54 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          -title; -if(isset($license) and $upgrade == 'yes') printf($lang->extension->upgradeVersion, $this->post->installedVersion, $this->post->upgradeVersion); -?> -
          - - " . sprintf($lang->extension->installFailed, $installType) . ""; - 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 "

          " . sprintf($lang->extension->installFinished, $installType) . "

          "; - echo "

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

          '; - ?> - -
          - - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          +title; +if(isset($license) and $upgrade == 'yes') printf($lang->extension->upgradeVersion, $this->post->installedVersion, $this->post->upgradeVersion); +?> +
          + + " . sprintf($lang->extension->installFailed, $installType) . ""; + 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 "

          " . sprintf($lang->extension->installFinished, $installType) . "

          "; + 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 963624a332..470421b9af 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 and $this->extension->checkVersion($extension->latestRelease->zentaoVersion)) - { - $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 and $this->extension->checkVersion($extension->latestRelease->zentaoVersion)) + { + $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/structure.html.php b/module/extension/view/structure.html.php index c0fdcf230f..55aad2981a 100644 --- a/module/extension/view/structure.html.php +++ b/module/extension/view/structure.html.php @@ -1,26 +1,26 @@ - - * @package extension - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -
          name . '[' . $extension->code . '] ' .$lang->extension->structure . ':';?> -
          - app->getAppRoot(); - $files = json_decode($extension->files); - foreach($files as $file => $md5) echo $appRoot . $file . "
          "; - ?> -
          - + + * @package extension + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + +
          name . '[' . $extension->code . '] ' .$lang->extension->structure . ':';?> +
          + app->getAppRoot(); + $files = json_decode($extension->files); + foreach($files as $file => $md5) echo $appRoot . $file . "
          "; + ?> +
          + diff --git a/module/extension/view/uninstall.html.php b/module/extension/view/uninstall.html.php index e8eff9d9d6..2871788a9e 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 56eb4470d8..7fd45464aa 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 866107d546..1b7c1a3882 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 90f2780e54..4353e3adff 100644 --- a/module/file/control.php +++ b/module/file/control.php @@ -1,294 +1,294 @@ - - * @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( $this->post->encode != "utf-8") - { - if(function_exists('mb_convert_encoding')) - { - $output = @mb_convert_encoding($output, $this->post->encode, 'utf-8'); - } - elseif(function_exists('iconv')) - { - $output = @iconv('utf-8', $this->post->encode, $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->host = common::getSysURL(); - - switch($this->post->kind) - { - case 'task': - foreach($this->view->rows as $row) - { - $row->name = html::a($this->host . $this->createLink('task', 'view', "taskID=$row->id"), $row->name); - } - break; - case 'story': - foreach($this->view->rows as $row) - { - $row->title= html::a($this->host . $this->createLink('story', 'view', "storyID=$row->id"), $row->title); - } - break; - case 'bug': - foreach($this->view->rows as $row) - { - $row->title= html::a($this->host . $this->createLink('bug', 'view', "bugID=$row->id"), $row->title); - } - break; - case 'testcase': - foreach($this->view->rows as $row) - { - $row->title= html::a($this->host . $this->createLink('testcase', 'view', "caseID=$row->id"), $row->title); - } - break; - } - $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) - { - ob_clean(); // clean the ob content to make sure no space or utf-8 bom output. - - /* 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( $this->post->encode != "utf-8") + { + if(function_exists('mb_convert_encoding')) + { + $output = @mb_convert_encoding($output, $this->post->encode, 'utf-8'); + } + elseif(function_exists('iconv')) + { + $output = @iconv('utf-8', $this->post->encode, $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->host = common::getSysURL(); + + switch($this->post->kind) + { + case 'task': + foreach($this->view->rows as $row) + { + $row->name = html::a($this->host . $this->createLink('task', 'view', "taskID=$row->id"), $row->name); + } + break; + case 'story': + foreach($this->view->rows as $row) + { + $row->title= html::a($this->host . $this->createLink('story', 'view', "storyID=$row->id"), $row->title); + } + break; + case 'bug': + foreach($this->view->rows as $row) + { + $row->title= html::a($this->host . $this->createLink('bug', 'view', "bugID=$row->id"), $row->title); + } + break; + case 'testcase': + foreach($this->view->rows as $row) + { + $row->title= html::a($this->host . $this->createLink('testcase', 'view', "caseID=$row->id"), $row->title); + } + break; + } + $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) + { + ob_clean(); // clean the ob content to make sure no space or utf-8 bom output. + + /* 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 4d7d2eabfa..3f549d3aa5 100644 --- a/module/file/lang/en.php +++ b/module/file/lang/en.php @@ -1,25 +1,25 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->file = new stdclass(); -$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->maxUploadSize = "%s"; - -$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 = new stdclass(); +$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->maxUploadSize = "%s"; + +$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 817376fcf6..3cbfca9841 100644 --- a/module/file/lang/zh-cn.php +++ b/module/file/lang/zh-cn.php @@ -1,25 +1,25 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->file = new stdclass(); -$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->maxUploadSize = "%s"; - -$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 = new stdclass(); +$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->maxUploadSize = "%s"; + +$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 c873fe5593..13bc7f6abc 100644 --- a/module/file/lang/zh-tw.php +++ b/module/file/lang/zh-tw.php @@ -1,25 +1,25 @@ - - * @package file - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @link http://www.zentao.net - */ -$lang->file = new stdclass(); -$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->maxUploadSize = "最大可上傳附件:%s"; - -$lang->file->errorNotExists = "檔案夾 '%s' 不存在"; -$lang->file->errorCanNotWrite = "檔案夾 '%s' 不可寫,請改變檔案夾的權限。在linux中輸入指令:sudo chmod -R 777 '%s'"; -$lang->file->confirmDelete = " 您確定刪除該附件嗎?"; + + * @package file + * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ + * @link http://www.zentao.net + */ +$lang->file = new stdclass(); +$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->maxUploadSize = "最大可上傳附件:%s"; + +$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 32892c3331..ab8c08f391 100644 --- a/module/file/model.php +++ b/module/file/model.php @@ -1,239 +1,239 @@ - - * @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(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); - } - - /** - * Replace a file. - * - * @access public - * @return bool - */ - public function replaceFile($fileID, $postName = 'upFile') - { - if($files = $this->getUpload($postName)) - { - $file = $files[0]; - $filePath = $this->dao->select('pathname')->from(TABLE_FILE)->where('id')->eq($fileID)->fetch('', false); - $pathName = $filePath->pathname; - $realPathName= $this->savePath . $pathName; - if(!is_dir(dirname($realPathName)))mkdir(dirname($realPathName)); - move_uploaded_file($file['tmpname'], $realPathName); - - $fileInfo->addedBy = $this->app->user->account; - $fileInfo->addedDate = helper::now(); - $fileInfo->size = $file['size']; - $this->dao->update(TABLE_FILE)->data($fileInfo, false)->where('id')->eq($fileID)->exec(false); - return true; - } - else - { - return false; - } - } - -} + + * @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(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); + } + + /** + * Replace a file. + * + * @access public + * @return bool + */ + public function replaceFile($fileID, $postName = 'upFile') + { + if($files = $this->getUpload($postName)) + { + $file = $files[0]; + $filePath = $this->dao->select('pathname')->from(TABLE_FILE)->where('id')->eq($fileID)->fetch('', false); + $pathName = $filePath->pathname; + $realPathName= $this->savePath . $pathName; + if(!is_dir(dirname($realPathName)))mkdir(dirname($realPathName)); + move_uploaded_file($file['tmpname'], $realPathName); + + $fileInfo->addedBy = $this->app->user->account; + $fileInfo->addedDate = helper::now(); + $fileInfo->size = $file['size']; + $this->dao->update(TABLE_FILE)->data($fileInfo, false)->where('id')->eq($fileID)->exec(false); + return true; + } + else + { + return false; + } + } + +} diff --git a/module/file/view/edit.html.php b/module/file/view/edit.html.php index b3490e46f3..0d476fae11 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 4a07af54b1..6cf3311d7e 100644 --- a/module/file/view/export.html.php +++ b/module/file/view/export.html.php @@ -1,62 +1,62 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -

          -
          - - - - - -
          export;?>
          - ' . $lang->exportType . ':' . html::radio('exportType', $lang->exportTypeList, ($this->cookie->checkedItem) ? 'selected' : 'all') . '

          '?> - setFileName;?> - - exportFileTypeList, '', 'onchange=switchEncode(this.value)');?> - exportEncodeList, 'gbk', key($lang->exportFileTypeList) == 'csv' ? "" : "class='hidden'");?> - -
          -
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +

          +
          + + + + + +
          export;?>
          + ' . $lang->exportType . ':' . html::radio('exportType', $lang->exportTypeList, ($this->cookie->checkedItem) ? 'selected' : 'all') . '

          '?> + setFileName;?> + + exportFileTypeList, '', 'onchange=switchEncode(this.value)');?> + exportEncodeList, 'gbk', key($lang->exportFileTypeList) == 'csv' ? "" : "class='hidden'");?> + +
          +
          + diff --git a/module/file/view/export2csv.html.php b/module/file/view/export2csv.html.php index 1e8f1b53ca..4d65d72b09 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 3fbb16b749..b7b355f0bb 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 3747ab98b7..0d03be5d55 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 1a60b0ace9..5fdef3bd36 100644 --- a/module/group/control.php +++ b/module/group/control.php @@ -1,236 +1,236 @@ - - * @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); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->groups = $groups; - - $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, $menu = 'my', $version = '') - { - if($type == 'byGroup') $groupID = $param; - $this->view->type = $type; - foreach($this->lang->resource as $moduleName => $action) - { - if($this->group->checkMenuModule($menu, $moduleName) or $type != 'byGroup') $this->app->loadLang($moduleName); - } - - if(!empty($_POST)) - { - if($type == 'byGroup') $result = $this->group->updatePrivByGroup($groupID, $menu, $version); - if($type == 'byModule') $result = $this->group->updatePrivByModule(); - print(js::alert($result ? $this->lang->group->successSaved : $this->lang->group->errorNotSaved)); - exit; - } - - if($type == 'byGroup') - { - $this->group->sortResource(); - $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; - - /* Join changelog when be equal or greater than this version.*/ - $realVersion = str_replace('_', '.', $version); - $changelog = array(); - foreach($this->lang->changelog as $currentVersion => $currentChangeLog) - { - if(version_compare($currentVersion, $realVersion, '>=')) $changelog[] = join($currentChangeLog, ','); - } - - $this->view->group = $group; - $this->view->changelogs = ',' . join($changelog, ',') . ','; - $this->view->groupPrivs = $groupPrivs; - $this->view->groupID = $groupID; - $this->view->menu = $menu; - $this->view->version = $version; - } - elseif($type == 'byModule') - { - $this->group->sortResource(); - $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('nodeleted|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); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->groups = $groups; + + $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, $menu = 'my', $version = '') + { + if($type == 'byGroup') $groupID = $param; + $this->view->type = $type; + foreach($this->lang->resource as $moduleName => $action) + { + if($this->group->checkMenuModule($menu, $moduleName) or $type != 'byGroup') $this->app->loadLang($moduleName); + } + + if(!empty($_POST)) + { + if($type == 'byGroup') $result = $this->group->updatePrivByGroup($groupID, $menu, $version); + if($type == 'byModule') $result = $this->group->updatePrivByModule(); + print(js::alert($result ? $this->lang->group->successSaved : $this->lang->group->errorNotSaved)); + exit; + } + + if($type == 'byGroup') + { + $this->group->sortResource(); + $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; + + /* Join changelog when be equal or greater than this version.*/ + $realVersion = str_replace('_', '.', $version); + $changelog = array(); + foreach($this->lang->changelog as $currentVersion => $currentChangeLog) + { + if(version_compare($currentVersion, $realVersion, '>=')) $changelog[] = join($currentChangeLog, ','); + } + + $this->view->group = $group; + $this->view->changelogs = ',' . join($changelog, ',') . ','; + $this->view->groupPrivs = $groupPrivs; + $this->view->groupID = $groupID; + $this->view->menu = $menu; + $this->view->version = $version; + } + elseif($type == 'byModule') + { + $this->group->sortResource(); + $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('nodeleted|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 9fec4ffaac..e934de8627 100644 --- a/module/group/lang/en.php +++ b/module/group/lang/en.php @@ -1,64 +1,64 @@ - - * @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->option = 'Option'; -$lang->group->inside = 'Group users'; -$lang->group->outside = 'Other users'; -$lang->group->other = 'Other module'; -$lang->group->all = 'All priv'; - -$lang->group->copyOptions['copyPriv'] = 'Copy priviledge'; -$lang->group->copyOptions['copyUser'] = 'Copy user'; - -$lang->group->versions[''] = 'Since version of power'; -$lang->group->versions['4_0_beta2'] = 'Zentao 4.0.beta2'; -$lang->group->versions['3_3'] = 'Zentao 3.3'; -$lang->group->versions['3_2_1'] = 'Zentao 3.2.1'; -$lang->group->versions['3_2'] = 'Zentao 3.2'; -$lang->group->versions['3_1'] = 'Zentao 3.1'; -$lang->group->versions['3_0_beta2'] = 'Zentao 3.0.beta2'; -$lang->group->versions['3_0_beta1'] = 'Zentao 3.0.beta1'; -$lang->group->versions['2_4'] = 'Zentao 2.4'; -$lang->group->versions['2_3'] = 'Zentao 2.3'; -$lang->group->versions['2_2'] = 'Zentao 2.2'; -$lang->group->versions['2_1'] = 'Zentao 2.1'; -$lang->group->versions['2_0'] = 'Zentao 2.0'; -$lang->group->versions['1_5'] = 'Zentao 1.5'; -$lang->group->versions['1_4'] = 'Zentao 1.4'; -$lang->group->versions['1_3'] = 'Zentao 1.3'; -$lang->group->versions['1_2'] = 'Zentao 1.2'; -$lang->group->versions['1_1'] = 'Zentao 1.1'; -$lang->group->versions['1_0_1'] = 'Zentao 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->option = 'Option'; +$lang->group->inside = 'Group users'; +$lang->group->outside = 'Other users'; +$lang->group->other = 'Other module'; +$lang->group->all = 'All priv'; + +$lang->group->copyOptions['copyPriv'] = 'Copy priviledge'; +$lang->group->copyOptions['copyUser'] = 'Copy user'; + +$lang->group->versions[''] = 'Since version of power'; +$lang->group->versions['4_0_beta2'] = 'Zentao 4.0.beta2'; +$lang->group->versions['3_3'] = 'Zentao 3.3'; +$lang->group->versions['3_2_1'] = 'Zentao 3.2.1'; +$lang->group->versions['3_2'] = 'Zentao 3.2'; +$lang->group->versions['3_1'] = 'Zentao 3.1'; +$lang->group->versions['3_0_beta2'] = 'Zentao 3.0.beta2'; +$lang->group->versions['3_0_beta1'] = 'Zentao 3.0.beta1'; +$lang->group->versions['2_4'] = 'Zentao 2.4'; +$lang->group->versions['2_3'] = 'Zentao 2.3'; +$lang->group->versions['2_2'] = 'Zentao 2.2'; +$lang->group->versions['2_1'] = 'Zentao 2.1'; +$lang->group->versions['2_0'] = 'Zentao 2.0'; +$lang->group->versions['1_5'] = 'Zentao 1.5'; +$lang->group->versions['1_4'] = 'Zentao 1.4'; +$lang->group->versions['1_3'] = 'Zentao 1.3'; +$lang->group->versions['1_2'] = 'Zentao 1.2'; +$lang->group->versions['1_1'] = 'Zentao 1.1'; +$lang->group->versions['1_0_1'] = 'Zentao 1.0.1'; + +include (dirname(__FILE__) . '/resource.php'); diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index cc7525cd0f..2bbe73a2ed 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1,795 +1,795 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ - -/* Module order. */ -$lang->moduleOrder[0] = 'index'; -$lang->moduleOrder[5] = 'my'; -$lang->moduleOrder[10] = 'todo'; - -$lang->moduleOrder[15] = 'product'; -$lang->moduleOrder[20] = 'story'; -$lang->moduleOrder[25] = 'productplan'; -$lang->moduleOrder[30] = 'release'; - -$lang->moduleOrder[35] = 'project'; -$lang->moduleOrder[40] = 'task'; -$lang->moduleOrder[45] = 'build'; - -$lang->moduleOrder[50] = 'qa'; -$lang->moduleOrder[55] = 'bug'; -$lang->moduleOrder[60] = 'testcase'; -$lang->moduleOrder[65] = 'testtask'; - -$lang->moduleOrder[70] = 'doc'; -$lang->moduleOrder[75] = 'report'; - -$lang->moduleOrder[80] = 'company'; -$lang->moduleOrder[85] = 'dept'; -$lang->moduleOrder[90] = 'group'; -$lang->moduleOrder[95] = 'user'; - -$lang->moduleOrder[100] = 'admin'; -$lang->moduleOrder[105] = 'extension'; -$lang->moduleOrder[105] = 'extension'; -$lang->moduleOrder[110] = 'editor'; -$lang->moduleOrder[115] = 'convert'; -$lang->moduleOrder[120] = 'action'; - -$lang->moduleOrder[125] = 'mail'; -$lang->moduleOrder[130] = 'svn'; -$lang->moduleOrder[135] = 'search'; -$lang->moduleOrder[140] = 'tree'; -$lang->moduleOrder[145] = 'api'; -$lang->moduleOrder[150] = 'file'; -$lang->moduleOrder[155] = 'misc'; - -$lang->resource = new stdclass(); - -/* Index module. */ -$lang->resource->index = new stdclass(); -$lang->resource->index->index = 'index'; - -$lang->index->methodOrder[0] = 'index'; - -/* My module. */ -$lang->resource->my = new stdclass(); -$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 = 'myProject'; -$lang->resource->my->profile = 'profile'; -$lang->resource->my->dynamic = 'dynamic'; -$lang->resource->my->editProfile = 'editProfile'; -$lang->resource->my->changePassword = 'changePassword'; - -$lang->my->methodOrder[0] = 'index'; -$lang->my->methodOrder[5] = 'todo'; -$lang->my->methodOrder[10] = 'task'; -$lang->my->methodOrder[15] = 'bug'; -$lang->my->methodOrder[20] = 'testTask'; -$lang->my->methodOrder[25] = 'testCase'; -$lang->my->methodOrder[30] = 'story'; -$lang->my->methodOrder[35] = 'project'; -$lang->my->methodOrder[40] = 'profile'; -$lang->my->methodOrder[45] = 'dynamic'; -$lang->my->methodOrder[50] = 'editProfile'; -$lang->my->methodOrder[55] = 'changePassword'; - -/* Todo. */ -$lang->resource->todo = new stdclass(); -$lang->resource->todo->create = 'create'; -$lang->resource->todo->batchCreate = 'batchCreate'; -$lang->resource->todo->edit = 'edit'; -$lang->resource->todo->batchEdit = 'batchEdit'; -$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'; - -$lang->todo->methodOrder[5] = 'create'; -$lang->todo->methodOrder[10] = 'batchCreate'; -$lang->todo->methodOrder[15] = 'edit'; -$lang->todo->methodOrder[20] = 'view'; -$lang->todo->methodOrder[25] = 'delete'; -$lang->todo->methodOrder[30] = 'export'; -$lang->todo->methodOrder[35] = 'mark'; -$lang->todo->methodOrder[40] = 'import2Today'; - -/* Product. */ -$lang->resource->product = new stdclass(); -$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->order = 'order'; -$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->product->methodOrder[0] = 'index'; -$lang->product->methodOrder[5] = 'browse'; -$lang->product->methodOrder[10] = 'create'; -$lang->product->methodOrder[15] = 'view'; -$lang->product->methodOrder[20] = 'edit'; -$lang->product->methodOrder[25] = 'order'; -$lang->product->methodOrder[30] = 'delete'; -$lang->product->methodOrder[35] = 'roadmap'; -$lang->product->methodOrder[40] = 'doc'; -$lang->product->methodOrder[45] = 'dynamic'; -$lang->product->methodOrder[50] = 'project'; - -/* Story. */ -$lang->resource->story = new stdclass(); -$lang->resource->story->create = 'create'; -$lang->resource->story->batchCreate = 'batchCreate'; -$lang->resource->story->edit = 'edit'; -$lang->resource->story->batchEdit = 'batchEdit'; -$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->batchClose = 'batchClose'; -$lang->resource->story->activate = 'lblActivate'; -$lang->resource->story->tasks = 'tasks'; -$lang->resource->story->report = 'reportChart'; - -$lang->story->methodOrder[5] = 'create'; -$lang->story->methodOrder[10] = 'batchCreate'; -$lang->story->methodOrder[15] = 'edit'; -$lang->story->methodOrder[20] = 'export'; -$lang->story->methodOrder[25] = 'delete'; -$lang->story->methodOrder[30] = 'view'; -$lang->story->methodOrder[35] = 'change'; -$lang->story->methodOrder[40] = 'review'; -$lang->story->methodOrder[45] = 'close'; -$lang->story->methodOrder[50] = 'batchClose'; -$lang->story->methodOrder[55] = 'activate'; -$lang->story->methodOrder[60] = 'tasks'; -$lang->story->methodOrder[65] = 'report'; - -/* Product plan. */ -$lang->resource->productplan = new stdclass(); -$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'; - -$lang->productplan->methodOrder[5] = 'browse'; -$lang->productplan->methodOrder[10] = 'create'; -$lang->productplan->methodOrder[15] = 'edit'; -$lang->productplan->methodOrder[20] = 'delete'; -$lang->productplan->methodOrder[25] = 'view'; -$lang->productplan->methodOrder[30] = 'linkStory'; -$lang->productplan->methodOrder[35] = 'unlinkStory'; - -/* Release. */ -$lang->resource->release = new stdclass(); -$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->export = 'export'; - -$lang->release->methodOrder[5] = 'browse'; -$lang->release->methodOrder[10] = 'create'; -$lang->release->methodOrder[15] = 'edit'; -$lang->release->methodOrder[20] = 'delete'; -$lang->release->methodOrder[25] = 'view'; -$lang->release->methodOrder[35] = 'export'; - -/* Project. */ -$lang->resource->project = new stdclass(); -$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->order = 'order'; -$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->project->methodOrder[0] = 'index'; -$lang->project->methodOrder[5] = 'view'; -$lang->project->methodOrder[10] = 'browse'; -$lang->project->methodOrder[15] = 'create'; -$lang->project->methodOrder[20] = 'edit'; -$lang->project->methodOrder[25] = 'order'; -$lang->project->methodOrder[30] = 'delete'; -$lang->project->methodOrder[35] = 'task'; -$lang->project->methodOrder[40] = 'grouptask'; -$lang->project->methodOrder[45] = 'importtask'; -$lang->project->methodOrder[50] = 'importBug'; -$lang->project->methodOrder[55] = 'story'; -$lang->project->methodOrder[60] = 'build'; -$lang->project->methodOrder[65] = 'testtask'; -$lang->project->methodOrder[70] = 'bug'; -$lang->project->methodOrder[75] = 'burn'; -$lang->project->methodOrder[80] = 'computeBurn'; -$lang->project->methodOrder[85] = 'burnData'; -$lang->project->methodOrder[90] = 'team'; -$lang->project->methodOrder[95] = 'doc'; -$lang->project->methodOrder[100] = 'dynamic'; -$lang->project->methodOrder[105] = 'manageProducts'; -$lang->project->methodOrder[110] = 'manageMembers'; -$lang->project->methodOrder[115] = 'unlinkMember'; -$lang->project->methodOrder[120] = 'linkStory'; -$lang->project->methodOrder[125] = 'unlinkStory'; - -/* Task. */ -$lang->resource->task = new stdclass(); -$lang->resource->task->create = 'create'; -$lang->resource->task->batchCreate = 'batchCreate'; -$lang->resource->task->batchEdit = 'batchEdit'; -$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->report = 'reportChart'; - -$lang->task->methodOrder[5] = 'create'; -$lang->task->methodOrder[10] = 'batchCreate'; -$lang->task->methodOrder[15] = 'batchEdit'; -$lang->task->methodOrder[20] = 'edit'; -$lang->task->methodOrder[25] = 'assignTo'; -$lang->task->methodOrder[30] = 'start'; -$lang->task->methodOrder[35] = 'finish'; -$lang->task->methodOrder[40] = 'cancel'; -$lang->task->methodOrder[45] = 'close'; -$lang->task->methodOrder[50] = 'batchClose'; -$lang->task->methodOrder[55] = 'activate'; -$lang->task->methodOrder[60] = 'delete'; -$lang->task->methodOrder[65] = 'view'; -$lang->task->methodOrder[70] = 'export'; -$lang->task->methodOrder[75] = 'confirmStoryChange'; -$lang->task->methodOrder[90] = 'report'; - -/* Build. */ -$lang->resource->build = new stdclass(); -$lang->resource->build->create = 'create'; -$lang->resource->build->edit = 'edit'; -$lang->resource->build->delete = 'delete'; -$lang->resource->build->view = 'view'; - -$lang->build->methodOrder[5] = 'create'; -$lang->build->methodOrder[10] = 'edit'; -$lang->build->methodOrder[15] = 'delete'; -$lang->build->methodOrder[20] = 'view'; - -/* QA. */ -$lang->resource->qa = new stdclass(); -$lang->resource->qa->index = 'index'; - -$lang->qa->methodOrder[0] = 'index'; - -/* Bug. */ -$lang->resource->bug = new stdclass(); -$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->batchEdit = 'batchEdit'; -$lang->resource->bug->assignTo = 'assignTo'; -$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->bug->methodOrder[0] = 'index'; -$lang->bug->methodOrder[5] = 'browse'; -$lang->bug->methodOrder[10] = 'create'; -$lang->bug->methodOrder[15] = 'confirmBug'; -$lang->bug->methodOrder[20] = 'view'; -$lang->bug->methodOrder[25] = 'edit'; -$lang->bug->methodOrder[30] = 'assignTo'; -$lang->bug->methodOrder[35] = 'resolve'; -$lang->bug->methodOrder[40] = 'activate'; -$lang->bug->methodOrder[45] = 'close'; -$lang->bug->methodOrder[50] = 'report'; -$lang->bug->methodOrder[55] = 'export'; -$lang->bug->methodOrder[60] = 'confirmStoryChange'; -$lang->bug->methodOrder[65] = 'delete'; -$lang->bug->methodOrder[70] = 'saveTemplate'; -$lang->bug->methodOrder[75] = 'deleteTemplate'; -$lang->bug->methodOrder[80] = 'customFields'; - -/* Test case. */ -$lang->resource->testcase = new stdclass(); -$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->batchEdit = 'batchEdit'; -$lang->resource->testcase->delete = 'delete'; -$lang->resource->testcase->export = 'export'; -$lang->resource->testcase->confirmStoryChange = 'confirmStoryChange'; - -$lang->testcase->methodOrder[0] = 'index'; -$lang->testcase->methodOrder[5] = 'browse'; -$lang->testcase->methodOrder[10] = 'create'; -$lang->testcase->methodOrder[15] = 'batchCreate'; -$lang->testcase->methodOrder[20] = 'view'; -$lang->testcase->methodOrder[25] = 'edit'; -$lang->testcase->methodOrder[30] = 'delete'; -$lang->testcase->methodOrder[35] = 'export'; -$lang->testcase->methodOrder[40] = 'confirmStoryChange'; - -/* Test task. */ -$lang->resource->testtask = new stdclass(); -$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'; -$lang->resource->testtask->results = 'lblResults'; -$lang->resource->testtask->batchRun = 'batchRun'; - -$lang->testtask->methodOrder[0] = 'index'; -$lang->testtask->methodOrder[5] = 'create'; -$lang->testtask->methodOrder[10] = 'browse'; -$lang->testtask->methodOrder[15] = 'view'; -$lang->testtask->methodOrder[20] = 'cases'; -$lang->testtask->methodOrder[25] = 'edit'; -$lang->testtask->methodOrder[30] = 'delete'; -$lang->testtask->methodOrder[35] = 'batchAssign'; -$lang->testtask->methodOrder[40] = 'linkcase'; -$lang->testtask->methodOrder[45] = 'unlinkcase'; -$lang->testtask->methodOrder[50] = 'runcase'; -$lang->testtask->methodOrder[55] = 'results'; - -/* Doc. */ -$lang->resource->doc = new stdclass(); -$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'; - -$lang->doc->methodOrder[0] = 'index'; -$lang->doc->methodOrder[5] = 'browse'; -$lang->doc->methodOrder[10] = 'createLib'; -$lang->doc->methodOrder[15] = 'editLib'; -$lang->doc->methodOrder[20] = 'deleteLib'; -$lang->doc->methodOrder[25] = 'create'; -$lang->doc->methodOrder[30] = 'view'; -$lang->doc->methodOrder[35] = 'edit'; -$lang->doc->methodOrder[40] = 'delete'; - -/* mail. */ -$lang->resource->mail = new stdclass(); -$lang->resource->mail->index = 'index'; -$lang->resource->mail->detect = 'detect'; -$lang->resource->mail->edit = 'edit'; -$lang->resource->mail->save = 'save'; -$lang->resource->mail->test = 'test'; - -$lang->mail->methodOrder[5] = 'index'; -$lang->mail->methodOrder[10] = 'detect'; -$lang->mail->methodOrder[15] = 'edit'; -$lang->mail->methodOrder[20] = 'save'; -$lang->mail->methodOrder[25] = 'test'; - -/* Subversion. */ -$lang->resource->svn = new stdclass(); -$lang->resource->svn->diff = 'diff'; -$lang->resource->svn->cat = 'cat'; -$lang->resource->svn->apiSync = 'apiSync'; - -$lang->svn->methodOrder[5] = 'diff'; -$lang->svn->methodOrder[10] = 'cat'; -$lang->svn->methodOrder[15] = 'apiSync'; - -/* Company. */ -$lang->resource->company = new stdclass(); -$lang->resource->company->index = 'index'; -$lang->resource->company->browse = 'browse'; -$lang->resource->company->create = 'create'; -$lang->resource->company->edit = 'edit'; -$lang->resource->company->delete = 'delete'; -$lang->resource->company->dynamic= 'dynamic'; - -$lang->company->methodOrder[0] = 'index'; -$lang->company->methodOrder[5] = 'browse'; -$lang->company->methodOrder[10] = 'create'; -$lang->company->methodOrder[15] = 'edit'; -$lang->company->methodOrder[20] = 'delete'; -$lang->company->methodOrder[25] = 'dynamic'; - -/* Department. */ -$lang->resource->dept = new stdclass(); -$lang->resource->dept->browse = 'browse'; -$lang->resource->dept->updateOrder = 'updateOrder'; -$lang->resource->dept->manageChild = 'manageChild'; -$lang->resource->dept->delete = 'delete'; - -$lang->dept->methodOrder[5] = 'browse'; -$lang->dept->methodOrder[10] = 'updateOrder'; -$lang->dept->methodOrder[15] = 'manageChild'; -$lang->dept->methodOrder[20] = 'delete'; - -/* Group. */ -$lang->resource->group = new stdclass(); -$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'; - -$lang->group->methodOrder[5] = 'browse'; -$lang->group->methodOrder[10] = 'create'; -$lang->group->methodOrder[15] = 'edit'; -$lang->group->methodOrder[20] = 'copy'; -$lang->group->methodOrder[25] = 'delete'; -$lang->group->methodOrder[30] = 'managePriv'; -$lang->group->methodOrder[35] = 'manageMember'; - -/* User. */ -$lang->resource->user = new stdclass(); -$lang->resource->user->create = 'create'; -$lang->resource->user->batchCreate = 'batchCreate'; -$lang->resource->user->view = 'view'; -$lang->resource->user->edit = 'edit'; -$lang->resource->user->unlock = 'unlock'; -$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->batchEdit = 'batchEdit'; -$lang->resource->user->manageContacts = 'manageContacts'; -$lang->resource->user->deleteContacts = 'deleteContacts'; - -$lang->user->methodOrder[5] = 'create'; -$lang->user->methodOrder[7] = 'batchCreate'; -$lang->user->methodOrder[10] = 'view'; -$lang->user->methodOrder[15] = 'edit'; -$lang->user->methodOrder[20] = 'unlock'; -$lang->user->methodOrder[25] = 'delete'; -$lang->user->methodOrder[30] = 'todo'; -$lang->user->methodOrder[35] = 'task'; -$lang->user->methodOrder[40] = 'bug'; -$lang->user->methodOrder[45] = 'project'; -$lang->user->methodOrder[50] = 'dynamic'; -$lang->user->methodOrder[55] = 'profile'; -$lang->user->methodOrder[60] = 'batchEdit'; -$lang->user->methodOrder[65] = 'manageContacts'; -$lang->user->methodOrder[70] = 'deleteContacts'; - -/* Tree. */ -$lang->resource->tree = new stdclass(); -$lang->resource->tree->browse = 'browse'; -$lang->resource->tree->updateOrder = 'updateOrder'; -$lang->resource->tree->manageChild = 'manageChild'; -$lang->resource->tree->edit = 'edit'; -$lang->resource->tree->fix = 'fix'; -$lang->resource->tree->delete = 'delete'; - -$lang->tree->methodOrder[5] = 'browse'; -$lang->tree->methodOrder[10] = 'updateOrder'; -$lang->tree->methodOrder[15] = 'manageChild'; -$lang->tree->methodOrder[20] = 'edit'; -$lang->tree->methodOrder[25] = 'delete'; - -/* Report. */ -$lang->resource->report = new stdclass(); -$lang->resource->report->index = 'index'; -$lang->resource->report->projectDeviation = 'projectDeviation'; -$lang->resource->report->productInfo = 'productInfo'; -$lang->resource->report->bugSummary = 'bugSummary'; -$lang->resource->report->bugassign = 'bugAssign'; -$lang->resource->report->workload = 'workload'; - -$lang->report->methodOrder[0] = 'index'; -$lang->report->methodOrder[5] = 'projectDeviation'; -$lang->report->methodOrder[10] = 'productInfo'; -$lang->report->methodOrder[15] = 'bugSummary'; -$lang->report->methodOrder[17] = 'bugSummary'; -$lang->report->methodOrder[20] = 'workload'; - -/* Search. */ -$lang->resource->search = new stdclass(); -$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'; - -$lang->search->methodOrder[5] = 'buildForm'; -$lang->search->methodOrder[10] = 'buildQuery'; -$lang->search->methodOrder[15] = 'saveQuery'; -$lang->search->methodOrder[20] = 'deleteQuery'; -$lang->search->methodOrder[25] = 'select'; - -/* Admin. */ -$lang->resource->admin = new stdclass(); -$lang->resource->admin->index = 'index'; -$lang->resource->admin->checkDB = 'checkDB'; - -$lang->admin->methodOrder[0] = 'index'; -$lang->admin->methodOrder[5] = 'checkDB'; - -/* Extension. */ -$lang->resource->extension = new stdclass(); -$lang->resource->extension->browse = 'browse'; -$lang->resource->extension->obtain = 'obtain'; -$lang->resource->extension->structure = 'structure'; -$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'; - -$lang->extension->methodOrder[5] = 'browse'; -$lang->extension->methodOrder[10] = 'obtain'; -$lang->extension->methodOrder[15] = 'structure'; -$lang->extension->methodOrder[20] = 'install'; -$lang->extension->methodOrder[25] = 'uninstall'; -$lang->extension->methodOrder[30] = 'activate'; -$lang->extension->methodOrder[35] = 'deactivate'; -$lang->extension->methodOrder[40] = 'upload'; -$lang->extension->methodOrder[45] = 'erase'; -$lang->extension->methodOrder[50] = 'upgrade'; - -/* Editor. */ -$lang->resource->editor = new stdclass(); -$lang->resource->editor->index = 'index'; -$lang->resource->editor->extend = 'extend'; -$lang->resource->editor->edit = 'edit'; -$lang->resource->editor->newPage = 'newPage'; -$lang->resource->editor->save = 'save'; -$lang->resource->editor->delete = 'delete'; - -$lang->editor->methodOrder[5] = 'index'; -$lang->editor->methodOrder[10] = 'extend'; -$lang->editor->methodOrder[15] = 'edit'; -$lang->editor->methodOrder[20] = 'newPage'; -$lang->editor->methodOrder[25] = 'save'; -$lang->editor->methodOrder[30] = 'delete'; - -/* Convert. */ -$lang->resource->convert = new stdclass(); -$lang->resource->convert->index = 'index'; -$lang->resource->convert->selectSource = 'selectSource'; -$lang->resource->convert->setConfig = 'setConfig'; -$lang->resource->convert->setBugfree = 'setBugfree'; -$lang->resource->convert->setRedmine = 'setRedmine'; -$lang->resource->convert->checkConfig = 'checkConfig'; -$lang->resource->convert->checkBugFree = 'checkBugFree'; -$lang->resource->convert->checkRedmine = 'checkRedmine'; -$lang->resource->convert->execute = 'execute'; -$lang->resource->convert->convertBugFree = 'convertBugFree'; -$lang->resource->convert->convertRedmine = 'convertRedmine'; - -$lang->convert->methodOrder[5] = 'index'; -$lang->convert->methodOrder[10] = 'selectSource'; -$lang->convert->methodOrder[15] = 'setConfig'; -$lang->convert->methodOrder[20] = 'setBugfree'; -$lang->convert->methodOrder[25] = 'setRedmine'; -$lang->convert->methodOrder[30] = 'checkConfig'; -$lang->convert->methodOrder[35] = 'checkBugFree'; -$lang->convert->methodOrder[40] = 'checkRedmine'; -$lang->convert->methodOrder[45] = 'execute'; -$lang->convert->methodOrder[50] = 'convertBugFree'; -$lang->convert->methodOrder[55] = 'convertRedmine'; - -//$lang->resource->webapp = new stdclass(); -//$lang->resource->webapp->index = 'index'; -//$lang->resource->webapp->obtain = 'obtain'; -//$lang->resource->webapp->create = 'create'; -//$lang->resource->webapp->edit = 'edit'; -//$lang->resource->webapp->install = 'install'; -//$lang->resource->webapp->uninstall = 'uninstall'; - -//$lang->webapp->methodOrder[5] = 'index'; -//$lang->webapp->methodOrder[10] = 'obtain'; -//$lang->webapp->methodOrder[15] = 'create'; -//$lang->webapp->methodOrder[20] = 'edit'; -//$lang->webapp->methodOrder[25] = 'install'; -//$lang->webapp->methodOrder[30] = 'uninstall'; - -/* Others. */ -$lang->resource->api = new stdclass(); -$lang->resource->api->getModel = 'getModel'; - -$lang->api->methodOrder[5] = 'getModel'; - -$lang->resource->file = new stdclass(); -$lang->resource->file->download = 'download'; -$lang->resource->file->edit = 'edit'; -$lang->resource->file->delete = 'delete'; - -$lang->file->methodOrder[5] = 'download'; -$lang->file->methodOrder[10] = 'edit'; -$lang->file->methodOrder[15] = 'delete'; - -$lang->resource->misc = new stdclass(); -$lang->resource->misc->ping = 'ping'; - -$lang->misc->methodOrder[5] = 'ping'; - -$lang->resource->action = new stdclass(); -$lang->resource->action->trash = 'trash'; -$lang->resource->action->undelete = 'undelete'; -$lang->resource->action->hide = 'hide'; - -$lang->action->methodOrder[5] = 'trash'; -$lang->action->methodOrder[10] = 'undelete'; -$lang->action->methodOrder[15] = 'hide'; - -/* 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'][] = 'bug-saveTemplate'; -$lang->changelog['1.2'][] = 'bug-deleteTemplate'; -$lang->changelog['1.2'][] = 'bug-customFields'; -$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'][] = 'file-delete'; - -$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'][] = 'task-assign'; -$lang->changelog['2.4'][] = 'project-testtask'; -$lang->changelog['2.4'][] = 'todo-export'; -$lang->changelog['2.4'][] = 'product-project'; - -$lang->changelog['3.0.beta2'][] = 'extension-structure'; -$lang->changelog['3.0.beta2'][] = 'product-order'; -$lang->changelog['3.0.beta2'][] = 'project-order'; - -$lang->changelog['3.1'][] = 'todo-batchCreate'; - -$lang->changelog['3.2'][] = 'my-changePassword'; -$lang->changelog['3.2'][] = 'story-batchClose'; -$lang->changelog['3.2'][] = 'task-batchEdit'; -$lang->changelog['3.2'][] = 'release-export'; -$lang->changelog['3.2'][] = 'report-index'; -$lang->changelog['3.2'][] = 'report-projectDeviation'; -$lang->changelog['3.2'][] = 'report-productInfo'; -$lang->changelog['3.2'][] = 'report-bugSummary'; -$lang->changelog['3.2'][] = 'report-workload'; -$lang->changelog['3.2'][] = 'tree-fix'; - -$lang->changelog['3.3'][] = 'report-bugAssign'; - -$lang->changelog['4.0.beta2'][] = 'todo-batchEdit'; -$lang->changelog['4.0.beta2'][] = 'story-batchEdit'; -$lang->changelog['4.0.beta2'][] = 'bug-batchEdit'; -$lang->changelog['4.0.beta2'][] = 'testcase-batchEdit'; -$lang->changelog['4.0.beta2'][] = 'testtask-batchRun'; -$lang->changelog['4.0.beta2'][] = 'user-batchEdit'; -$lang->changelog['4.0.beta2'][] = 'user-manageContacts'; -$lang->changelog['4.0.beta2'][] = 'user-deleteContacts'; + + * @package group + * @version $Id$ + * @link http://www.zentao.net + */ + +/* Module order. */ +$lang->moduleOrder[0] = 'index'; +$lang->moduleOrder[5] = 'my'; +$lang->moduleOrder[10] = 'todo'; + +$lang->moduleOrder[15] = 'product'; +$lang->moduleOrder[20] = 'story'; +$lang->moduleOrder[25] = 'productplan'; +$lang->moduleOrder[30] = 'release'; + +$lang->moduleOrder[35] = 'project'; +$lang->moduleOrder[40] = 'task'; +$lang->moduleOrder[45] = 'build'; + +$lang->moduleOrder[50] = 'qa'; +$lang->moduleOrder[55] = 'bug'; +$lang->moduleOrder[60] = 'testcase'; +$lang->moduleOrder[65] = 'testtask'; + +$lang->moduleOrder[70] = 'doc'; +$lang->moduleOrder[75] = 'report'; + +$lang->moduleOrder[80] = 'company'; +$lang->moduleOrder[85] = 'dept'; +$lang->moduleOrder[90] = 'group'; +$lang->moduleOrder[95] = 'user'; + +$lang->moduleOrder[100] = 'admin'; +$lang->moduleOrder[105] = 'extension'; +$lang->moduleOrder[105] = 'extension'; +$lang->moduleOrder[110] = 'editor'; +$lang->moduleOrder[115] = 'convert'; +$lang->moduleOrder[120] = 'action'; + +$lang->moduleOrder[125] = 'mail'; +$lang->moduleOrder[130] = 'svn'; +$lang->moduleOrder[135] = 'search'; +$lang->moduleOrder[140] = 'tree'; +$lang->moduleOrder[145] = 'api'; +$lang->moduleOrder[150] = 'file'; +$lang->moduleOrder[155] = 'misc'; + +$lang->resource = new stdclass(); + +/* Index module. */ +$lang->resource->index = new stdclass(); +$lang->resource->index->index = 'index'; + +$lang->index->methodOrder[0] = 'index'; + +/* My module. */ +$lang->resource->my = new stdclass(); +$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 = 'myProject'; +$lang->resource->my->profile = 'profile'; +$lang->resource->my->dynamic = 'dynamic'; +$lang->resource->my->editProfile = 'editProfile'; +$lang->resource->my->changePassword = 'changePassword'; + +$lang->my->methodOrder[0] = 'index'; +$lang->my->methodOrder[5] = 'todo'; +$lang->my->methodOrder[10] = 'task'; +$lang->my->methodOrder[15] = 'bug'; +$lang->my->methodOrder[20] = 'testTask'; +$lang->my->methodOrder[25] = 'testCase'; +$lang->my->methodOrder[30] = 'story'; +$lang->my->methodOrder[35] = 'project'; +$lang->my->methodOrder[40] = 'profile'; +$lang->my->methodOrder[45] = 'dynamic'; +$lang->my->methodOrder[50] = 'editProfile'; +$lang->my->methodOrder[55] = 'changePassword'; + +/* Todo. */ +$lang->resource->todo = new stdclass(); +$lang->resource->todo->create = 'create'; +$lang->resource->todo->batchCreate = 'batchCreate'; +$lang->resource->todo->edit = 'edit'; +$lang->resource->todo->batchEdit = 'batchEdit'; +$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'; + +$lang->todo->methodOrder[5] = 'create'; +$lang->todo->methodOrder[10] = 'batchCreate'; +$lang->todo->methodOrder[15] = 'edit'; +$lang->todo->methodOrder[20] = 'view'; +$lang->todo->methodOrder[25] = 'delete'; +$lang->todo->methodOrder[30] = 'export'; +$lang->todo->methodOrder[35] = 'mark'; +$lang->todo->methodOrder[40] = 'import2Today'; + +/* Product. */ +$lang->resource->product = new stdclass(); +$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->order = 'order'; +$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->product->methodOrder[0] = 'index'; +$lang->product->methodOrder[5] = 'browse'; +$lang->product->methodOrder[10] = 'create'; +$lang->product->methodOrder[15] = 'view'; +$lang->product->methodOrder[20] = 'edit'; +$lang->product->methodOrder[25] = 'order'; +$lang->product->methodOrder[30] = 'delete'; +$lang->product->methodOrder[35] = 'roadmap'; +$lang->product->methodOrder[40] = 'doc'; +$lang->product->methodOrder[45] = 'dynamic'; +$lang->product->methodOrder[50] = 'project'; + +/* Story. */ +$lang->resource->story = new stdclass(); +$lang->resource->story->create = 'create'; +$lang->resource->story->batchCreate = 'batchCreate'; +$lang->resource->story->edit = 'edit'; +$lang->resource->story->batchEdit = 'batchEdit'; +$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->batchClose = 'batchClose'; +$lang->resource->story->activate = 'lblActivate'; +$lang->resource->story->tasks = 'tasks'; +$lang->resource->story->report = 'reportChart'; + +$lang->story->methodOrder[5] = 'create'; +$lang->story->methodOrder[10] = 'batchCreate'; +$lang->story->methodOrder[15] = 'edit'; +$lang->story->methodOrder[20] = 'export'; +$lang->story->methodOrder[25] = 'delete'; +$lang->story->methodOrder[30] = 'view'; +$lang->story->methodOrder[35] = 'change'; +$lang->story->methodOrder[40] = 'review'; +$lang->story->methodOrder[45] = 'close'; +$lang->story->methodOrder[50] = 'batchClose'; +$lang->story->methodOrder[55] = 'activate'; +$lang->story->methodOrder[60] = 'tasks'; +$lang->story->methodOrder[65] = 'report'; + +/* Product plan. */ +$lang->resource->productplan = new stdclass(); +$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'; + +$lang->productplan->methodOrder[5] = 'browse'; +$lang->productplan->methodOrder[10] = 'create'; +$lang->productplan->methodOrder[15] = 'edit'; +$lang->productplan->methodOrder[20] = 'delete'; +$lang->productplan->methodOrder[25] = 'view'; +$lang->productplan->methodOrder[30] = 'linkStory'; +$lang->productplan->methodOrder[35] = 'unlinkStory'; + +/* Release. */ +$lang->resource->release = new stdclass(); +$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->export = 'export'; + +$lang->release->methodOrder[5] = 'browse'; +$lang->release->methodOrder[10] = 'create'; +$lang->release->methodOrder[15] = 'edit'; +$lang->release->methodOrder[20] = 'delete'; +$lang->release->methodOrder[25] = 'view'; +$lang->release->methodOrder[35] = 'export'; + +/* Project. */ +$lang->resource->project = new stdclass(); +$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->order = 'order'; +$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->project->methodOrder[0] = 'index'; +$lang->project->methodOrder[5] = 'view'; +$lang->project->methodOrder[10] = 'browse'; +$lang->project->methodOrder[15] = 'create'; +$lang->project->methodOrder[20] = 'edit'; +$lang->project->methodOrder[25] = 'order'; +$lang->project->methodOrder[30] = 'delete'; +$lang->project->methodOrder[35] = 'task'; +$lang->project->methodOrder[40] = 'grouptask'; +$lang->project->methodOrder[45] = 'importtask'; +$lang->project->methodOrder[50] = 'importBug'; +$lang->project->methodOrder[55] = 'story'; +$lang->project->methodOrder[60] = 'build'; +$lang->project->methodOrder[65] = 'testtask'; +$lang->project->methodOrder[70] = 'bug'; +$lang->project->methodOrder[75] = 'burn'; +$lang->project->methodOrder[80] = 'computeBurn'; +$lang->project->methodOrder[85] = 'burnData'; +$lang->project->methodOrder[90] = 'team'; +$lang->project->methodOrder[95] = 'doc'; +$lang->project->methodOrder[100] = 'dynamic'; +$lang->project->methodOrder[105] = 'manageProducts'; +$lang->project->methodOrder[110] = 'manageMembers'; +$lang->project->methodOrder[115] = 'unlinkMember'; +$lang->project->methodOrder[120] = 'linkStory'; +$lang->project->methodOrder[125] = 'unlinkStory'; + +/* Task. */ +$lang->resource->task = new stdclass(); +$lang->resource->task->create = 'create'; +$lang->resource->task->batchCreate = 'batchCreate'; +$lang->resource->task->batchEdit = 'batchEdit'; +$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->report = 'reportChart'; + +$lang->task->methodOrder[5] = 'create'; +$lang->task->methodOrder[10] = 'batchCreate'; +$lang->task->methodOrder[15] = 'batchEdit'; +$lang->task->methodOrder[20] = 'edit'; +$lang->task->methodOrder[25] = 'assignTo'; +$lang->task->methodOrder[30] = 'start'; +$lang->task->methodOrder[35] = 'finish'; +$lang->task->methodOrder[40] = 'cancel'; +$lang->task->methodOrder[45] = 'close'; +$lang->task->methodOrder[50] = 'batchClose'; +$lang->task->methodOrder[55] = 'activate'; +$lang->task->methodOrder[60] = 'delete'; +$lang->task->methodOrder[65] = 'view'; +$lang->task->methodOrder[70] = 'export'; +$lang->task->methodOrder[75] = 'confirmStoryChange'; +$lang->task->methodOrder[90] = 'report'; + +/* Build. */ +$lang->resource->build = new stdclass(); +$lang->resource->build->create = 'create'; +$lang->resource->build->edit = 'edit'; +$lang->resource->build->delete = 'delete'; +$lang->resource->build->view = 'view'; + +$lang->build->methodOrder[5] = 'create'; +$lang->build->methodOrder[10] = 'edit'; +$lang->build->methodOrder[15] = 'delete'; +$lang->build->methodOrder[20] = 'view'; + +/* QA. */ +$lang->resource->qa = new stdclass(); +$lang->resource->qa->index = 'index'; + +$lang->qa->methodOrder[0] = 'index'; + +/* Bug. */ +$lang->resource->bug = new stdclass(); +$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->batchEdit = 'batchEdit'; +$lang->resource->bug->assignTo = 'assignTo'; +$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->bug->methodOrder[0] = 'index'; +$lang->bug->methodOrder[5] = 'browse'; +$lang->bug->methodOrder[10] = 'create'; +$lang->bug->methodOrder[15] = 'confirmBug'; +$lang->bug->methodOrder[20] = 'view'; +$lang->bug->methodOrder[25] = 'edit'; +$lang->bug->methodOrder[30] = 'assignTo'; +$lang->bug->methodOrder[35] = 'resolve'; +$lang->bug->methodOrder[40] = 'activate'; +$lang->bug->methodOrder[45] = 'close'; +$lang->bug->methodOrder[50] = 'report'; +$lang->bug->methodOrder[55] = 'export'; +$lang->bug->methodOrder[60] = 'confirmStoryChange'; +$lang->bug->methodOrder[65] = 'delete'; +$lang->bug->methodOrder[70] = 'saveTemplate'; +$lang->bug->methodOrder[75] = 'deleteTemplate'; +$lang->bug->methodOrder[80] = 'customFields'; + +/* Test case. */ +$lang->resource->testcase = new stdclass(); +$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->batchEdit = 'batchEdit'; +$lang->resource->testcase->delete = 'delete'; +$lang->resource->testcase->export = 'export'; +$lang->resource->testcase->confirmStoryChange = 'confirmStoryChange'; + +$lang->testcase->methodOrder[0] = 'index'; +$lang->testcase->methodOrder[5] = 'browse'; +$lang->testcase->methodOrder[10] = 'create'; +$lang->testcase->methodOrder[15] = 'batchCreate'; +$lang->testcase->methodOrder[20] = 'view'; +$lang->testcase->methodOrder[25] = 'edit'; +$lang->testcase->methodOrder[30] = 'delete'; +$lang->testcase->methodOrder[35] = 'export'; +$lang->testcase->methodOrder[40] = 'confirmStoryChange'; + +/* Test task. */ +$lang->resource->testtask = new stdclass(); +$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'; +$lang->resource->testtask->results = 'lblResults'; +$lang->resource->testtask->batchRun = 'batchRun'; + +$lang->testtask->methodOrder[0] = 'index'; +$lang->testtask->methodOrder[5] = 'create'; +$lang->testtask->methodOrder[10] = 'browse'; +$lang->testtask->methodOrder[15] = 'view'; +$lang->testtask->methodOrder[20] = 'cases'; +$lang->testtask->methodOrder[25] = 'edit'; +$lang->testtask->methodOrder[30] = 'delete'; +$lang->testtask->methodOrder[35] = 'batchAssign'; +$lang->testtask->methodOrder[40] = 'linkcase'; +$lang->testtask->methodOrder[45] = 'unlinkcase'; +$lang->testtask->methodOrder[50] = 'runcase'; +$lang->testtask->methodOrder[55] = 'results'; + +/* Doc. */ +$lang->resource->doc = new stdclass(); +$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'; + +$lang->doc->methodOrder[0] = 'index'; +$lang->doc->methodOrder[5] = 'browse'; +$lang->doc->methodOrder[10] = 'createLib'; +$lang->doc->methodOrder[15] = 'editLib'; +$lang->doc->methodOrder[20] = 'deleteLib'; +$lang->doc->methodOrder[25] = 'create'; +$lang->doc->methodOrder[30] = 'view'; +$lang->doc->methodOrder[35] = 'edit'; +$lang->doc->methodOrder[40] = 'delete'; + +/* mail. */ +$lang->resource->mail = new stdclass(); +$lang->resource->mail->index = 'index'; +$lang->resource->mail->detect = 'detect'; +$lang->resource->mail->edit = 'edit'; +$lang->resource->mail->save = 'save'; +$lang->resource->mail->test = 'test'; + +$lang->mail->methodOrder[5] = 'index'; +$lang->mail->methodOrder[10] = 'detect'; +$lang->mail->methodOrder[15] = 'edit'; +$lang->mail->methodOrder[20] = 'save'; +$lang->mail->methodOrder[25] = 'test'; + +/* Subversion. */ +$lang->resource->svn = new stdclass(); +$lang->resource->svn->diff = 'diff'; +$lang->resource->svn->cat = 'cat'; +$lang->resource->svn->apiSync = 'apiSync'; + +$lang->svn->methodOrder[5] = 'diff'; +$lang->svn->methodOrder[10] = 'cat'; +$lang->svn->methodOrder[15] = 'apiSync'; + +/* Company. */ +$lang->resource->company = new stdclass(); +$lang->resource->company->index = 'index'; +$lang->resource->company->browse = 'browse'; +$lang->resource->company->create = 'create'; +$lang->resource->company->edit = 'edit'; +$lang->resource->company->delete = 'delete'; +$lang->resource->company->dynamic= 'dynamic'; + +$lang->company->methodOrder[0] = 'index'; +$lang->company->methodOrder[5] = 'browse'; +$lang->company->methodOrder[10] = 'create'; +$lang->company->methodOrder[15] = 'edit'; +$lang->company->methodOrder[20] = 'delete'; +$lang->company->methodOrder[25] = 'dynamic'; + +/* Department. */ +$lang->resource->dept = new stdclass(); +$lang->resource->dept->browse = 'browse'; +$lang->resource->dept->updateOrder = 'updateOrder'; +$lang->resource->dept->manageChild = 'manageChild'; +$lang->resource->dept->delete = 'delete'; + +$lang->dept->methodOrder[5] = 'browse'; +$lang->dept->methodOrder[10] = 'updateOrder'; +$lang->dept->methodOrder[15] = 'manageChild'; +$lang->dept->methodOrder[20] = 'delete'; + +/* Group. */ +$lang->resource->group = new stdclass(); +$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'; + +$lang->group->methodOrder[5] = 'browse'; +$lang->group->methodOrder[10] = 'create'; +$lang->group->methodOrder[15] = 'edit'; +$lang->group->methodOrder[20] = 'copy'; +$lang->group->methodOrder[25] = 'delete'; +$lang->group->methodOrder[30] = 'managePriv'; +$lang->group->methodOrder[35] = 'manageMember'; + +/* User. */ +$lang->resource->user = new stdclass(); +$lang->resource->user->create = 'create'; +$lang->resource->user->batchCreate = 'batchCreate'; +$lang->resource->user->view = 'view'; +$lang->resource->user->edit = 'edit'; +$lang->resource->user->unlock = 'unlock'; +$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->batchEdit = 'batchEdit'; +$lang->resource->user->manageContacts = 'manageContacts'; +$lang->resource->user->deleteContacts = 'deleteContacts'; + +$lang->user->methodOrder[5] = 'create'; +$lang->user->methodOrder[7] = 'batchCreate'; +$lang->user->methodOrder[10] = 'view'; +$lang->user->methodOrder[15] = 'edit'; +$lang->user->methodOrder[20] = 'unlock'; +$lang->user->methodOrder[25] = 'delete'; +$lang->user->methodOrder[30] = 'todo'; +$lang->user->methodOrder[35] = 'task'; +$lang->user->methodOrder[40] = 'bug'; +$lang->user->methodOrder[45] = 'project'; +$lang->user->methodOrder[50] = 'dynamic'; +$lang->user->methodOrder[55] = 'profile'; +$lang->user->methodOrder[60] = 'batchEdit'; +$lang->user->methodOrder[65] = 'manageContacts'; +$lang->user->methodOrder[70] = 'deleteContacts'; + +/* Tree. */ +$lang->resource->tree = new stdclass(); +$lang->resource->tree->browse = 'browse'; +$lang->resource->tree->updateOrder = 'updateOrder'; +$lang->resource->tree->manageChild = 'manageChild'; +$lang->resource->tree->edit = 'edit'; +$lang->resource->tree->fix = 'fix'; +$lang->resource->tree->delete = 'delete'; + +$lang->tree->methodOrder[5] = 'browse'; +$lang->tree->methodOrder[10] = 'updateOrder'; +$lang->tree->methodOrder[15] = 'manageChild'; +$lang->tree->methodOrder[20] = 'edit'; +$lang->tree->methodOrder[25] = 'delete'; + +/* Report. */ +$lang->resource->report = new stdclass(); +$lang->resource->report->index = 'index'; +$lang->resource->report->projectDeviation = 'projectDeviation'; +$lang->resource->report->productInfo = 'productInfo'; +$lang->resource->report->bugSummary = 'bugSummary'; +$lang->resource->report->bugassign = 'bugAssign'; +$lang->resource->report->workload = 'workload'; + +$lang->report->methodOrder[0] = 'index'; +$lang->report->methodOrder[5] = 'projectDeviation'; +$lang->report->methodOrder[10] = 'productInfo'; +$lang->report->methodOrder[15] = 'bugSummary'; +$lang->report->methodOrder[17] = 'bugSummary'; +$lang->report->methodOrder[20] = 'workload'; + +/* Search. */ +$lang->resource->search = new stdclass(); +$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'; + +$lang->search->methodOrder[5] = 'buildForm'; +$lang->search->methodOrder[10] = 'buildQuery'; +$lang->search->methodOrder[15] = 'saveQuery'; +$lang->search->methodOrder[20] = 'deleteQuery'; +$lang->search->methodOrder[25] = 'select'; + +/* Admin. */ +$lang->resource->admin = new stdclass(); +$lang->resource->admin->index = 'index'; +$lang->resource->admin->checkDB = 'checkDB'; + +$lang->admin->methodOrder[0] = 'index'; +$lang->admin->methodOrder[5] = 'checkDB'; + +/* Extension. */ +$lang->resource->extension = new stdclass(); +$lang->resource->extension->browse = 'browse'; +$lang->resource->extension->obtain = 'obtain'; +$lang->resource->extension->structure = 'structure'; +$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'; + +$lang->extension->methodOrder[5] = 'browse'; +$lang->extension->methodOrder[10] = 'obtain'; +$lang->extension->methodOrder[15] = 'structure'; +$lang->extension->methodOrder[20] = 'install'; +$lang->extension->methodOrder[25] = 'uninstall'; +$lang->extension->methodOrder[30] = 'activate'; +$lang->extension->methodOrder[35] = 'deactivate'; +$lang->extension->methodOrder[40] = 'upload'; +$lang->extension->methodOrder[45] = 'erase'; +$lang->extension->methodOrder[50] = 'upgrade'; + +/* Editor. */ +$lang->resource->editor = new stdclass(); +$lang->resource->editor->index = 'index'; +$lang->resource->editor->extend = 'extend'; +$lang->resource->editor->edit = 'edit'; +$lang->resource->editor->newPage = 'newPage'; +$lang->resource->editor->save = 'save'; +$lang->resource->editor->delete = 'delete'; + +$lang->editor->methodOrder[5] = 'index'; +$lang->editor->methodOrder[10] = 'extend'; +$lang->editor->methodOrder[15] = 'edit'; +$lang->editor->methodOrder[20] = 'newPage'; +$lang->editor->methodOrder[25] = 'save'; +$lang->editor->methodOrder[30] = 'delete'; + +/* Convert. */ +$lang->resource->convert = new stdclass(); +$lang->resource->convert->index = 'index'; +$lang->resource->convert->selectSource = 'selectSource'; +$lang->resource->convert->setConfig = 'setConfig'; +$lang->resource->convert->setBugfree = 'setBugfree'; +$lang->resource->convert->setRedmine = 'setRedmine'; +$lang->resource->convert->checkConfig = 'checkConfig'; +$lang->resource->convert->checkBugFree = 'checkBugFree'; +$lang->resource->convert->checkRedmine = 'checkRedmine'; +$lang->resource->convert->execute = 'execute'; +$lang->resource->convert->convertBugFree = 'convertBugFree'; +$lang->resource->convert->convertRedmine = 'convertRedmine'; + +$lang->convert->methodOrder[5] = 'index'; +$lang->convert->methodOrder[10] = 'selectSource'; +$lang->convert->methodOrder[15] = 'setConfig'; +$lang->convert->methodOrder[20] = 'setBugfree'; +$lang->convert->methodOrder[25] = 'setRedmine'; +$lang->convert->methodOrder[30] = 'checkConfig'; +$lang->convert->methodOrder[35] = 'checkBugFree'; +$lang->convert->methodOrder[40] = 'checkRedmine'; +$lang->convert->methodOrder[45] = 'execute'; +$lang->convert->methodOrder[50] = 'convertBugFree'; +$lang->convert->methodOrder[55] = 'convertRedmine'; + +//$lang->resource->webapp = new stdclass(); +//$lang->resource->webapp->index = 'index'; +//$lang->resource->webapp->obtain = 'obtain'; +//$lang->resource->webapp->create = 'create'; +//$lang->resource->webapp->edit = 'edit'; +//$lang->resource->webapp->install = 'install'; +//$lang->resource->webapp->uninstall = 'uninstall'; + +//$lang->webapp->methodOrder[5] = 'index'; +//$lang->webapp->methodOrder[10] = 'obtain'; +//$lang->webapp->methodOrder[15] = 'create'; +//$lang->webapp->methodOrder[20] = 'edit'; +//$lang->webapp->methodOrder[25] = 'install'; +//$lang->webapp->methodOrder[30] = 'uninstall'; + +/* Others. */ +$lang->resource->api = new stdclass(); +$lang->resource->api->getModel = 'getModel'; + +$lang->api->methodOrder[5] = 'getModel'; + +$lang->resource->file = new stdclass(); +$lang->resource->file->download = 'download'; +$lang->resource->file->edit = 'edit'; +$lang->resource->file->delete = 'delete'; + +$lang->file->methodOrder[5] = 'download'; +$lang->file->methodOrder[10] = 'edit'; +$lang->file->methodOrder[15] = 'delete'; + +$lang->resource->misc = new stdclass(); +$lang->resource->misc->ping = 'ping'; + +$lang->misc->methodOrder[5] = 'ping'; + +$lang->resource->action = new stdclass(); +$lang->resource->action->trash = 'trash'; +$lang->resource->action->undelete = 'undelete'; +$lang->resource->action->hide = 'hide'; + +$lang->action->methodOrder[5] = 'trash'; +$lang->action->methodOrder[10] = 'undelete'; +$lang->action->methodOrder[15] = 'hide'; + +/* 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'][] = 'bug-saveTemplate'; +$lang->changelog['1.2'][] = 'bug-deleteTemplate'; +$lang->changelog['1.2'][] = 'bug-customFields'; +$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'][] = 'file-delete'; + +$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'][] = 'task-assign'; +$lang->changelog['2.4'][] = 'project-testtask'; +$lang->changelog['2.4'][] = 'todo-export'; +$lang->changelog['2.4'][] = 'product-project'; + +$lang->changelog['3.0.beta2'][] = 'extension-structure'; +$lang->changelog['3.0.beta2'][] = 'product-order'; +$lang->changelog['3.0.beta2'][] = 'project-order'; + +$lang->changelog['3.1'][] = 'todo-batchCreate'; + +$lang->changelog['3.2'][] = 'my-changePassword'; +$lang->changelog['3.2'][] = 'story-batchClose'; +$lang->changelog['3.2'][] = 'task-batchEdit'; +$lang->changelog['3.2'][] = 'release-export'; +$lang->changelog['3.2'][] = 'report-index'; +$lang->changelog['3.2'][] = 'report-projectDeviation'; +$lang->changelog['3.2'][] = 'report-productInfo'; +$lang->changelog['3.2'][] = 'report-bugSummary'; +$lang->changelog['3.2'][] = 'report-workload'; +$lang->changelog['3.2'][] = 'tree-fix'; + +$lang->changelog['3.3'][] = 'report-bugAssign'; + +$lang->changelog['4.0.beta2'][] = 'todo-batchEdit'; +$lang->changelog['4.0.beta2'][] = 'story-batchEdit'; +$lang->changelog['4.0.beta2'][] = 'bug-batchEdit'; +$lang->changelog['4.0.beta2'][] = 'testcase-batchEdit'; +$lang->changelog['4.0.beta2'][] = 'testtask-batchRun'; +$lang->changelog['4.0.beta2'][] = 'user-batchEdit'; +$lang->changelog['4.0.beta2'][] = 'user-manageContacts'; +$lang->changelog['4.0.beta2'][] = 'user-deleteContacts'; diff --git a/module/group/lang/zh-cn.php b/module/group/lang/zh-cn.php index b06fcc77b1..ee782fedf2 100644 --- a/module/group/lang/zh-cn.php +++ b/module/group/lang/zh-cn.php @@ -1,64 +1,64 @@ - - * @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->option = '选项'; -$lang->group->inside = '组内用户'; -$lang->group->outside = '组外用户'; -$lang->group->other = '其他模块'; -$lang->group->all = '所有权限'; - -$lang->group->copyOptions['copyPriv'] = '复制权限'; -$lang->group->copyOptions['copyUser'] = '复制用户'; - -$lang->group->versions[''] = '版本至今的权限'; -$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2'; -$lang->group->versions['3_3'] = '禅道3.3'; -$lang->group->versions['3_2_1'] = '禅道3.2.1'; -$lang->group->versions['3_2'] = '禅道3.2'; -$lang->group->versions['3_1'] = '禅道3.1'; -$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2'; -$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->option = '选项'; +$lang->group->inside = '组内用户'; +$lang->group->outside = '组外用户'; +$lang->group->other = '其他模块'; +$lang->group->all = '所有权限'; + +$lang->group->copyOptions['copyPriv'] = '复制权限'; +$lang->group->copyOptions['copyUser'] = '复制用户'; + +$lang->group->versions[''] = '版本至今的权限'; +$lang->group->versions['4_0_beta2'] = '禅道4.0.beta2'; +$lang->group->versions['3_3'] = '禅道3.3'; +$lang->group->versions['3_2_1'] = '禅道3.2.1'; +$lang->group->versions['3_2'] = '禅道3.2'; +$lang->group->versions['3_1'] = '禅道3.1'; +$lang->group->versions['3_0_beta2'] = '禅道3.0.beta2'; +$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 d09c30a136..6ede41b829 100644 --- a/module/group/lang/zh-tw.php +++ b/module/group/lang/zh-tw.php @@ -1,61 +1,61 @@ - - * @package group - * @version $Id: zh-tw.php 3507 2012-09-03 00:58:51Z shiyangyangwork@yahoo.cn $ - * @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->option = '選項'; -$lang->group->inside = '組內用戶'; -$lang->group->outside = '組外用戶'; - -$lang->group->copyOptions['copyPriv'] = '複製權限'; -$lang->group->copyOptions['copyUser'] = '複製用戶'; - -$lang->group->versions[''] = '顯示各版本新增權限'; -$lang->group->versions['3.3'] = '禪道3.3'; -$lang->group->versions['3.2.1'] = '禪道3.2.1'; -$lang->group->versions['3.2'] = '禪道3.2'; -$lang->group->versions['3.1'] = '禪道3.1'; -$lang->group->versions['3.0.beta2'] = '禪道3.0.beta2'; -$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 3507 2012-09-03 00:58:51Z shiyangyangwork@yahoo.cn $ + * @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->option = '選項'; +$lang->group->inside = '組內用戶'; +$lang->group->outside = '組外用戶'; + +$lang->group->copyOptions['copyPriv'] = '複製權限'; +$lang->group->copyOptions['copyUser'] = '複製用戶'; + +$lang->group->versions[''] = '顯示各版本新增權限'; +$lang->group->versions['3.3'] = '禪道3.3'; +$lang->group->versions['3.2.1'] = '禪道3.2.1'; +$lang->group->versions['3.2'] = '禪道3.2'; +$lang->group->versions['3.1'] = '禪道3.1'; +$lang->group->versions['3.0.beta2'] = '禪道3.0.beta2'; +$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 de685746b5..b001ef6cf0 100644 --- a/module/group/model.php +++ b/module/group/model.php @@ -1,373 +1,373 @@ - - * @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 public - * @return void - */ - public 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 public - * @return void - */ - public 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)->orderBy('id')->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, $menu, $version) - { - /* Set priv when have version. */ - if($version) - { - $noCheckeds = trim($this->post->noChecked, ','); - if($noCheckeds) - { - $noCheckeds = explode(',', $noCheckeds); - foreach($noCheckeds as $noChecked) - { - /* Delete no checked priv*/ - list($module, $method) = explode('-', $noChecked); - $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->andWhere('module')->eq($module)->andWhere('method')->eq($method)->exec(); - } - } - - /* Replace new. */ - if($this->post->actions) - { - foreach($this->post->actions as $moduleName => $moduleActions) - { - foreach($moduleActions as $actionName) - { - $data->group = $groupID; - $data->module = $moduleName; - $data->method = $actionName; - $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); - } - } - } - return true; - } - - /* Delete old. */ - $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->andWhere('module')->in($this->getMenuModules($menu))->exec(); - - /* Insert new. */ - if($this->post->actions) - { - 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(); - } - } - - /** - * Sort resource. - * - * @access public - * @return void - */ - public function sortResource() - { - $resources = $this->lang->resource; - $this->lang->resource = new stdclass(); - - /* sort moduleOrder. */ - ksort($this->lang->moduleOrder, SORT_ASC); - foreach($this->lang->moduleOrder as $moduleName) - { - $resource = $resources->$moduleName; - unset($resources->$moduleName); - $this->lang->resource->$moduleName = $resource; - } - foreach($resources as $key => $resource) - { - $this->lang->resource->$key = $resource; - } - - /* sort methodOrder. */ - foreach($this->lang->resource as $moduleName => $resources) - { - $resources = (array)$resources; - $tmpResources = new stdclass(); - - if(isset($this->lang->$moduleName->methodOrder)) - { - ksort($this->lang->$moduleName->methodOrder, SORT_ASC); - foreach($this->lang->$moduleName->methodOrder as $key) - { - if(isset($resources[$key])) - { - $tmpResources->$key = $resources[$key]; - unset($resources[$key]); - } - } - if($resources) - { - foreach($resources as $key => $resource) - { - $tmpResources->$key = $resource; - } - } - $this->lang->resource->$moduleName = $tmpResources; - unset($tmpResources); - } - } - } - - /** - * Check menu have module - * - * @param string $menu - * @param string $moduleName - * @access public - * @return void - */ - public function checkMenuModule($menu, $moduleName) - { - if(empty($menu)) return true; - if($menu == 'other' and (isset($this->lang->menugroup->$moduleName) or isset($this->lang->menu->$moduleName))) return false; - if($menu != 'other' and !($moduleName == $menu or (isset($this->lang->menugroup->$moduleName) and $this->lang->menugroup->$moduleName == $menu))) return false; - return true; - } - - /** - * Get modules in menu - * - * @param string $menu - * @access public - * @return void - */ - public function getMenuModules($menu) - { - $modules = array(); - foreach($this->lang->resource as $moduleName => $action) - { - if($this->checkMenuModule($menu, $moduleName)) $modules[] = $moduleName; - } - return $modules; - } -} + + * @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 public + * @return void + */ + public 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 public + * @return void + */ + public 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)->orderBy('id')->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, $menu, $version) + { + /* Set priv when have version. */ + if($version) + { + $noCheckeds = trim($this->post->noChecked, ','); + if($noCheckeds) + { + $noCheckeds = explode(',', $noCheckeds); + foreach($noCheckeds as $noChecked) + { + /* Delete no checked priv*/ + list($module, $method) = explode('-', $noChecked); + $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->andWhere('module')->eq($module)->andWhere('method')->eq($method)->exec(); + } + } + + /* Replace new. */ + if($this->post->actions) + { + foreach($this->post->actions as $moduleName => $moduleActions) + { + foreach($moduleActions as $actionName) + { + $data->group = $groupID; + $data->module = $moduleName; + $data->method = $actionName; + $this->dao->replace(TABLE_GROUPPRIV)->data($data)->exec(); + } + } + } + return true; + } + + /* Delete old. */ + $this->dao->delete()->from(TABLE_GROUPPRIV)->where('`group`')->eq($groupID)->andWhere('module')->in($this->getMenuModules($menu))->exec(); + + /* Insert new. */ + if($this->post->actions) + { + 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(); + } + } + + /** + * Sort resource. + * + * @access public + * @return void + */ + public function sortResource() + { + $resources = $this->lang->resource; + $this->lang->resource = new stdclass(); + + /* sort moduleOrder. */ + ksort($this->lang->moduleOrder, SORT_ASC); + foreach($this->lang->moduleOrder as $moduleName) + { + $resource = $resources->$moduleName; + unset($resources->$moduleName); + $this->lang->resource->$moduleName = $resource; + } + foreach($resources as $key => $resource) + { + $this->lang->resource->$key = $resource; + } + + /* sort methodOrder. */ + foreach($this->lang->resource as $moduleName => $resources) + { + $resources = (array)$resources; + $tmpResources = new stdclass(); + + if(isset($this->lang->$moduleName->methodOrder)) + { + ksort($this->lang->$moduleName->methodOrder, SORT_ASC); + foreach($this->lang->$moduleName->methodOrder as $key) + { + if(isset($resources[$key])) + { + $tmpResources->$key = $resources[$key]; + unset($resources[$key]); + } + } + if($resources) + { + foreach($resources as $key => $resource) + { + $tmpResources->$key = $resource; + } + } + $this->lang->resource->$moduleName = $tmpResources; + unset($tmpResources); + } + } + } + + /** + * Check menu have module + * + * @param string $menu + * @param string $moduleName + * @access public + * @return void + */ + public function checkMenuModule($menu, $moduleName) + { + if(empty($menu)) return true; + if($menu == 'other' and (isset($this->lang->menugroup->$moduleName) or isset($this->lang->menu->$moduleName))) return false; + if($menu != 'other' and !($moduleName == $menu or (isset($this->lang->menugroup->$moduleName) and $this->lang->menugroup->$moduleName == $menu))) return false; + return true; + } + + /** + * Get modules in menu + * + * @param string $menu + * @access public + * @return void + */ + public function getMenuModules($menu) + { + $modules = array(); + foreach($this->lang->resource as $moduleName => $action) + { + if($this->checkMenuModule($menu, $moduleName)) $modules[] = $moduleName; + } + return $modules; + } +} diff --git a/module/group/view/browse.html.php b/module/group/view/browse.html.php index 219c5e2524..da14695915 100644 --- a/module/group/view/browse.html.php +++ b/module/group/view/browse.html.php @@ -1,48 +1,48 @@ - - * @package group - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          group->browse;?>
          -
          group->create);?>
          -
          group->id;?>group->name;?>group->desc;?>actions;?>
          id;?>name;?>desc;?> - id", $lang->group->managePrivByGroup);?> - id", $lang->group->manageMember);?> - id", '', 'list');?> - id", '', 'list');?> - id", '', 'list', '', "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;?>actions;?>
          id;?>name;?>desc;?> + id", $lang->group->managePrivByGroup);?> + id", $lang->group->manageMember);?> + id", '', 'list');?> + id", '', 'list');?> + id", '', 'list', '', "hiddenwin");?> +
          group->managePrivByModule, inlink('managePriv', 'type=byModule'));?>
          + diff --git a/module/group/view/copy.html.php b/module/group/view/copy.html.php index 7d1d5d03d4..2b4e14a6ab 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 3d14ff2985..de4ff205ea 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 24863ff047..6da3725404 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 cd19f7cede..47988f3cf9 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 057cc326bb..77c881363f 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 - */ -?> -
          -
          - menu as $module => $title):?> - > - - - - >group->other)?> - >group->all)?> - lang->group->versions, $version, "onchange=showPriv(this.value)");?> -
          - - - - - - resource as $moduleName => $moduleActions):?> - group->checkMenuModule($menu, $moduleName)) continue;?> - $actionLabel) - { - if(strpos($changelogs, ",$moduleName-$actionLabel,") !== false) - { - $hasMethod = true; - break; - } - } - if(!$hasMethod) continue; - } - ?> - '> - - - - - - - -
          group->module;?>group->method;?>
          lang->$moduleName->common;?> - - - $actionLabel):?> - -
          - /> - $moduleName->$actionLabel;?> -
          - "; $i ++;?> - -
          selectAll . html::selectAll('', 'checkbox')?> - save, "onclick='setNoChecked()'"); - echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); - echo html::hidden('foo'); // Just a hidden var, to make sure $_POST is not empty. - echo html::hidden('noChecked'); // Save the value of no checked. - ?> -
          -
          - + + * @package group + * @version $Id: managepriv.html.php 1517 2011-03-07 10:02:57Z wwccss $ + * @link http://www.zentao.net + */ +?> +
          +
          + menu as $module => $title):?> + > + + + + >group->other)?> + >group->all)?> + lang->group->versions, $version, "onchange=showPriv(this.value)");?> +
          + + + + + + resource as $moduleName => $moduleActions):?> + group->checkMenuModule($menu, $moduleName)) continue;?> + $actionLabel) + { + if(strpos($changelogs, ",$moduleName-$actionLabel,") !== false) + { + $hasMethod = true; + break; + } + } + if(!$hasMethod) continue; + } + ?> + '> + + + + + + + +
          group->module;?>group->method;?>
          lang->$moduleName->common;?> + + + $actionLabel):?> + +
          + /> + $moduleName->$actionLabel;?> +
          + "; $i ++;?> + +
          selectAll . html::selectAll('', 'checkbox')?> + save, "onclick='setNoChecked()'"); + echo html::linkButton($lang->goback, $this->createLink('group', 'browse')); + echo html::hidden('foo'); // Just a hidden var, to make sure $_POST is not empty. + echo html::hidden('noChecked'); // Save the value of no checked. + ?> +
          +
          + diff --git a/module/group/view/privbymodule.html.php b/module/group/view/privbymodule.html.php index 87de1d036c..8a2ba39d13 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 2b25a20c30..5410d265d2 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 8947a3c3b1..4949e0585c 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 c54f51fdf2..195a1264d2 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($type='') - { - if(empty($type))$this->locate($this->createLink('my', 'index')); - - if($_POST) - { - $this->loadModel('setting')->setItem('system.common.global.flow', $this->post->flow); - if($this->post->flow != 'full') die(js::locate($this->createLink('extension', 'install', "extension={$this->config->index->flow2Ext[$this->post->flow]}"), 'parent')); - die(js::reload( 'parent.parent')); - } - $this->display(); - } - - /** - * 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($type='') + { + if(empty($type))$this->locate($this->createLink('my', 'index')); + + if($_POST) + { + $this->loadModel('setting')->setItem('system.common.global.flow', $this->post->flow); + if($this->post->flow != 'full') die(js::locate($this->createLink('extension', 'install', "extension={$this->config->index->flow2Ext[$this->post->flow]}"), 'parent')); + die(js::reload( 'parent.parent')); + } + $this->display(); + } + + /** + * 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 2afcac9a23..4389f274c5 100644 --- a/module/index/model.php +++ b/module/index/model.php @@ -1,15 +1,15 @@ - - * @package index - * @version $Id$ - */ -?> - + * @package index + * @version $Id$ + */ +?> + - * @package index - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - -
          index->selectFlow?>
          - index->flowList as $type => $name) - { - $checked = $type == 'full' ? "checked='checked'" : ''; - echo "

          $name

          "; - } - ?> -
          {$lang->index->flowNotice}

          "?>
          -
          - - + + * @package index + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + +
          index->selectFlow?>
          + index->flowList as $type => $name) + { + $checked = $type == 'full' ? "checked='checked'" : ''; + echo "

          $name

          "; + } + ?> +
          {$lang->index->flowNotice}

          "?>
          +
          + + diff --git a/module/install/control.php b/module/install/control.php index a5212c0354..52430e55bd 100644 --- a/module/install/control.php +++ b/module/install/control.php @@ -1,163 +1,163 @@ - - * @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->app->loadLang('user'); - $this->app->loadLang('admin'); - $this->config->webRoot = 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->sessionResult = $this->install->checkSessionSavePath(); - $this->view->sessionInfo = $this->install->getSessionSavePath(); - $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 = new stdclass(); - $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())); - - if($this->post->importDemoData) $this->install->importDemoData(); - if(dao::isError()) echo js::alert($this->lang->install->errorImportDemoData); - - $this->loadModel('setting')->updateVersion($this->config->version); - $this->setting->setSN(); - die(js::locate(inlink('step5'), '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(); - } - } - - /** - * Join zentao community or login pms. - * - * @access public - * @return void - */ - public function step5() - { - $this->display(); - unset($_SESSION['installing']); - session_destroy(); - } -} + + * @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->app->loadLang('user'); + $this->app->loadLang('admin'); + $this->config->webRoot = 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->sessionResult = $this->install->checkSessionSavePath(); + $this->view->sessionInfo = $this->install->getSessionSavePath(); + $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 = new stdclass(); + $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())); + + if($this->post->importDemoData) $this->install->importDemoData(); + if(dao::isError()) echo js::alert($this->lang->install->errorImportDemoData); + + $this->loadModel('setting')->updateVersion($this->config->version); + $this->setting->setSN(); + die(js::locate(inlink('step5'), '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(); + } + } + + /** + * Join zentao community or login pms. + * + * @access public + * @return void + */ + public function step5() + { + $this->display(); + unset($_SESSION['installing']); + session_destroy(); + } +} diff --git a/module/install/lang/en.php b/module/install/lang/en.php index 7433440b42..f2e625d099 100644 --- a/module/install/lang/en.php +++ b/module/install/lang/en.php @@ -1,137 +1,137 @@ - - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->install = new stdclass(); - -$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->session = 'Session save path'; -$lang->install->sessionFail = 'Edit the php.ini file to set session.save_path'; -$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->importDemoData = 'Import demo 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->errorTableExists = 'The same tables alread exists, to continue install, go back and check the clear db box.'; -$lang->install->errorCreateTable = 'Table create failed.'; -$lang->install->errorImportDemoData = 'Import demo data.'; - -$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->groupList['ADMIN']['name'] = 'Administrator'; -$lang->install->groupList['ADMIN']['desc'] = 'for administrator'; -$lang->install->groupList['DEV']['name'] = 'Developer'; -$lang->install->groupList['DEV']['desc'] = 'for developers'; -$lang->install->groupList['QA']['name'] = 'tester'; -$lang->install->groupList['QA']['desc'] = 'for testers'; -$lang->install->groupList['PM']['name'] = 'Project manager'; -$lang->install->groupList['PM']['desc'] = 'for project managers'; -$lang->install->groupList['PO']['name'] = 'Product manager'; -$lang->install->groupList['PO']['desc'] = 'for product managers'; -$lang->install->groupList['TD']['name'] = 'Technical director'; -$lang->install->groupList['TD']['desc'] = 'for technical director'; -$lang->install->groupList['PD']['name'] = 'Product director'; -$lang->install->groupList['PD']['desc'] = 'for product director'; -$lang->install->groupList['QD']['name'] = 'Quality director'; -$lang->install->groupList['QD']['desc'] = 'for quality director'; -$lang->install->groupList['TOP']['name'] = 'Top manager'; -$lang->install->groupList['TOP']['desc'] = 'for top manager'; -$lang->install->groupList['OTHERS']['name'] = 'Others'; -$lang->install->groupList['OTHERS']['desc'] = 'for others'; - -$lang->install->success = "Success installed"; - -$lang->install->joinZentao = <<Please remove install.php in time。Now you can login ZenTaoPMS, create groups and grant priviledges. -Tips: For you get zentao news in time, please register Zetao community(www.zentao.net). -EOT; + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->install = new stdclass(); + +$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->session = 'Session save path'; +$lang->install->sessionFail = 'Edit the php.ini file to set session.save_path'; +$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->importDemoData = 'Import demo 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->errorTableExists = 'The same tables alread exists, to continue install, go back and check the clear db box.'; +$lang->install->errorCreateTable = 'Table create failed.'; +$lang->install->errorImportDemoData = 'Import demo data.'; + +$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->groupList['ADMIN']['name'] = 'Administrator'; +$lang->install->groupList['ADMIN']['desc'] = 'for administrator'; +$lang->install->groupList['DEV']['name'] = 'Developer'; +$lang->install->groupList['DEV']['desc'] = 'for developers'; +$lang->install->groupList['QA']['name'] = 'tester'; +$lang->install->groupList['QA']['desc'] = 'for testers'; +$lang->install->groupList['PM']['name'] = 'Project manager'; +$lang->install->groupList['PM']['desc'] = 'for project managers'; +$lang->install->groupList['PO']['name'] = 'Product manager'; +$lang->install->groupList['PO']['desc'] = 'for product managers'; +$lang->install->groupList['TD']['name'] = 'Technical director'; +$lang->install->groupList['TD']['desc'] = 'for technical director'; +$lang->install->groupList['PD']['name'] = 'Product director'; +$lang->install->groupList['PD']['desc'] = 'for product director'; +$lang->install->groupList['QD']['name'] = 'Quality director'; +$lang->install->groupList['QD']['desc'] = 'for quality director'; +$lang->install->groupList['TOP']['name'] = 'Top manager'; +$lang->install->groupList['TOP']['desc'] = 'for top manager'; +$lang->install->groupList['OTHERS']['name'] = 'Others'; +$lang->install->groupList['OTHERS']['desc'] = 'for others'; + +$lang->install->success = "Success installed"; + +$lang->install->joinZentao = <<Please remove install.php in time。Now you can login ZenTaoPMS, create groups and grant priviledges. +Tips: For you get zentao news in time, please register Zetao community(www.zentao.net). +EOT; diff --git a/module/install/lang/zh-cn.php b/module/install/lang/zh-cn.php index 98388232cc..45675abda2 100644 --- a/module/install/lang/zh-cn.php +++ b/module/install/lang/zh-cn.php @@ -1,137 +1,137 @@ - - * @package install - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->install = new stdclass(); - -$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->session = 'Session存储目录'; -$lang->install->sessionFail = '修改PHP配置文件,设置session.save_path'; -$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->importDemoData = '导入demo数据'; - -$lang->install->requestTypes['GET'] = '普通方式'; -$lang->install->requestTypes['PATH_INFO'] = '静态友好方式'; - -$lang->install->errorConnectDB = '数据库连接失败 '; -$lang->install->errorCreateDB = '数据库创建失败'; -$lang->install->errorTableExists = '数据表已经存在,您之前应该有安装过禅道,继续安装请返回前页并选择清空数据'; -$lang->install->errorCreateTable = '创建表失败'; -$lang->install->errorImportDemoData = '导入demo数据失败'; - -$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->groupList['ADMIN']['name'] = '管理员'; -$lang->install->groupList['ADMIN']['desc'] = '系统管理员'; -$lang->install->groupList['DEV']['name'] = '研发'; -$lang->install->groupList['DEV']['desc'] = '研发人员'; -$lang->install->groupList['QA']['name'] = '测试'; -$lang->install->groupList['QA']['desc'] = '测试人员'; -$lang->install->groupList['PM']['name'] = '项目经理'; -$lang->install->groupList['PM']['desc'] = '项目经理'; -$lang->install->groupList['PO']['name'] = '产品经理'; -$lang->install->groupList['PO']['desc'] = '产品经理'; -$lang->install->groupList['TD']['name'] = '研发主管'; -$lang->install->groupList['TD']['desc'] = '研发主管'; -$lang->install->groupList['PD']['name'] = '产品主管'; -$lang->install->groupList['PD']['desc'] = '产品主管'; -$lang->install->groupList['QD']['name'] = '测试主管'; -$lang->install->groupList['QD']['desc'] = '测试主管'; -$lang->install->groupList['TOP']['name'] = '高层管理'; -$lang->install->groupList['TOP']['desc'] = '高层管理'; -$lang->install->groupList['OTHERS']['name'] = '其他'; -$lang->install->groupList['OTHERS']['desc'] = '其他'; - -$lang->install->success = "安装成功"; - -$lang->install->joinZentao = <<请及时删除install.php。现在您可以直接,设置用户及分组! -友情提示:为了您及时获得禅道的最新动态,请在禅道社区(www.zentao.net)进行登记。 -EOT; + + * @package install + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->install = new stdclass(); + +$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->session = 'Session存储目录'; +$lang->install->sessionFail = '修改PHP配置文件,设置session.save_path'; +$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->importDemoData = '导入demo数据'; + +$lang->install->requestTypes['GET'] = '普通方式'; +$lang->install->requestTypes['PATH_INFO'] = '静态友好方式'; + +$lang->install->errorConnectDB = '数据库连接失败 '; +$lang->install->errorCreateDB = '数据库创建失败'; +$lang->install->errorTableExists = '数据表已经存在,您之前应该有安装过禅道,继续安装请返回前页并选择清空数据'; +$lang->install->errorCreateTable = '创建表失败'; +$lang->install->errorImportDemoData = '导入demo数据失败'; + +$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->groupList['ADMIN']['name'] = '管理员'; +$lang->install->groupList['ADMIN']['desc'] = '系统管理员'; +$lang->install->groupList['DEV']['name'] = '研发'; +$lang->install->groupList['DEV']['desc'] = '研发人员'; +$lang->install->groupList['QA']['name'] = '测试'; +$lang->install->groupList['QA']['desc'] = '测试人员'; +$lang->install->groupList['PM']['name'] = '项目经理'; +$lang->install->groupList['PM']['desc'] = '项目经理'; +$lang->install->groupList['PO']['name'] = '产品经理'; +$lang->install->groupList['PO']['desc'] = '产品经理'; +$lang->install->groupList['TD']['name'] = '研发主管'; +$lang->install->groupList['TD']['desc'] = '研发主管'; +$lang->install->groupList['PD']['name'] = '产品主管'; +$lang->install->groupList['PD']['desc'] = '产品主管'; +$lang->install->groupList['QD']['name'] = '测试主管'; +$lang->install->groupList['QD']['desc'] = '测试主管'; +$lang->install->groupList['TOP']['name'] = '高层管理'; +$lang->install->groupList['TOP']['desc'] = '高层管理'; +$lang->install->groupList['OTHERS']['name'] = '其他'; +$lang->install->groupList['OTHERS']['desc'] = '其他'; + +$lang->install->success = "安装成功"; + +$lang->install->joinZentao = <<请及时删除install.php。现在您可以直接,设置用户及分组! +友情提示:为了您及时获得禅道的最新动态,请在禅道社区(www.zentao.net)进行登记。 +EOT; diff --git a/module/install/lang/zh-tw.php b/module/install/lang/zh-tw.php index 6d33635156..d1b192650a 100644 --- a/module/install/lang/zh-tw.php +++ b/module/install/lang/zh-tw.php @@ -1,137 +1,137 @@ - - * @package install - * @version $Id: zh-tw.php 3879 2012-12-24 06:24:54Z wyd621@gmail.com $ - * @link http://www.zentao.net - */ -$lang->install = new stdclass(); - -$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->session = 'Session存儲目錄'; -$lang->install->sessionFail = '修改PHP配置檔案,設置session.save_path'; -$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->importDemoData = '導入demo數據'; - -$lang->install->requestTypes['GET'] = '普通方式'; -$lang->install->requestTypes['PATH_INFO'] = '靜態友好方式'; - -$lang->install->errorConnectDB = '資料庫連接失敗 '; -$lang->install->errorCreateDB = '資料庫創建失敗'; -$lang->install->errorTableExists = '數據表已經存在,您之前應該有安裝過禪道,繼續安裝請返回前頁並選擇清空數據'; -$lang->install->errorCreateTable = '創建表失敗'; -$lang->install->errorImportDemoData = '導入demo數據失敗'; - -$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->groupList['ADMIN']['name'] = '管理員'; -$lang->install->groupList['ADMIN']['desc'] = '系統管理員'; -$lang->install->groupList['DEV']['name'] = '研發'; -$lang->install->groupList['DEV']['desc'] = '研發人員'; -$lang->install->groupList['QA']['name'] = '測試'; -$lang->install->groupList['QA']['desc'] = '測試人員'; -$lang->install->groupList['PM']['name'] = '項目經理'; -$lang->install->groupList['PM']['desc'] = '項目經理'; -$lang->install->groupList['PO']['name'] = '產品經理'; -$lang->install->groupList['PO']['desc'] = '產品經理'; -$lang->install->groupList['TD']['name'] = '研發主管'; -$lang->install->groupList['TD']['desc'] = '研發主管'; -$lang->install->groupList['PD']['name'] = '產品主管'; -$lang->install->groupList['PD']['desc'] = '產品主管'; -$lang->install->groupList['QD']['name'] = '測試主管'; -$lang->install->groupList['QD']['desc'] = '測試主管'; -$lang->install->groupList['TOP']['name'] = '高層管理'; -$lang->install->groupList['TOP']['desc'] = '高層管理'; -$lang->install->groupList['OTHERS']['name'] = '其他'; -$lang->install->groupList['OTHERS']['desc'] = '其他'; - -$lang->install->success = "安裝成功"; - -$lang->install->joinZentao = <<請及時刪除install.php。現在您可以直接,設置用戶及分組! -友情提示:為了您及時獲得禪道的最新動態,請在禪道社區(www.zentao.net)進行登記。 -EOT; + + * @package install + * @version $Id: zh-tw.php 3879 2012-12-24 06:24:54Z wyd621@gmail.com $ + * @link http://www.zentao.net + */ +$lang->install = new stdclass(); + +$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->session = 'Session存儲目錄'; +$lang->install->sessionFail = '修改PHP配置檔案,設置session.save_path'; +$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->importDemoData = '導入demo數據'; + +$lang->install->requestTypes['GET'] = '普通方式'; +$lang->install->requestTypes['PATH_INFO'] = '靜態友好方式'; + +$lang->install->errorConnectDB = '資料庫連接失敗 '; +$lang->install->errorCreateDB = '資料庫創建失敗'; +$lang->install->errorTableExists = '數據表已經存在,您之前應該有安裝過禪道,繼續安裝請返回前頁並選擇清空數據'; +$lang->install->errorCreateTable = '創建表失敗'; +$lang->install->errorImportDemoData = '導入demo數據失敗'; + +$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->groupList['ADMIN']['name'] = '管理員'; +$lang->install->groupList['ADMIN']['desc'] = '系統管理員'; +$lang->install->groupList['DEV']['name'] = '研發'; +$lang->install->groupList['DEV']['desc'] = '研發人員'; +$lang->install->groupList['QA']['name'] = '測試'; +$lang->install->groupList['QA']['desc'] = '測試人員'; +$lang->install->groupList['PM']['name'] = '項目經理'; +$lang->install->groupList['PM']['desc'] = '項目經理'; +$lang->install->groupList['PO']['name'] = '產品經理'; +$lang->install->groupList['PO']['desc'] = '產品經理'; +$lang->install->groupList['TD']['name'] = '研發主管'; +$lang->install->groupList['TD']['desc'] = '研發主管'; +$lang->install->groupList['PD']['name'] = '產品主管'; +$lang->install->groupList['PD']['desc'] = '產品主管'; +$lang->install->groupList['QD']['name'] = '測試主管'; +$lang->install->groupList['QD']['desc'] = '測試主管'; +$lang->install->groupList['TOP']['name'] = '高層管理'; +$lang->install->groupList['TOP']['desc'] = '高層管理'; +$lang->install->groupList['OTHERS']['name'] = '其他'; +$lang->install->groupList['OTHERS']['desc'] = '其他'; + +$lang->install->success = "安裝成功"; + +$lang->install->joinZentao = <<請及時刪除install.php。現在您可以直接,設置用戶及分組! +友情提示:為了您及時獲得禪道的最新動態,請在禪道社區(www.zentao.net)進行登記。 +EOT; diff --git a/module/install/model.php b/module/install/model.php index 21175d13fd..9eb2a1ff99 100644 --- a/module/install/model.php +++ b/module/install/model.php @@ -1,451 +1,451 @@ - - * @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 session save path. - * - * @access public - * @return array - */ - public function getSessionSavePath() - { - if(preg_match('/WIN/i', PHP_OS)) - { - $result['path'] = session_save_path(); - $result['exists'] = is_dir($result['path']); - $result['writable'] = is_writable($result['path']); - return $result; - } - return array('path' => '/tmp', 'exists' => true, 'writable' => true); - } - - /** - * Check session save path. - * - * @access public - * @return string - */ - public function checkSessionSavePath() - { - if(preg_match('/WIN/i', PHP_OS)) - { - $sessionSavePath = session_save_path(); - return $result = (is_dir($sessionSavePath) and is_writable($sessionSavePath)) ? 'ok' : 'fail'; - } - return 'ok'; - } - - /** - * 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; - } - - /** - * Check config ok or not. - * - * @access public - * @return array - */ - public function checkConfig() - { - $return = new stdclass(); - $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->tableExits() and $this->post->clearDB == false) - { - $return->result = 'fail'; - $return->error = $this->lang->install->errorTableExists; - 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(); - } - - /** - * Check table exits or not. - * - * @access public - * @return void - */ - public function tableExits() - { - $configTable = str_replace('`', "'", TABLE_CONFIG); - $sql = "SHOW TABLES FROM {$this->config->db->name} like $configTable"; - 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->gender = ''; - $admin->company = $companyID; - $this->dao->insert(TABLE_USER)->data($admin)->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); - - /* Update group name and desc on dafault lang.*/ - include('lang/' . $this->config->default->lang . '.php'); - $groups = $this->dao->select('*')->from(TABLE_GROUP)->orderBy('id')->fetchAll(); - foreach($groups as $group) - { - if(isset($lang->install->groupList[$group->name]))$this->dao->update(TABLE_GROUP)->data($lang->install->groupList[$group->name])->where('id')->eq($group->id)->exec(); - } - } - } - - /** - * Import demo data. - * - * @access public - * @return void - */ - public function importDemoData() - { - $demoDataFile = $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'demo.sql'; - $insertTables = explode(";\n", file_get_contents($demoDataFile)); - foreach($insertTables as $table) - { - $table = trim($table); - if(empty($table)) continue; - - $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; - } - - $config->company = '1'; - $config->module = 'common'; - $config->owner = 'system'; - $config->section = 'global'; - $config->key = 'showDemoUsers'; - $config->value = '1'; - $this->dao->replace(TABLE_CONFIG)->data($config, false)->exec(false); - return true; - } - -} + + * @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 session save path. + * + * @access public + * @return array + */ + public function getSessionSavePath() + { + if(preg_match('/WIN/i', PHP_OS)) + { + $result['path'] = session_save_path(); + $result['exists'] = is_dir($result['path']); + $result['writable'] = is_writable($result['path']); + return $result; + } + return array('path' => '/tmp', 'exists' => true, 'writable' => true); + } + + /** + * Check session save path. + * + * @access public + * @return string + */ + public function checkSessionSavePath() + { + if(preg_match('/WIN/i', PHP_OS)) + { + $sessionSavePath = session_save_path(); + return $result = (is_dir($sessionSavePath) and is_writable($sessionSavePath)) ? 'ok' : 'fail'; + } + return 'ok'; + } + + /** + * 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; + } + + /** + * Check config ok or not. + * + * @access public + * @return array + */ + public function checkConfig() + { + $return = new stdclass(); + $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->tableExits() and $this->post->clearDB == false) + { + $return->result = 'fail'; + $return->error = $this->lang->install->errorTableExists; + 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(); + } + + /** + * Check table exits or not. + * + * @access public + * @return void + */ + public function tableExits() + { + $configTable = str_replace('`', "'", TABLE_CONFIG); + $sql = "SHOW TABLES FROM {$this->config->db->name} like $configTable"; + 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->gender = ''; + $admin->company = $companyID; + $this->dao->insert(TABLE_USER)->data($admin)->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); + + /* Update group name and desc on dafault lang.*/ + include('lang/' . $this->config->default->lang . '.php'); + $groups = $this->dao->select('*')->from(TABLE_GROUP)->orderBy('id')->fetchAll(); + foreach($groups as $group) + { + if(isset($lang->install->groupList[$group->name]))$this->dao->update(TABLE_GROUP)->data($lang->install->groupList[$group->name])->where('id')->eq($group->id)->exec(); + } + } + } + + /** + * Import demo data. + * + * @access public + * @return void + */ + public function importDemoData() + { + $demoDataFile = $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'demo.sql'; + $insertTables = explode(";\n", file_get_contents($demoDataFile)); + foreach($insertTables as $table) + { + $table = trim($table); + if(empty($table)) continue; + + $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; + } + + $config->company = '1'; + $config->module = 'common'; + $config->owner = 'system'; + $config->section = 'global'; + $config->key = 'showDemoUsers'; + $config->value = '1'; + $this->dao->replace(TABLE_CONFIG)->data($config, false)->exec(false); + return true; + } + +} diff --git a/module/install/view/index.html.php b/module/install/view/index.html.php index 301e88758a..45d9e99c0f 100644 --- a/module/install/view/index.html.php +++ b/module/install/view/index.html.php @@ -1,36 +1,36 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - - - - - -
          install->welcome;?>
          install->desc, $config->version));?>
          - version, $config->version) > 0)):?> - install->newReleased, $latestRelease);?> -

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

          - -

          - config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"');?> - createLink('install', 'step1'), $lang->install->start);?> -

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

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

          + +

          + config->langs, $app->cookie->lang, 'onchange="selectLang(this.value)"');?> + createLink('install', 'step1'), $lang->install->start);?> +

          + +
          + diff --git a/module/install/view/step1.html.php b/module/install/view/step1.html.php index f1f8462140..e7e3de706c 100644 --- a/module/install/view/step1.html.php +++ b/module/install/view/step1.html.php @@ -1,121 +1,121 @@ - - * @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']); - ?> -
          install->session;?> - install->exists) : print($lang->install->notExists); - $sessionInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); - ?> - install->$sessionResult;?> - install->mkdir, $sessionInfo['path'], $sessionInfo['path']); - if(!$sessionInfo['writable']) printf($lang->install->chmod, $sessionInfo['path'], $sessionInfo['path']); - } - else - { - echo $lang->install->sessionFail; - } - ?> -
          - 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']); + ?> +
          install->session;?> + install->exists) : print($lang->install->notExists); + $sessionInfo['writable'] ? print($lang->install->writable) : print($lang->install->notWritable); + ?> + install->$sessionResult;?> + install->mkdir, $sessionInfo['path'], $sessionInfo['path']); + if(!$sessionInfo['writable']) printf($lang->install->chmod, $sessionInfo['path'], $sessionInfo['path']); + } + else + { + echo $lang->install->sessionFail; + } + ?> +
          + 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 31c7a623b0..f05740c514 100644 --- a/module/install/view/step2.html.php +++ b/module/install/view/step2.html.php @@ -1,63 +1,63 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - -
          '> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          install->setConfig;?>
          install->key;?>install->value?>
          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->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 a1b72fefaa..090508815b 100644 --- a/module/install/view/step3.html.php +++ b/module/install/view/step3.html.php @@ -1,73 +1,73 @@ - - * @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 = getWebRoot(); -\$config->default->domain = '$domain'; -\$config->default->lang = '$defaultLang'; -\$config->mysqldump = ''; -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 = getWebRoot(); +\$config->default->domain = '$domain'; +\$config->default->lang = '$defaultLang'; +\$config->mysqldump = ''; +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 527ae694f7..6f1feb9e1e 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;?>install->importDemoData);?>
          -
          - - + + * @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;?>install->importDemoData);?>
          +
          + + diff --git a/module/install/view/step5.html.php b/module/install/view/step5.html.php index a0edd989f7..d20c57f6d1 100644 --- a/module/install/view/step5.html.php +++ b/module/install/view/step5.html.php @@ -1,21 +1,21 @@ - - * @package ZenTaoPMS - * @version $Id: step5.html.php 2568 2012-02-18 15:53:35Z zhujinyong@cnezsoft.com$ - */ -?> - - - - - - -
          install->success;?>
          - install->joinZentao, $config->version, $this->createLink('admin', 'register'), $this->createLink('admin', 'bind'), inlink('step6')));?> -
          - + + * @package ZenTaoPMS + * @version $Id: step5.html.php 2568 2012-02-18 15:53:35Z zhujinyong@cnezsoft.com$ + */ +?> + + + + + + +
          install->success;?>
          + install->joinZentao, $config->version, $this->createLink('admin', 'register'), $this->createLink('admin', 'bind'), inlink('step6')));?> +
          + diff --git a/module/mail/control.php b/module/mail/control.php index 30cc2e7c89..2b7e14c901 100755 --- a/module/mail/control.php +++ b/module/mail/control.php @@ -1,152 +1,152 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -class mail extends control -{ - /** - * The index page, goto edit page or detect page. - * - * @access public - * @return void - */ - public function index() - { - if($this->config->mail->turnon) $this->locate(inlink('edit')); - $this->locate(inlink('detect')); - } - - /** - * Detect email config auto. - * - * @access public - * @return void - */ - public function detect() - { - if($_POST) - { - $error = ''; - if($this->post->fromAddress == false) $error = sprintf($this->lang->error->notempty, $this->lang->mail->fromAddress); - if(!validater::checkEmail($this->post->fromAddress)) $error .= '\n' . sprintf($this->lang->error->email, $this->lang->mail->fromAddress); - - if($error) die(js::alert($error)); - - $mailConfig = $this->mail->autoDetect($this->post->fromAddress); - $mailConfig->fromAddress = $this->post->fromAddress; - $this->session->set('mailConfig', $mailConfig); - - die(js::locate(inlink('edit'), 'parent')); - } - - $this->view->header->title = $this->lang->mail->detect; - $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); - $this->view->position[] = $this->lang->mail->detect; - - $this->view->fromAddress = $this->session->mailConfig ? $this->session->mailConfig->fromAddress : ''; - - $this->display(); - } - - /** - * Edit the mail config. - * - * @access public - * @return void - */ - public function edit() - { - if($this->config->mail->turnon) - { - $mailConfig = $this->config->mail->smtp; - $mailConfig->fromAddress = $this->config->mail->fromAddress; - $mailConfig->fromName = $this->config->mail->fromName; - } - elseif($this->session->mailConfig) - { - $mailConfig = $this->session->mailConfig; - } - else - { - $this->locate(inlink('detect')); - } - - $this->view->header->title = $this->lang->mail->edit; - $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); - $this->view->position[] = $this->lang->mail->edit; - - $this->view->mailExist = $this->mail->mailExist(); - $this->view->mailConfig = $mailConfig; - $this->display(); - } - - /** - * Save the email config. - * - * @access public - * @return void - */ - public function save() - { - if(!empty($_POST)) - { - $mailConfig = new stdclass(); - $mailConfig->smtp = new stdclass(); - - $mailConfig->turnon = $this->post->turnon; - $mailConfig->mta = 'smtp'; - $mailConfig->fromAddress = $this->post->fromAddress; - $mailConfig->fromName = $this->post->fromName; - $mailConfig->smtp->host = $this->post->host; - $mailConfig->smtp->port = $this->post->port; - $mailConfig->smtp->auth = $this->post->auth; - $mailConfig->smtp->username = $this->post->username; - $mailConfig->smtp->password = $this->post->password; - $mailConfig->smtp->secure = $this->post->secure; - $mailConfig->smtp->debug = $this->post->debug; - - $this->loadModel('setting')->setItems('system.mail', $mailConfig); - if(dao::isError()) die(js::error(dao::getError())); - - $this->session->set('mailConfig', ''); - - $this->view->header->title = $this->lang->mail->save; - $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); - $this->view->position[] = $this->lang->mail->save; - - $this->view->mailExist = $this->mail->mailExist(); - $this->display(); - } - } - - /** - * Send test email. - * - * @access public - * @return void - */ - public function test() - { - if(!$this->config->mail->turnon) - { - die(js::alert($this->lang->mail->needConfigure) . js::locate('back')); - } - - if($_POST) - { - $this->mail->send($this->post->to, $this->lang->mail->subject, $this->lang->mail->content,"", true); - if($this->mail->isError()) die(js::error($this->mail->getError())); - die(js::alert($this->lang->mail->successSended)); - } - - $this->view->users = $this->dao->select('account, CONCAT(realname, " ", email) AS email' )->from(TABLE_USER)->where('email')->ne('')->orderBy('account')->fetchPairs(); - $this->display(); - } -} + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +class mail extends control +{ + /** + * The index page, goto edit page or detect page. + * + * @access public + * @return void + */ + public function index() + { + if($this->config->mail->turnon) $this->locate(inlink('edit')); + $this->locate(inlink('detect')); + } + + /** + * Detect email config auto. + * + * @access public + * @return void + */ + public function detect() + { + if($_POST) + { + $error = ''; + if($this->post->fromAddress == false) $error = sprintf($this->lang->error->notempty, $this->lang->mail->fromAddress); + if(!validater::checkEmail($this->post->fromAddress)) $error .= '\n' . sprintf($this->lang->error->email, $this->lang->mail->fromAddress); + + if($error) die(js::alert($error)); + + $mailConfig = $this->mail->autoDetect($this->post->fromAddress); + $mailConfig->fromAddress = $this->post->fromAddress; + $this->session->set('mailConfig', $mailConfig); + + die(js::locate(inlink('edit'), 'parent')); + } + + $this->view->header->title = $this->lang->mail->detect; + $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); + $this->view->position[] = $this->lang->mail->detect; + + $this->view->fromAddress = $this->session->mailConfig ? $this->session->mailConfig->fromAddress : ''; + + $this->display(); + } + + /** + * Edit the mail config. + * + * @access public + * @return void + */ + public function edit() + { + if($this->config->mail->turnon) + { + $mailConfig = $this->config->mail->smtp; + $mailConfig->fromAddress = $this->config->mail->fromAddress; + $mailConfig->fromName = $this->config->mail->fromName; + } + elseif($this->session->mailConfig) + { + $mailConfig = $this->session->mailConfig; + } + else + { + $this->locate(inlink('detect')); + } + + $this->view->header->title = $this->lang->mail->edit; + $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); + $this->view->position[] = $this->lang->mail->edit; + + $this->view->mailExist = $this->mail->mailExist(); + $this->view->mailConfig = $mailConfig; + $this->display(); + } + + /** + * Save the email config. + * + * @access public + * @return void + */ + public function save() + { + if(!empty($_POST)) + { + $mailConfig = new stdclass(); + $mailConfig->smtp = new stdclass(); + + $mailConfig->turnon = $this->post->turnon; + $mailConfig->mta = 'smtp'; + $mailConfig->fromAddress = $this->post->fromAddress; + $mailConfig->fromName = $this->post->fromName; + $mailConfig->smtp->host = $this->post->host; + $mailConfig->smtp->port = $this->post->port; + $mailConfig->smtp->auth = $this->post->auth; + $mailConfig->smtp->username = $this->post->username; + $mailConfig->smtp->password = $this->post->password; + $mailConfig->smtp->secure = $this->post->secure; + $mailConfig->smtp->debug = $this->post->debug; + + $this->loadModel('setting')->setItems('system.mail', $mailConfig); + if(dao::isError()) die(js::error(dao::getError())); + + $this->session->set('mailConfig', ''); + + $this->view->header->title = $this->lang->mail->save; + $this->view->position[] = html::a(inlink('index'), $this->lang->mail->common); + $this->view->position[] = $this->lang->mail->save; + + $this->view->mailExist = $this->mail->mailExist(); + $this->display(); + } + } + + /** + * Send test email. + * + * @access public + * @return void + */ + public function test() + { + if(!$this->config->mail->turnon) + { + die(js::alert($this->lang->mail->needConfigure) . js::locate('back')); + } + + if($_POST) + { + $this->mail->send($this->post->to, $this->lang->mail->subject, $this->lang->mail->content,"", true); + if($this->mail->isError()) die(js::error($this->mail->getError())); + die(js::alert($this->lang->mail->successSended)); + } + + $this->view->users = $this->dao->select('account, CONCAT(realname, " ", email) AS email' )->from(TABLE_USER)->where('email')->ne('')->orderBy('account')->fetchPairs(); + $this->display(); + } +} diff --git a/module/mail/model.php b/module/mail/model.php index c27a05bb2c..a25f6af2db 100644 --- a/module/mail/model.php +++ b/module/mail/model.php @@ -1,406 +1,406 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -?> -app->loadClass('phpmailer', $static = true); - $this->setMTA(); - } - - /** - * Auto detect email config. - * - * @param string $email - * @access public - * @return object - */ - public function autoDetect($email) - { - /* Split the email to username and domain. */ - list($username, $domain) = explode('@', $email); - $domain = strtolower($domain); - - /* - * 1. try to find config from the providers. - * 2. try to find the mx record to get the domain and then search it in providers. - * 3. try smtp.$domain's 25 and 465 port, if can connect, use smtp.$domain. - */ - $config = $this->getConfigFromProvider($domain, $username); - if(!$config) $config = $this->getConfigByMXRR($domain, $username); - if(!$config) $config = $this->getConfigByDetectingSMTP($domain, $username, 25); - if(!$config) $config = $this->getConfigByDetectingSMTP($domain, $username, 465); - - /* Set default values. */ - $config->mta = 'smtp'; - $config->fromName = 'zentao'; - $config->password = ''; - $config->debug = 1; - if(!isset($config->host)) $config->host = ''; - if(!isset($config->auth)) $config->auth = 1; - if(!isset($config->port)) $config->port = '25'; - - return $config; - } - - /** - * Try get config from providers. - * - * @param int $domain - * @param int $username - * @access public - * @return bool|object - */ - public function getConfigFromProvider($domain, $username) - { - if(isset($this->config->mail->provider[$domain])) - { - $config = (object)$this->config->mail->provider[$domain]; - $config->mta = 'smtp'; - $config->username = $username; - $config->auth = 1; - if(!isset($config->port)) $config->port = 25; - if(!isset($config->secure)) $config->secure = ''; - return $config; - } - return false; - } - - /** - * Get config by MXRR. - * - * @param string $domain - * @param string $username - * @access public - * @return bool|object - */ - public function getConfigByMXRR($domain, $username) - { - /* Try to get mx record, under linux, use getmxrr() directly, windows use nslookup. */ - if(function_exists('getmxrr')) - { - getmxrr($domain, $smtpHosts); - } - elseif(strpos(PHP_OS, 'WIN') !== false) - { - $smtpHosts = array(); - $result = `nslookup -q=mx {$domain} 2>nul`; - $lines = explode("\n", $result); - foreach($lines as $line) - { - if(stripos($line, 'exchanger')) $smtpHosts[] = trim(substr($line, strrpos($line, '=') + 1)); - } - } - - /* Cycle the smtpHosts and try to find it's config from the provider config. */ - foreach($smtpHosts as $smtpHost) - { - /* Get the domain name from the hosts, for example: imxbiz1.qq.com get qq.com. */ - $smtpDomain = explode('.', $smtpHost); - array_shift($smtpDomain); - $smtpDomain = strtolower(implode('.', $smtpDomain)); - if($config = $this->getConfigFromProvider($smtpDomain, $username)) - { - $config->username = "$username@$domain"; - return $config; - } - } - - return false; - } - - /** - * Try connect to smtp.$domain's 25 or 465 port and compute the config according to the connection result. - * - * @param string $domain - * @param string $username - * @param int $port - * @access public - * @return bool|object - */ - public function getConfigByDetectingSMTP($domain, $username, $port) - { - $host = 'smtp.' . $domain; - ini_set('default_socket_timeout', 3); - $connection = @fsockopen($host, $port); - if(!$connection) return false; - fclose($connection); - - $config->username = $username; - $config->host = $host; - $config->auth = 1; - $config->port = $port; - $config->secure = $port == 465 ? 'ssl' : ''; - - return $config; - } - - /** - * 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)) $this->app->error("The MTA {$this->config->mail->mta} not supported now.", __FILE__, __LINE__, $exit = true); - $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(); - } - - /** - * Check system if there is a mail at least. - * - * @access public - * @return bool | object - */ - public function mailExist() - { - return $this->dao->select('email')->from(TABLE_USER)->where('email')->ne('')->fetch(); - } - - /** - * 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(); + } + + /** + * Auto detect email config. + * + * @param string $email + * @access public + * @return object + */ + public function autoDetect($email) + { + /* Split the email to username and domain. */ + list($username, $domain) = explode('@', $email); + $domain = strtolower($domain); + + /* + * 1. try to find config from the providers. + * 2. try to find the mx record to get the domain and then search it in providers. + * 3. try smtp.$domain's 25 and 465 port, if can connect, use smtp.$domain. + */ + $config = $this->getConfigFromProvider($domain, $username); + if(!$config) $config = $this->getConfigByMXRR($domain, $username); + if(!$config) $config = $this->getConfigByDetectingSMTP($domain, $username, 25); + if(!$config) $config = $this->getConfigByDetectingSMTP($domain, $username, 465); + + /* Set default values. */ + $config->mta = 'smtp'; + $config->fromName = 'zentao'; + $config->password = ''; + $config->debug = 1; + if(!isset($config->host)) $config->host = ''; + if(!isset($config->auth)) $config->auth = 1; + if(!isset($config->port)) $config->port = '25'; + + return $config; + } + + /** + * Try get config from providers. + * + * @param int $domain + * @param int $username + * @access public + * @return bool|object + */ + public function getConfigFromProvider($domain, $username) + { + if(isset($this->config->mail->provider[$domain])) + { + $config = (object)$this->config->mail->provider[$domain]; + $config->mta = 'smtp'; + $config->username = $username; + $config->auth = 1; + if(!isset($config->port)) $config->port = 25; + if(!isset($config->secure)) $config->secure = ''; + return $config; + } + return false; + } + + /** + * Get config by MXRR. + * + * @param string $domain + * @param string $username + * @access public + * @return bool|object + */ + public function getConfigByMXRR($domain, $username) + { + /* Try to get mx record, under linux, use getmxrr() directly, windows use nslookup. */ + if(function_exists('getmxrr')) + { + getmxrr($domain, $smtpHosts); + } + elseif(strpos(PHP_OS, 'WIN') !== false) + { + $smtpHosts = array(); + $result = `nslookup -q=mx {$domain} 2>nul`; + $lines = explode("\n", $result); + foreach($lines as $line) + { + if(stripos($line, 'exchanger')) $smtpHosts[] = trim(substr($line, strrpos($line, '=') + 1)); + } + } + + /* Cycle the smtpHosts and try to find it's config from the provider config. */ + foreach($smtpHosts as $smtpHost) + { + /* Get the domain name from the hosts, for example: imxbiz1.qq.com get qq.com. */ + $smtpDomain = explode('.', $smtpHost); + array_shift($smtpDomain); + $smtpDomain = strtolower(implode('.', $smtpDomain)); + if($config = $this->getConfigFromProvider($smtpDomain, $username)) + { + $config->username = "$username@$domain"; + return $config; + } + } + + return false; + } + + /** + * Try connect to smtp.$domain's 25 or 465 port and compute the config according to the connection result. + * + * @param string $domain + * @param string $username + * @param int $port + * @access public + * @return bool|object + */ + public function getConfigByDetectingSMTP($domain, $username, $port) + { + $host = 'smtp.' . $domain; + ini_set('default_socket_timeout', 3); + $connection = @fsockopen($host, $port); + if(!$connection) return false; + fclose($connection); + + $config->username = $username; + $config->host = $host; + $config->auth = 1; + $config->port = $port; + $config->secure = $port == 465 ? 'ssl' : ''; + + return $config; + } + + /** + * 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)) $this->app->error("The MTA {$this->config->mail->mta} not supported now.", __FILE__, __LINE__, $exit = true); + $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(); + } + + /** + * Check system if there is a mail at least. + * + * @access public + * @return bool | object + */ + public function mailExist() + { + return $this->dao->select('email')->from(TABLE_USER)->where('email')->ne('')->fetch(); + } + + /** + * 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/detect.html.php b/module/mail/view/detect.html.php index 0522a3d260..6e0bbb3ac4 100755 --- a/module/mail/view/detect.html.php +++ b/module/mail/view/detect.html.php @@ -1,20 +1,20 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -include '../../common/view/header.html.php'; -?> -
          - - - -
          mail->inputFromEmail; ?>
          mail->nextStep);?>
          -
          - + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +?> +
          + + + +
          mail->inputFromEmail; ?>
          mail->nextStep);?>
          +
          + diff --git a/module/mail/view/edit.html.php b/module/mail/view/edit.html.php index c40c7630e2..b75ec099ce 100755 --- a/module/mail/view/edit.html.php +++ b/module/mail/view/edit.html.php @@ -1,68 +1,68 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -include '../../common/view/header.html.php'; -?> -
          ' id='dataform'> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          mail->edit;?>
          mail->turnon; ?>mail->turnonList, 1);?>
          mail->fromAddress; ?>fromAddress, 'class=text-3');?>
          mail->fromName; ?>fromName, 'class=text-3');?>
          mail->host; ?>host, 'class=text-3');?>
          mail->port; ?>port, 'class=text-3');?>
          mail->auth; ?>mail->authList, $mailConfig->auth, 'onchange=setAuth(this.value)'); ?>
          mail->username; ?>username, 'class=text-3') ?>
          mail->password; ?>password, 'class="text-3" autocomplete="off"') ?>
          mail->secure; ?>mail->secureList, $mailConfig->secure); ?>
          mail->debug; ?>mail->debugList, $mailConfig->debug);?>
          - config->mail->turnon and $mailExist) echo html::linkButton($lang->mail->test, inlink('test')); - ?> -
          -
          - + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +?> +
          ' id='dataform'> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          mail->edit;?>
          mail->turnon; ?>mail->turnonList, 1);?>
          mail->fromAddress; ?>fromAddress, 'class=text-3');?>
          mail->fromName; ?>fromName, 'class=text-3');?>
          mail->host; ?>host, 'class=text-3');?>
          mail->port; ?>port, 'class=text-3');?>
          mail->auth; ?>mail->authList, $mailConfig->auth, 'onchange=setAuth(this.value)'); ?>
          mail->username; ?>username, 'class=text-3') ?>
          mail->password; ?>password, 'class="text-3" autocomplete="off"') ?>
          mail->secure; ?>mail->secureList, $mailConfig->secure); ?>
          mail->debug; ?>mail->debugList, $mailConfig->debug);?>
          + config->mail->turnon and $mailExist) echo html::linkButton($lang->mail->test, inlink('test')); + ?> +
          +
          + diff --git a/module/mail/view/save.html.php b/module/mail/view/save.html.php index 50e204ce5b..e9f587a1dc 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->save ?>
          - mail->successSaved; - if($this->config->mail->turnon and $mailExist) echo html::linkButton($lang->mail->test, inlink('test')); - ?> -
          - + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +?> + + + + + +
          mail->save ?>
          + mail->successSaved; + if($this->config->mail->turnon and $mailExist) echo html::linkButton($lang->mail->test, inlink('test')); + ?> +
          + diff --git a/module/mail/view/test.html.php b/module/mail/view/test.html.php index 699537e83c..6a266aaea3 100755 --- a/module/mail/view/test.html.php +++ b/module/mail/view/test.html.php @@ -1,28 +1,28 @@ - - * @package mail - * @version $Id$ - * @link http://www.zentao.net - */ -include '../../common/view/header.html.php'; -?> -
          - - - - - -
          mail->test; ?>
          - user->account); - echo html::submitButton($lang->mail->test); - echo html::linkButton($lang->mail->edit, $this->inLink('edit')); - ?> -
          -
          - + + * @package mail + * @version $Id$ + * @link http://www.zentao.net + */ +include '../../common/view/header.html.php'; +?> +
          + + + + + +
          mail->test; ?>
          + user->account); + echo html::submitButton($lang->mail->test); + echo html::linkButton($lang->mail->edit, $this->inLink('edit')); + ?> +
          +
          + diff --git a/module/misc/control.php b/module/misc/control.php index 9df8c9b077..5742dbf216 100644 --- a/module/misc/control.php +++ b/module/misc/control.php @@ -1,118 +1,118 @@ - - * @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, 1) == 1) $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(); - } - - /** - * Check current version is latest or not. - * - * @access public - * @return void - */ - public function checkUpdate() - { - $note = isset($_GET['note']) ? $_GET['note'] : ''; - $browser = isset($_GET['browser']) ? $_GET['browser'] : ''; - - $this->view->note = urldecode(helper::safe64Decode($note)); - $this->view->browser = $browser; - $this->display(); - } - - /** - * Check model extension logic - * - * @access public - * @return void - */ - public function checkExtension() - { - echo $this->misc->hello(); - echo $this->misc->hello2(); - } - - /** - * Down notify. - * - * @access public - * @return void - */ - public function downNotify() - { - $notifyDir = $this->app->getBasePath() . 'www/data/notify/'; - $packageFile = $notifyDir . 'notify.zip'; - $tmpDir = $notifyDir . 'notify'; - $loginFile = $tmpDir . '/notify/logininfo'; - - $this->app->loadClass('pclzip', true); - $sourceZip = new pclzip($packageFile); - $files = $sourceZip->extract(PCLZIP_OPT_PATH, $notifyDir); - if($files == 0) die("Error : ".$sourceZip->errorInfo(true)); - - $currentUser = $this->app->user; - $loginInfo = json_encode(array('account' => $currentUser->account, 'password' => $currentUser->password, 'zentaoRoot' => 'http://' . $this->config->default->domain)); - file_put_contents($loginFile, $loginInfo); - - unlink($packageFile); - $newZip = new pclzip($packageFile); - if($newZip->create($tmpDir, PCLZIP_OPT_REMOVE_PATH, $notifyDir)) - { - $this->zfile = $this->app->loadClass('zfile'); - $this->zfile->removeDir($tmpDir); - } - $this->fetch('file', 'sendDownHeader', array('fileName' => 'notify.zip', 'zip', file_get_contents($packageFile))); - } -} + + * @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, 1) == 1) $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(); + } + + /** + * Check current version is latest or not. + * + * @access public + * @return void + */ + public function checkUpdate() + { + $note = isset($_GET['note']) ? $_GET['note'] : ''; + $browser = isset($_GET['browser']) ? $_GET['browser'] : ''; + + $this->view->note = urldecode(helper::safe64Decode($note)); + $this->view->browser = $browser; + $this->display(); + } + + /** + * Check model extension logic + * + * @access public + * @return void + */ + public function checkExtension() + { + echo $this->misc->hello(); + echo $this->misc->hello2(); + } + + /** + * Down notify. + * + * @access public + * @return void + */ + public function downNotify() + { + $notifyDir = $this->app->getBasePath() . 'www/data/notify/'; + $packageFile = $notifyDir . 'notify.zip'; + $tmpDir = $notifyDir . 'notify'; + $loginFile = $tmpDir . '/notify/logininfo'; + + $this->app->loadClass('pclzip', true); + $sourceZip = new pclzip($packageFile); + $files = $sourceZip->extract(PCLZIP_OPT_PATH, $notifyDir); + if($files == 0) die("Error : ".$sourceZip->errorInfo(true)); + + $currentUser = $this->app->user; + $loginInfo = json_encode(array('account' => $currentUser->account, 'password' => $currentUser->password, 'zentaoRoot' => 'http://' . $this->config->default->domain)); + file_put_contents($loginFile, $loginInfo); + + unlink($packageFile); + $newZip = new pclzip($packageFile); + if($newZip->create($tmpDir, PCLZIP_OPT_REMOVE_PATH, $notifyDir)) + { + $this->zfile = $this->app->loadClass('zfile'); + $this->zfile->removeDir($tmpDir); + } + $this->fetch('file', 'sendDownHeader', array('fileName' => 'notify.zip', 'zip', file_get_contents($packageFile))); + } +} diff --git a/module/misc/lang/en.php b/module/misc/lang/en.php index aa897264d8..6744a70f2f 100644 --- a/module/misc/lang/en.php +++ b/module/misc/lang/en.php @@ -1,49 +1,49 @@ - - * @package misc - * @version $Id: English.php 824 2010-05-02 15:32:06Z wwccss $ - * @link http://www.zentao.net - */ -$lang->misc = new stdclass(); -$lang->misc->common = 'Misc'; -$lang->misc->ping = 'Keep session'; - -$lang->misc->zentao = new stdclass(); -$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['proversion'] = 'Try pro version free!'; -$lang->misc->zentao->about['official'] = "Official site"; -$lang->misc->zentao->about['changelog'] = "Change log"; -$lang->misc->zentao->about['license'] = "License"; -$lang->misc->zentao->about['extension'] = "Extensions"; - -$lang->misc->zentao->support['vip'] = "Business"; -$lang->misc->zentao->support['manual'] = "Manual"; -$lang->misc->zentao->support['faq'] = "FAQ"; -$lang->misc->zentao->support['ask'] = "Ask"; -$lang->misc->zentao->support['qqgroup'] = "QQ Group"; - -$lang->misc->zentao->cowin['donate'] = "Donate"; -$lang->misc->zentao->cowin['reportbug'] = "Report bug"; -$lang->misc->zentao->cowin['feedback'] = "Feedback feature"; -$lang->misc->zentao->cowin['recommend'] = "Recommend"; -$lang->misc->zentao->cowin['cowinmore'] = "More..."; - -$lang->misc->zentao->service['zentaotrain']= 'ZenTao training'; -$lang->misc->zentao->service['scrumtrain'] = 'Agile training'; -$lang->misc->zentao->service['idc'] = 'ZenTao online'; -$lang->misc->zentao->service['custom'] = 'custom develop'; -$lang->misc->zentao->service['install'] = 'Install service'; -$lang->misc->zentao->service['fixissue'] = 'Issue support'; -$lang->misc->zentao->service['servicemore']= 'More...'; - -$lang->misc->copyright = "Copyright ©2009-2012 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 = new stdclass(); +$lang->misc->common = 'Misc'; +$lang->misc->ping = 'Keep session'; + +$lang->misc->zentao = new stdclass(); +$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['proversion'] = 'Try pro version free!'; +$lang->misc->zentao->about['official'] = "Official site"; +$lang->misc->zentao->about['changelog'] = "Change log"; +$lang->misc->zentao->about['license'] = "License"; +$lang->misc->zentao->about['extension'] = "Extensions"; + +$lang->misc->zentao->support['vip'] = "Business"; +$lang->misc->zentao->support['manual'] = "Manual"; +$lang->misc->zentao->support['faq'] = "FAQ"; +$lang->misc->zentao->support['ask'] = "Ask"; +$lang->misc->zentao->support['qqgroup'] = "QQ Group"; + +$lang->misc->zentao->cowin['donate'] = "Donate"; +$lang->misc->zentao->cowin['reportbug'] = "Report bug"; +$lang->misc->zentao->cowin['feedback'] = "Feedback feature"; +$lang->misc->zentao->cowin['recommend'] = "Recommend"; +$lang->misc->zentao->cowin['cowinmore'] = "More..."; + +$lang->misc->zentao->service['zentaotrain']= 'ZenTao training'; +$lang->misc->zentao->service['scrumtrain'] = 'Agile training'; +$lang->misc->zentao->service['idc'] = 'ZenTao online'; +$lang->misc->zentao->service['custom'] = 'custom develop'; +$lang->misc->zentao->service['install'] = 'Install service'; +$lang->misc->zentao->service['fixissue'] = 'Issue support'; +$lang->misc->zentao->service['servicemore']= 'More...'; + +$lang->misc->copyright = "Copyright ©2009-2013 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 249af5756b..13b8043fe9 100644 --- a/module/misc/lang/zh-cn.php +++ b/module/misc/lang/zh-cn.php @@ -1,49 +1,49 @@ - - * @package misc - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->misc = new stdclass(); -$lang->misc->common = '杂项'; -$lang->misc->ping = '防超时'; - -$lang->misc->zentao = new stdclass(); -$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['proversion'] = '免费试用专业版本'; -$lang->misc->zentao->about['official'] = "官方网站"; -$lang->misc->zentao->about['changelog'] = "版本历史"; -$lang->misc->zentao->about['license'] = "授权协议"; -$lang->misc->zentao->about['extension'] = "插件平台"; - -$lang->misc->zentao->support['vip'] = "商业技术支持"; -$lang->misc->zentao->support['manual'] = "用户手册"; -$lang->misc->zentao->support['faq'] = "常见问题"; -$lang->misc->zentao->support['ask'] = "官方问答"; -$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; - -$lang->misc->zentao->cowin['donate'] = "捐助我们"; -$lang->misc->zentao->cowin['reportbug'] = "汇报Bug"; -$lang->misc->zentao->cowin['feedback'] = "反馈需求"; -$lang->misc->zentao->cowin['recommend'] = "推荐给朋友"; -$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; - -$lang->misc->zentao->service['zentaotrain']= '禅道使用培训'; -$lang->misc->zentao->service['scrumtrain'] = '敏捷开发培训'; -$lang->misc->zentao->service['idc'] = '禅道在线托管'; -$lang->misc->zentao->service['custom'] = '禅道定制开发'; -$lang->misc->zentao->service['install'] = '禅道安装服务'; -$lang->misc->zentao->service['fixissue'] = '禅道问题解决'; -$lang->misc->zentao->service['servicemore']= '更多服务...'; - -$lang->misc->copyright = "版权所有 ©2009-2012 青岛易软天创网络科技有限公司"; + + * @package misc + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->misc = new stdclass(); +$lang->misc->common = '杂项'; +$lang->misc->ping = '防超时'; + +$lang->misc->zentao = new stdclass(); +$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['proversion'] = '免费试用专业版本'; +$lang->misc->zentao->about['official'] = "官方网站"; +$lang->misc->zentao->about['changelog'] = "版本历史"; +$lang->misc->zentao->about['license'] = "授权协议"; +$lang->misc->zentao->about['extension'] = "插件平台"; + +$lang->misc->zentao->support['vip'] = "商业技术支持"; +$lang->misc->zentao->support['manual'] = "用户手册"; +$lang->misc->zentao->support['faq'] = "常见问题"; +$lang->misc->zentao->support['ask'] = "官方问答"; +$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; + +$lang->misc->zentao->cowin['donate'] = "捐助我们"; +$lang->misc->zentao->cowin['reportbug'] = "汇报Bug"; +$lang->misc->zentao->cowin['feedback'] = "反馈需求"; +$lang->misc->zentao->cowin['recommend'] = "推荐给朋友"; +$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; + +$lang->misc->zentao->service['zentaotrain']= '禅道使用培训'; +$lang->misc->zentao->service['scrumtrain'] = '敏捷开发培训'; +$lang->misc->zentao->service['idc'] = '禅道在线托管'; +$lang->misc->zentao->service['custom'] = '禅道定制开发'; +$lang->misc->zentao->service['install'] = '禅道安装服务'; +$lang->misc->zentao->service['fixissue'] = '禅道问题解决'; +$lang->misc->zentao->service['servicemore']= '更多服务...'; + +$lang->misc->copyright = "版权所有 ©2009-2013 青岛易软天创网络科技有限公司"; diff --git a/module/misc/lang/zh-tw.php b/module/misc/lang/zh-tw.php index 2e71988b2a..a874ec3e55 100644 --- a/module/misc/lang/zh-tw.php +++ b/module/misc/lang/zh-tw.php @@ -1,49 +1,49 @@ - - * @package misc - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @link http://www.zentao.net - */ -$lang->misc = new stdclass(); -$lang->misc->common = '雜項'; -$lang->misc->ping = '防超時'; - -$lang->misc->zentao = new stdclass(); -$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['proversion'] = '免費試用專業版本'; -$lang->misc->zentao->about['official'] = "官方網站"; -$lang->misc->zentao->about['changelog'] = "版本歷史"; -$lang->misc->zentao->about['license'] = "授權協議"; -$lang->misc->zentao->about['extension'] = "插件平台"; - -$lang->misc->zentao->support['vip'] = "商業技術支持"; -$lang->misc->zentao->support['manual'] = "用戶手冊"; -$lang->misc->zentao->support['faq'] = "常見問題"; -$lang->misc->zentao->support['ask'] = "官方問答"; -$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; - -$lang->misc->zentao->cowin['donate'] = "捐助我們"; -$lang->misc->zentao->cowin['reportbug'] = "彙報Bug"; -$lang->misc->zentao->cowin['feedback'] = "反饋需求"; -$lang->misc->zentao->cowin['recommend'] = "推薦給朋友"; -$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; - -$lang->misc->zentao->service['zentaotrain']= '禪道使用培訓'; -$lang->misc->zentao->service['scrumtrain'] = '敏捷開發培訓'; -$lang->misc->zentao->service['idc'] = '禪道在綫託管'; -$lang->misc->zentao->service['custom'] = '禪道定製開發'; -$lang->misc->zentao->service['install'] = '禪道安裝服務'; -$lang->misc->zentao->service['fixissue'] = '禪道問題解決'; -$lang->misc->zentao->service['servicemore']= '更多服務...'; - -$lang->misc->copyright = "版權所有 ©2009-2012 青島易軟天創網絡科技有限公司"; + + * @package misc + * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ + * @link http://www.zentao.net + */ +$lang->misc = new stdclass(); +$lang->misc->common = '雜項'; +$lang->misc->ping = '防超時'; + +$lang->misc->zentao = new stdclass(); +$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['proversion'] = '免費試用專業版本'; +$lang->misc->zentao->about['official'] = "官方網站"; +$lang->misc->zentao->about['changelog'] = "版本歷史"; +$lang->misc->zentao->about['license'] = "授權協議"; +$lang->misc->zentao->about['extension'] = "插件平台"; + +$lang->misc->zentao->support['vip'] = "商業技術支持"; +$lang->misc->zentao->support['manual'] = "用戶手冊"; +$lang->misc->zentao->support['faq'] = "常見問題"; +$lang->misc->zentao->support['ask'] = "官方問答"; +$lang->misc->zentao->support['qqgroup'] = "官方QQ群"; + +$lang->misc->zentao->cowin['donate'] = "捐助我們"; +$lang->misc->zentao->cowin['reportbug'] = "彙報Bug"; +$lang->misc->zentao->cowin['feedback'] = "反饋需求"; +$lang->misc->zentao->cowin['recommend'] = "推薦給朋友"; +$lang->misc->zentao->cowin['cowinmore'] = "更多方式..."; + +$lang->misc->zentao->service['zentaotrain']= '禪道使用培訓'; +$lang->misc->zentao->service['scrumtrain'] = '敏捷開發培訓'; +$lang->misc->zentao->service['idc'] = '禪道在綫託管'; +$lang->misc->zentao->service['custom'] = '禪道定製開發'; +$lang->misc->zentao->service['install'] = '禪道安裝服務'; +$lang->misc->zentao->service['fixissue'] = '禪道問題解決'; +$lang->misc->zentao->service['servicemore']= '更多服務...'; + +$lang->misc->copyright = "版權所有 ©2009-2013 青島易軟天創網絡科技有限公司"; diff --git a/module/misc/model.php b/module/misc/model.php index 8ac651eb2d..b636187799 100644 --- a/module/misc/model.php +++ b/module/misc/model.php @@ -1,20 +1,20 @@ - - * @package misc - * @version $Id$ - * @link http://www.zentao.net - */ -?> -'; - } -} + + * @package misc + * @version $Id$ + * @link http://www.zentao.net + */ +?> +'; + } +} diff --git a/module/my/control.php b/module/my/control.php index d7335ed522..7dc016c2fb 100644 --- a/module/my/control.php +++ b/module/my/control.php @@ -1,467 +1,467 @@ - - * @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($recTotal = 1000, $this->config->my->dynamicCounts); // Init the $recTotal var, thus omit one sql query. - - $this->view->projectStats = $projectStats; - $this->view->productStats = $productStats; - $this->view->actions = $this->loadModel('action')->getDynamic('all', 'latest3days', '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->stories = $this->loadModel('story')->getUserStoryPairs($account, $this->config->my->storyCounts); - $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 - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function todo($type = 'today', $account = '', $status = 'all', $orderBy="date, status, begin", $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $uri = $this->app->getURI(true); - $this->session->set('todoList', $uri); - $this->session->set('bugList', $uri); - $this->session->set('taskList', $uri); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* 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->todos = $this->loadModel('todo')->getList($type, $account, $status, 0, $pager, $orderBy); - $this->view->date = (int)$type == 0 ? date(DT_DATE1) : date(DT_DATE1, strtotime($type)); - $this->view->type = is_numeric($type) ? 'bydate' : $type; - $this->view->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->status = $status; - $this->view->account = $this->app->user->account; - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $this->view->importFuture = ($type != 'today'); - - $this->display(); - } - - /** - * My stories - - * @param string $type - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function story($type = 'assignedto', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $this->session->set('storyList', $this->app->getURI(true)); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* 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, $orderBy, $pager); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->type = $type; - $this->view->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * My tasks - * - * @param string $type - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function task($type = 'assignedto', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save session. */ - $this->session->set('taskList', $this->app->getURI(true)); - $this->session->set('storyList', $this->app->getURI(true)); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* 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, 0, $pager, $orderBy); - $this->view->type = $type; - $this->view->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->pager = $pager; - $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($orderBy)->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(); - } - - /* Save bugIDs session for get the pre and next bug. */ - $bugIDs = ''; - foreach($bugs as $bug) $bugIDs .= ',' . $bug->id; - $this->session->set('bugIDs', $bugIDs . ','); - - /* 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->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * My test task. - * - * @access public - * @return void - */ - public function testtask($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* 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, $pager, $orderBy); - - $this->view->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $this->view->pager = $pager; - $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(); - } - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase'); - - /* 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->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $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(); - } - - /** - * Change password - * - * @access public - * @return void - */ - public function changePassword() - { - if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); - if(!empty($_POST)) - { - $this->user->updatePassword($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->changePassword; - $this->view->position[] = $this->lang->my->changePassword; - $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->recTotal = $recTotal; - $this->view->recPerPage = $recPerPage; - $this->view->pageID = $pageID; - $this->view->orderBy = $orderBy; - $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($recTotal = 1000, $this->config->my->dynamicCounts); // Init the $recTotal var, thus omit one sql query. + + $this->view->projectStats = $projectStats; + $this->view->productStats = $productStats; + $this->view->actions = $this->loadModel('action')->getDynamic('all', 'latest3days', '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->stories = $this->loadModel('story')->getUserStoryPairs($account, $this->config->my->storyCounts); + $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 + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function todo($type = 'today', $account = '', $status = 'all', $orderBy="date, status, begin", $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $uri = $this->app->getURI(true); + $this->session->set('todoList', $uri); + $this->session->set('bugList', $uri); + $this->session->set('taskList', $uri); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* 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->todos = $this->loadModel('todo')->getList($type, $account, $status, 0, $pager, $orderBy); + $this->view->date = (int)$type == 0 ? date(DT_DATE1) : date(DT_DATE1, strtotime($type)); + $this->view->type = is_numeric($type) ? 'bydate' : $type; + $this->view->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->status = $status; + $this->view->account = $this->app->user->account; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $this->view->importFuture = ($type != 'today'); + + $this->display(); + } + + /** + * My stories + + * @param string $type + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function story($type = 'assignedto', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $this->session->set('storyList', $this->app->getURI(true)); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* 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, $orderBy, $pager); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->type = $type; + $this->view->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * My tasks + * + * @param string $type + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function task($type = 'assignedto', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save session. */ + $this->session->set('taskList', $this->app->getURI(true)); + $this->session->set('storyList', $this->app->getURI(true)); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* 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, 0, $pager, $orderBy); + $this->view->type = $type; + $this->view->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->pager = $pager; + $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($orderBy)->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(); + } + + /* Save bugIDs session for get the pre and next bug. */ + $bugIDs = ''; + foreach($bugs as $bug) $bugIDs .= ',' . $bug->id; + $this->session->set('bugIDs', $bugIDs . ','); + + /* 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->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * My test task. + * + * @access public + * @return void + */ + public function testtask($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* 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, $pager, $orderBy); + + $this->view->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $this->view->pager = $pager; + $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(); + } + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase'); + + /* 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->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $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(); + } + + /** + * Change password + * + * @access public + * @return void + */ + public function changePassword() + { + if($this->app->user->account == 'guest') die(js::alert('guest') . js::locate('back')); + if(!empty($_POST)) + { + $this->user->updatePassword($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->changePassword; + $this->view->position[] = $this->lang->my->changePassword; + $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->recTotal = $recTotal; + $this->view->recPerPage = $recPerPage; + $this->view->pageID = $pageID; + $this->view->orderBy = $orderBy; + $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 0376969bfe..35d53b2c56 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -1,46 +1,46 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> -lang->my->menu->account = sprintf($this->lang->my->menu->account, $this->app->user->realname); - - /* Adjust the menu order according to the user role. */ - $role = $this->app->user->role; - if($role == 'qa') - { - unset($this->lang->my->menuOrder[20]); - $this->lang->my->menuOrder[32] = 'task'; - } - elseif($role == 'po') - { - unset($this->lang->my->menuOrder[35]); - unset($this->lang->my->menuOrder[20]); - $this->lang->my->menuOrder[17] = 'story'; - $this->lang->my->menuOrder[42] = 'task'; - } - elseif($role == 'pm') - { - unset($this->lang->my->menuOrder[40]); - $this->lang->my->menuOrder[17] = 'myProject'; - } - } -} + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> +lang->my->menu->account = sprintf($this->lang->my->menu->account, $this->app->user->realname); + + /* Adjust the menu order according to the user role. */ + $role = $this->app->user->role; + if($role == 'qa') + { + unset($this->lang->my->menuOrder[20]); + $this->lang->my->menuOrder[32] = 'task'; + } + elseif($role == 'po') + { + unset($this->lang->my->menuOrder[35]); + unset($this->lang->my->menuOrder[20]); + $this->lang->my->menuOrder[17] = 'story'; + $this->lang->my->menuOrder[42] = 'task'; + } + elseif($role == 'pm') + { + unset($this->lang->my->menuOrder[40]); + $this->lang->my->menuOrder[17] = 'myProject'; + } + } +} diff --git a/module/my/view/bug.html.php b/module/my/view/bug.html.php index 2e9eaedd06..2786cd8504 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->severityList[$bug->severity]) ? $lang->bug->severityList[$bug->severity] : $bug->severity;?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]) ? $lang->bug->priList[$bug->pri] : $bug->pri?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> - id"; - common::printIcon('bug', 'resolve', $params, $bug, 'list'); - common::printIcon('bug', 'close', $params, $bug, 'list'); - common::printIcon('bug', 'edit', $params, '', 'list'); - ?> -
          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->severityList[$bug->severity]) ? $lang->bug->severityList[$bug->severity] : $bug->severity;?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]) ? $lang->bug->priList[$bug->pri] : $bug->pri?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> + id"; + common::printIcon('bug', 'resolve', $params, $bug, 'list'); + common::printIcon('bug', 'close', $params, $bug, 'list'); + common::printIcon('bug', 'edit', $params, '', 'list'); + ?> +
          show();?>
          + + diff --git a/module/my/view/changepassword.html.php b/module/my/view/changepassword.html.php index 3abefc8917..eb7d88ed70 100755 --- a/module/my/view/changepassword.html.php +++ b/module/my/view/changepassword.html.php @@ -1,34 +1,34 @@ - - * @package user - * @version $Id: editprofile.html.php 2605 2012-02-21 07:22:58Z wwccss $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - - - - -
          my->changePassword;?>
          user->account;?>account . html::hidden('account',$user->account);?>
          user->password;?>
          user->password2;?>
          -
          - + + * @package user + * @version $Id: editprofile.html.php 2605 2012-02-21 07:22:58Z wwccss $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + + + + +
          my->changePassword;?>
          user->account;?>account . html::hidden('account',$user->account);?>
          user->password;?>
          user->password2;?>
          +
          + diff --git a/module/my/view/dynamic.html.php b/module/my/view/dynamic.html.php index 877e23774e..888f5a3191 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-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();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2013 青岛易软天创网络科技有限公司 (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 3a2d024ea2..66b4932a4d 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 3faf5b4613..f1fc84297a 100644 --- a/module/my/view/index.html.php +++ b/module/my/view/index.html.php @@ -1,41 +1,41 @@ - - * @package ZenTaoPMS - * @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $ - */ -?> - - - -version);?> - - - - - -
          -
          - -
          - - - - user->role and strpos('qa|qd', $app->user->role) !== false):?> - - - user->role and strpos('po|pd', $app->user->role) !== false):?> - - - - - - - -
          -global->flow) or strpos($this->config->version, 'pro') !== false or strpos($this->app->company->admins, ",{$this->app->user->account},") === false)) js::set('flow', 'true', 'number');?> - + + * @package ZenTaoPMS + * @version $Id: index.html.php 1947 2011-06-29 11:58:03Z wwccss $ + */ +?> + + + +version);?> + + + + + +
          +
          + +
          + + + + user->role and strpos('qa|qd', $app->user->role) !== false):?> + + + user->role and strpos('po|pd', $app->user->role) !== false):?> + + + + + + + +
          +global->flow) or strpos($this->config->version, 'pro') !== false or strpos($this->app->company->admins, ",{$this->app->user->account},") === false)) js::set('flow', 'true', 'number');?> + diff --git a/module/my/view/profile.html.php b/module/my/view/profile.html.php index ee5174f224..3c12e1528f 100644 --- a/module/my/view/profile.html.php +++ b/module/my/view/profile.html.php @@ -1,124 +1,124 @@ - - * @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->role;?>user->roleList[$user->role];?>
          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->role;?>user->roleList[$user->role];?>
          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 e05ec7cf72..9acb67f9b6 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 30f54ae3b9..f3788b2f5f 100644 --- a/module/my/view/story.html.php +++ b/module/my/view/story.html.php @@ -1,66 +1,66 @@ - - * @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;?>'>pri?>productTitle;?>title);?>planTitle;?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - id", $story, 'list'); - common::printIcon('story', 'review', "storyID=$story->id", $story, 'list'); - common::printIcon('story', 'close', "storyID=$story->id", $story, 'list'); - ?> -
          show();?>
          - - + + * @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;?>'>pri?>productTitle;?>title);?>planTitle;?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + id", $story, 'list'); + common::printIcon('story', 'review', "storyID=$story->id", $story, 'list'); + common::printIcon('story', 'close', "storyID=$story->id", $story, 'list'); + ?> +
          show();?>
          + + diff --git a/module/my/view/task.html.php b/module/my/view/task.html.php index 45abd6879a..c2ce06c5cb 100644 --- a/module/my/view/task.html.php +++ b/module/my/view/task.html.php @@ -1,87 +1,87 @@ - - * @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];?>'>task->priList[$task->pri]) ? $lang->task->priList[$task->pri] : $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];?> - id", $task, 'list'); - common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list'); - common::printIcon('task', 'close', "taskID=$task->id", $task, 'list'); - common::printIcon('task', 'activate', "taskID=$task->id", $task, 'list'); - ?> -
          - -
          close)?>
          - - show();?> -
          -';?> - + + * @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];?>'>task->priList[$task->pri]) ? $lang->task->priList[$task->pri] : $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];?> + id", $task, 'list'); + common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list'); + common::printIcon('task', 'close', "taskID=$task->id", $task, 'list'); + common::printIcon('task', 'activate', "taskID=$task->id", $task, 'list'); + ?> +
          + +
          close)?>
          + + show();?> +
          +';?> + diff --git a/module/my/view/team.html.php b/module/my/view/team.html.php index 95c5ad5ce6..a90904d650 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 93cbbbdd97..5873f8a9af 100644 --- a/module/my/view/testcase.html.php +++ b/module/my/view/testcase.html.php @@ -1,55 +1,55 @@ - - * @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?>'>pri?> - createLink('testcase', 'view', "testcaseID=$case->id"), $case->title);?>testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?>id", '', 'list');?>
          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?>'>pri?> + createLink('testcase', 'view', "testcaseID=$case->id"), $case->title);?>testcase->typeList[$case->type];?>openedBy];?>testcase->statusList[$case->status];?>id", '', 'list');?>
          show();?>
          + + diff --git a/module/my/view/testtask.html.php b/module/my/view/testtask.html.php index e5ed15006a..4df580f5ff 100644 --- a/module/my/view/testtask.html.php +++ b/module/my/view/testtask.html.php @@ -1,61 +1,61 @@ - - * @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::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); - common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', 'hiddenwin'); - ?> -
          show();?>
          - - + + * @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::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); + common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', 'hiddenwin'); + ?> +
          show();?>
          + + diff --git a/module/my/view/todo.html.php b/module/my/view/todo.html.php index e353b800fd..8eee6f3558 100644 --- a/module/my/view/todo.html.php +++ b/module/my/view/todo.html.php @@ -1,126 +1,126 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes';?> - -
          -
          - ' . html::a(inlink('todo', "date=today"), $lang->todo->todayTodos) . ''; - echo ''. html::a(inlink('todo', "date=yesterday"), $lang->todo->yesterdayTodos). ''; - 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=thismonth"), $lang->todo->thismonthTodos). ''; - echo '' . html::a(inlink('todo', "date=lastmonth"), $lang->todo->lastmonthTodos). ''; - echo ''. html::a(inlink('todo', "date=thisseason"),$lang->todo->thisseasonTodos).''; - echo '' . html::a(inlink('todo', "date=thisyear"), $lang->todo->thisyearTodos) . ''; - 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::input('date', $date,"class='w-date date' onchange='changeDate(this.value)'") . ''; - - if($type == 'bydate') - { - if($date == date('Y-m-d')) - { - $type = 'today'; - } - else if($date == date('Y-m-d', strtotime('-1 day'))) - { - $type = 'yesterday'; - } - } - ?> - -
          -
          - -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB);?>todo->date);?>todo->type);?> priAB);?> todo->name);?>todo->beginAB);?>todo->endAB);?>todo->status);?>actions;?>
          - - - - id; ?> - date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList[$todo->type];?>pri;?>'>pri?>createLink('todo', 'view', "id=$todo->id&from=my") . $onlybody, $todo->name, '', "class='colorbox'");?>begin;?>end;?>todo->statusList[$todo->status];?> - createLink('todo', 'mark', "id=$todo->id&status=$todo->status"), $lang->todo->{'mark'.ucfirst($todo->status)}, 'hiddenwin'); - common::printIcon('todo', 'edit', "id=$todo->id", '', 'list'); - common::printIcon('todo', 'delete', "id=$todo->id", '', 'list', '', 'hiddenwin'); - ?> -
          -
          - createLink('todo', 'batchEdit', "from=myTodo&type=$type&account=$account&status=$status"); - echo html::commonButton($lang->todo->batchEdit, "onclick=\"changeAction('todoform', 'batchEdit', '$actionLink')\""); - - } - if(common::hasPriv('todo', 'import2Today') and $importFuture) - { - $actionLink = $this->createLink('todo', 'import2Today'); - echo html::commonButton($lang->todo->import2Today, "onclick=\"changeAction('todoform', 'import2Today', '$actionLink')\""); - } - ?> -
          - show();?> -
          -
          - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes';?> +
          +
          +
          + ' . html::a(inlink('todo', "date=today"), $lang->todo->todayTodos) . ''; + echo ''. html::a(inlink('todo', "date=yesterday"), $lang->todo->yesterdayTodos). ''; + 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=thismonth"), $lang->todo->thismonthTodos). ''; + echo '' . html::a(inlink('todo', "date=lastmonth"), $lang->todo->lastmonthTodos). ''; + echo ''. html::a(inlink('todo', "date=thisseason"),$lang->todo->thisseasonTodos).''; + echo '' . html::a(inlink('todo', "date=thisyear"), $lang->todo->thisyearTodos) . ''; + 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::input('date', $date,"class='w-date date' onchange='changeDate(this.value)'") . ''; + + if($type == 'bydate') + { + if($date == date('Y-m-d')) + { + $type = 'today'; + } + else if($date == date('Y-m-d', strtotime('-1 day'))) + { + $type = 'yesterday'; + } + } + ?> + +
          +
          + +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB);?>todo->date);?>todo->type);?> priAB);?> todo->name);?>todo->beginAB);?>todo->endAB);?>todo->status);?>actions;?>
          + + + + id; ?> + date == '2030-01-01' ? $lang->todo->dayInFuture : $todo->date;?>todo->typeList[$todo->type];?>pri;?>'>pri?>createLink('todo', 'view', "id=$todo->id&from=my") . $onlybody, $todo->name, '', "class='colorbox'");?>begin;?>end;?>todo->statusList[$todo->status];?> + createLink('todo', 'mark', "id=$todo->id&status=$todo->status"), $lang->todo->{'mark'.ucfirst($todo->status)}, 'hiddenwin'); + common::printIcon('todo', 'edit', "id=$todo->id", '', 'list'); + common::printIcon('todo', 'delete', "id=$todo->id", '', 'list', '', 'hiddenwin'); + ?> +
          +
          + createLink('todo', 'batchEdit', "from=myTodo&type=$type&account=$account&status=$status"); + echo html::commonButton($lang->todo->batchEdit, "onclick=\"changeAction('todoform', 'batchEdit', '$actionLink')\""); + + } + if(common::hasPriv('todo', 'import2Today') and $importFuture) + { + $actionLink = $this->createLink('todo', 'import2Today'); + echo html::commonButton($lang->todo->import2Today, "onclick=\"changeAction('todoform', 'import2Today', '$actionLink')\""); + } + ?> +
          + show();?> +
          +
          + diff --git a/module/product/control.php b/module/product/control.php index 70654fe0e2..cc9d4e3905 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -1,448 +1,448 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -class product extends control -{ - public $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', $this->methodName) === false) $this->locate($this->createLink('product', 'create')); - $this->view->products = $this->products; - } - - /** - * Index page, to browse. - * - * @param string $locate locate to browse page or not. If not, display all products. - * @param int $productID - * @access public - * @return void - */ - public function index($locate = 'yes', $productID = 0) - { - if($locate == 'yes') $this->locate($this->createLink($this->moduleName, 'browse')); - - $this->session->set('productList', $this->app->getURI(true)); - $this->product->setMenu($this->products, $productID); - - $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->product->setMenu($this->products, $productID); - - $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->products[$productID]. $this->lang->colon . $this->lang->product->browse; - $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); - - /* Process the sql, get the conditon partion, save it to session. */ - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - - /* 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->loadModel('search')->setSearchParams($this->config->product->search); - - $this->view->productID = $productID; - $this->view->productName = $this->products[$productID]; - $this->view->moduleID = $moduleID; - $this->view->stories = $stories; - $this->view->summary = $this->product->summary($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->poUsers = $this->loadModel('user')->getPairs('nodeleted|pofirst'); - $this->view->qdUsers = $this->loadModel('user')->getPairs('nodeleted|qdfirst'); - $this->view->rdUsers = $this->loadModel('user')->getPairs('nodeleted|devfirst'); - $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->poUsers = $this->loadModel('user')->getPairs('nodeleted|pofirst'); - $this->view->qdUsers = $this->loadModel('user')->getPairs('nodeleted|qdfirst'); - $this->view->rdUsers = $this->loadModel('user')->getPairs('nodeleted|devfirst'); - - $this->display(); - } - - /** - * Close product. - * - * @param int $productID - * @access public - * @return void - */ - public function close($productID) - { - $product = $this->product->getById($productID); - $actions = $this->loadModel('action')->getList('product', $productID); - - if(!empty($_POST)) - { - $changes = $this->product->close($productID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('product', $productID, 'Closed', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('product', 'view', "productID=$productID"), 'parent')); - } - - $this->product->setMenu($this->products, $productID); - - $this->view->product = $product; - $this->view->header->title = $this->view->product->name . $this->lang->colon .$this->lang->close; - $this->view->position[] = $this->lang->close; - $this->view->actions = $actions; - $this->display(); - } - - /** - * View a product. - * - * @param int $productID - * @access public - * @return void - */ - public function view($productID) - { - $this->product->setMenu($this->products, $productID); - - $product = $this->product->getStatByID($productID); - $product->desc = $this->loadModel('file')->setImgSize($product->desc); - if(!$product) die(js::error($this->lang->notFound) . js::locate('back')); - - $this->view->header->title = $product->name . ' - ' . $this->lang->product->view; - $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 = $product->name . $this->lang->colon . $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 = $product->name . $this->lang->colon . $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->products[$productID] . $this->lang->colon . $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(); - } - - /** - * order product - * - * @param int $productID - * @access public - * @return void - */ - public function order($productID) - { - if($_POST) - { - $this->product->saveOrder(); - die(js::reload('parent')); - } - $this->product->setMenu($this->products, $productID); - $this->view->products = $this->product->getList('noclosed'); - $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, $params = 'nodeleted'); - die(html::select('project', $projects, $projectID, 'class=select-3 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 +{ + public $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', $this->methodName) === false) $this->locate($this->createLink('product', 'create')); + $this->view->products = $this->products; + } + + /** + * Index page, to browse. + * + * @param string $locate locate to browse page or not. If not, display all products. + * @param int $productID + * @access public + * @return void + */ + public function index($locate = 'yes', $productID = 0) + { + if($locate == 'yes') $this->locate($this->createLink($this->moduleName, 'browse')); + + $this->session->set('productList', $this->app->getURI(true)); + $this->product->setMenu($this->products, $productID); + + $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->product->setMenu($this->products, $productID); + + $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->products[$productID]. $this->lang->colon . $this->lang->product->browse; + $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); + + /* Process the sql, get the conditon partion, save it to session. */ + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + + /* 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->loadModel('search')->setSearchParams($this->config->product->search); + + $this->view->productID = $productID; + $this->view->productName = $this->products[$productID]; + $this->view->moduleID = $moduleID; + $this->view->stories = $stories; + $this->view->summary = $this->product->summary($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->poUsers = $this->loadModel('user')->getPairs('nodeleted|pofirst'); + $this->view->qdUsers = $this->loadModel('user')->getPairs('nodeleted|qdfirst'); + $this->view->rdUsers = $this->loadModel('user')->getPairs('nodeleted|devfirst'); + $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->poUsers = $this->loadModel('user')->getPairs('nodeleted|pofirst'); + $this->view->qdUsers = $this->loadModel('user')->getPairs('nodeleted|qdfirst'); + $this->view->rdUsers = $this->loadModel('user')->getPairs('nodeleted|devfirst'); + + $this->display(); + } + + /** + * Close product. + * + * @param int $productID + * @access public + * @return void + */ + public function close($productID) + { + $product = $this->product->getById($productID); + $actions = $this->loadModel('action')->getList('product', $productID); + + if(!empty($_POST)) + { + $changes = $this->product->close($productID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('product', $productID, 'Closed', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('product', 'view', "productID=$productID"), 'parent')); + } + + $this->product->setMenu($this->products, $productID); + + $this->view->product = $product; + $this->view->header->title = $this->view->product->name . $this->lang->colon .$this->lang->close; + $this->view->position[] = $this->lang->close; + $this->view->actions = $actions; + $this->display(); + } + + /** + * View a product. + * + * @param int $productID + * @access public + * @return void + */ + public function view($productID) + { + $this->product->setMenu($this->products, $productID); + + $product = $this->product->getStatByID($productID); + $product->desc = $this->loadModel('file')->setImgSize($product->desc); + if(!$product) die(js::error($this->lang->notFound) . js::locate('back')); + + $this->view->header->title = $product->name . ' - ' . $this->lang->product->view; + $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 = $product->name . $this->lang->colon . $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 = $product->name . $this->lang->colon . $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->products[$productID] . $this->lang->colon . $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(); + } + + /** + * order product + * + * @param int $productID + * @access public + * @return void + */ + public function order($productID) + { + if($_POST) + { + $this->product->saveOrder(); + die(js::reload('parent')); + } + $this->product->setMenu($this->products, $productID); + $this->view->products = $this->product->getList('noclosed'); + $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, $params = 'nodeleted'); + die(html::select('project', $projects, $projectID, 'class=select-3 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 a0cde2d5b9..b8195b7098 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -1,85 +1,85 @@ - - * @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->basicInfo = 'Basic info'; -$lang->product->otherInfo = 'Other info'; - -$lang->product->plans = 'Plans'; -$lang->product->releases = 'Releases'; -$lang->product->docs = 'Documents'; -$lang->product->bugs = 'Bugs'; -$lang->product->projects = 'Projects'; -$lang->product->cases = 'Cases'; -$lang->product->bulids = 'Bulids'; -$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->QD = 'Quality director'; -$lang->product->RD = 'Release director'; -$lang->product->acl = 'Access limitation'; -$lang->product->whitelist = 'Whitelist'; - -$lang->product->moduleStory = 'Module'; -$lang->product->searchStory = 'Search'; -$lang->product->assignedToMe = 'To me'; -$lang->product->openedByMe = 'My opened'; -$lang->product->reviewedByMe = 'My reviewed'; -$lang->product->closedByMe = 'My closed'; -$lang->product->draftStory = 'Draft'; -$lang->product->activeStory = 'Active'; -$lang->product->changedStory = 'Changed'; -$lang->product->closedStory = 'Closed'; - -$lang->product->allStory = 'All'; -$lang->product->allProduct = 'All products'; -$lang->product->allProductsOfProject = 'All related 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->basicInfo = 'Basic info'; +$lang->product->otherInfo = 'Other info'; + +$lang->product->plans = 'Plans'; +$lang->product->releases = 'Releases'; +$lang->product->docs = 'Documents'; +$lang->product->bugs = 'Bugs'; +$lang->product->projects = 'Projects'; +$lang->product->cases = 'Cases'; +$lang->product->bulids = 'Bulids'; +$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->QD = 'Quality director'; +$lang->product->RD = 'Release director'; +$lang->product->acl = 'Access limitation'; +$lang->product->whitelist = 'Whitelist'; + +$lang->product->moduleStory = 'Module'; +$lang->product->searchStory = 'Search'; +$lang->product->assignedToMe = 'To me'; +$lang->product->openedByMe = 'My opened'; +$lang->product->reviewedByMe = 'My reviewed'; +$lang->product->closedByMe = 'My closed'; +$lang->product->draftStory = 'Draft'; +$lang->product->activeStory = 'Active'; +$lang->product->changedStory = 'Changed'; +$lang->product->closedStory = 'Closed'; + +$lang->product->allStory = 'All'; +$lang->product->allProduct = 'All products'; +$lang->product->allProductsOfProject = 'All related 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 de11623960..7b3477e347 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -1,85 +1,85 @@ - - * @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->basicInfo = '基本信息'; -$lang->product->otherInfo = '其他信息'; - -$lang->product->plans = '计划数'; -$lang->product->releases = '发布数'; -$lang->product->docs = '文档数'; -$lang->product->bugs = '相关BUG'; -$lang->product->projects = '关联项目数'; -$lang->product->cases = '用例数'; -$lang->product->bulids = 'BULID数'; -$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->QD = '测试负责人'; -$lang->product->RD = '发布负责人'; -$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->allProductsOfProject = '全部关联产品'; - -$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->basicInfo = '基本信息'; +$lang->product->otherInfo = '其他信息'; + +$lang->product->plans = '计划数'; +$lang->product->releases = '发布数'; +$lang->product->docs = '文档数'; +$lang->product->bugs = '相关BUG'; +$lang->product->projects = '关联项目数'; +$lang->product->cases = '用例数'; +$lang->product->bulids = 'BULID数'; +$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->QD = '测试负责人'; +$lang->product->RD = '发布负责人'; +$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->allProductsOfProject = '全部关联产品'; + +$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 0d9f5d4bff..90b4467e4f 100644 --- a/module/product/lang/zh-tw.php +++ b/module/product/lang/zh-tw.php @@ -1,85 +1,85 @@ - - * @package product - * @version $Id: zh-tw.php 3823 2012-12-17 07:06:29Z 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->basicInfo = '基本信息'; -$lang->product->otherInfo = '其他信息'; - -$lang->product->plans = '計劃數'; -$lang->product->releases = '發佈數'; -$lang->product->docs = '文檔數'; -$lang->product->bugs = '相關BUG'; -$lang->product->projects = '關聯項目數'; -$lang->product->cases = '用例數'; -$lang->product->bulids = 'BULID數'; -$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->QD = '測試負責人'; -$lang->product->RD = '發佈負責人'; -$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->allProductsOfProject = '全部關聯產品'; - -$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 3823 2012-12-17 07:06:29Z 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->basicInfo = '基本信息'; +$lang->product->otherInfo = '其他信息'; + +$lang->product->plans = '計劃數'; +$lang->product->releases = '發佈數'; +$lang->product->docs = '文檔數'; +$lang->product->bugs = '相關BUG'; +$lang->product->projects = '關聯項目數'; +$lang->product->cases = '用例數'; +$lang->product->bulids = 'BULID數'; +$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->QD = '測試負責人'; +$lang->product->RD = '發佈負責人'; +$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->allProductsOfProject = '全部關聯產品'; + +$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 bf0ba27d52..fd58cdf821 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -1,609 +1,609 @@ - - * @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' and $currentMethod != 'create') $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 : $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 = '') - { - $productMode = $this->cookie->productMode ? $this->cookie->productMode : 'all'; - $productGroup = array(); - $products = $this->dao->select('id, status, name')->from(TABLE_PRODUCT)->where('id')->in(array_keys($products))->orderBy('`order`')->fetchAll(); - foreach($products as $product) - { - if($productMode == 'noclosed' and $product->status == 'closed') continue; - if($product->status != 'closed') - { - $productGroup[' '][$product->id] = $product->name; - } - elseif($product->status == 'closed') - { - $productGroup[$this->lang->product->statusList['closed']][$product->id] = $product->name; - } - } - - /** - * 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\""; - $selectHtml = html::selectGroup('productID', $productGroup, $productID, "tabindex=2 $onchange"); - - 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; - } - - /** - * Save order - * - * @access public - * @return void - */ - public function saveOrder() - { - foreach($_POST as $productID => $order) - { - $this->dao->update(TABLE_PRODUCT)->set('`order`')->eq($order)->where('id')->eq($productID)->exec(); - } - } - - /** - * 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. */ - $privProducts = $this->getPrivProducts(); - return isset($privProducts[$product->id]) ? true : 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 = 'noclosed')->andWhere('status')->ne('closed')->fi() - ->beginIF($status != 'all' and $status != 'noclosed')->andWhere('status')->in($status)->fi() - ->beginIF($limit > 0)->limit($limit)->fi() - ->orderBy('`order` asc') - ->fetchAll('id'); - } - - /** - * Get product pairs. - * - * @param string $mode - * @return array - */ - public function getPairs($mode = '') - { - $orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed, `order`'; - $mode .= $this->cookie->productMode; - $products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed') - ->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); - } - - /** - * Close product. - * - * @param int $productID. - * @access public - * @return void - */ - public function close($productID) - { - $oldProduct = $this->getById($productID); - $now = helper::now(); - $product= fixer::input('post') - ->setDefault('status', 'closed') - ->remove('comment')->get(); - - $this->dao->update(TABLE_PRODUCT)->data($product) - ->autoCheck() - ->where('id')->eq((int)$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->QD] = $product->QD; - $members[$product->RD] = $product->RD; - $members[$product->createdBy] = $product->createdBy; - - /* Set projects and teams as static thus we can only query sql one times. */ - static $projects, $teams; - if(empty($projects)) - { - $projects = $this->dao->select('t1.project, t1.product')->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t2.deleted')->eq(0) - ->fetchGroup('product', 'project'); - } - if(empty($teams)) - { - $teams = $this->dao->select('t1.project, t1.account')->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t2.deleted')->eq(0) - ->fetchGroup('project', 'account'); - } - - if(!isset($projects[$product->id])) return $members; - $productProjects = $projects[$product->id]; - - $projectTeams = array(); - foreach(array_keys($productProjects) as $projectID) $projectTeams = array_merge($projectTeams, array_keys($teams[$projectID])); - - return array_flip(array_merge($members, $projectTeams)); - } - - /** - * Get product stat by id - * - * @param int $productID - * @access public - * @return object|bool - */ - public function getStatByID($productID) - { - $product = $this->getById($productID); - if(!$this->checkPriv($product)) return false; - $stories = $this->dao->select('product, status, count(status) AS count')->from(TABLE_STORY)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->groupBy('product, status')->fetchAll('status'); - /* Padding the stories to sure all status have records. */ - foreach(array_keys($this->lang->story->statusList) as $status) - { - $stories[$status] = isset($stories[$status]) ? $stories[$status]->count : 0; - } - - $plans = $this->dao->select('count(*) AS count')->from(TABLE_PRODUCTPLAN)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->andWhere('end')->gt(helper::now())->fetch(); - $bulids = $this->dao->select('count(*) AS count')->from(TABLE_BUILD)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); - $cases = $this->dao->select('count(*) AS count')->from(TABLE_CASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); - $bugs = $this->dao->select('count(*) AS count')->from(TABLE_BUG)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); - $docs = $this->dao->select('count(*) AS count')->from(TABLE_DOC)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); - $releases = $this->dao->select('count(*) AS count')->from(TABLE_RELEASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); - $projects = $this->dao->select('count("t1.*") AS count')->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t2.deleted')->eq(0) - ->andWhere('t1.product')->eq($productID) - ->fetch(); - - $product->stories = $stories; - $product->plans = $plans ? $plans->count : 0; - $product->releases = $releases ? $releases->count : 0; - $product->bulids = $bulids ? $bulids->count : 0; - $product->cases = $cases ? $cases->count : 0; - $product->projects = $projects ? $projects->count : 0; - $product->bugs = $bugs ? $bugs->count : 0; - $product->docs = $docs ? $docs->count : 0; - - return $product; - } - - /** - * Get product stats. - * - * @access public - * @return array - */ - public function getStats() - { - $this->loadModel('report'); - $this->loadModel('story'); - $this->loadModel('bug'); - - $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(); - - $bugs = $this->dao->select('product,count(*) AS conut') - ->from(TABLE_BUG) - ->where('deleted')->eq(0) - ->andWhere('product')->in(array_keys($products)) - ->groupBy('product') - ->fetchPairs(); - $unResolved = $this->dao->select('product,count(*) AS count') - ->from(TABLE_BUG) - ->where('status')->eq('active') - ->andwhere('deleted')->eq(0) - ->andWhere('product')->in(array_keys($products)) - ->groupBy('product') - ->fetchPairs(); - $assignToNull = $this->dao->select('product,count(*) AS count') - ->from(TABLE_BUG) - ->where('AssignedTo')->eq('') - ->andwhere('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; - - $product->bugs = isset($bugs[$product->id]) ? $bugs[$product->id] : 0; - $product->unResolved = isset($unResolved[$product->id]) ? $unResolved[$product->id] : 0; - $product->assignToNull = isset($assignToNull[$product->id]) ? $assignToNull[$product->id] : 0; - $stats[] = $product; - } - } - else - { - unset($products[$key]); - } - } - - return $stats; - } - - public function getPrivProducts() - { - $account = ',' . $this->app->user->account . ','; - static $products; - if($products === null) - { - $groupSql = ''; - foreach($this->app->user->groups as $group) $groupSql .= "INSTR(CONCAT(',', t1.whitelist, ','), ',$group,') > 0 OR "; - $groupSql = !empty($groupSql) ? '(' . substr($groupSql, 0, strlen($groupSql) - 4) . ')' : '1 != 1'; - $products = $this->dao->select('distinct t1.id')->from(TABLE_PRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') - ->leftJoin(TABLE_TEAM)->alias('t3')->on('t2.project = t3.project') - ->leftJoin(TABLE_PROJECT)->alias('t4')->on('t2.project = t4.id') - ->beginIF(strpos($this->app->company->admins, $account) !== false)->where('t1.deleted')->eq(0)->fi() - ->beginIF(strpos($this->app->company->admins, $account) === false) - ->where('t1.acl')->eq('open') - ->orWhere("(t1.acl = 'custom' AND $groupSql)") - ->orWhere('t1.PO')->eq($this->app->user->account) - ->orWhere('t1.QD')->eq($this->app->user->account) - ->orWhere('t1.RD')->eq($this->app->user->account) - ->orWhere('t1.createdBy')->eq($this->app->user->account) - ->orWhere('t3.account')->eq($this->app->user->account) - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t4.deleted')->eq(0) - ->fi() - ->fetchAll('id'); - } - return $products; - } - - /** - * Get the summary of product's stories. - * - * @param array $stories - * @access public - * @return string. - */ - public function summary($stories) - { - $totalEstimate = 0.0; - foreach($stories as $key => $story) $totalEstimate += $story->estimate; - return sprintf($this->lang->product->storySummary, count($stories), $totalEstimate); - } - - /** - * Judge an action is clickable or not. - * - * @param object $product - * @param string $action - * @access public - * @return void - */ - public function isClickable($product, $action) - { - $action = strtolower($action); - - if($action == 'close') return $product->status != 'closed'; - - return true; - } -} + + * @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' and $currentMethod != 'create') $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 : $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 = '') + { + $productMode = $this->cookie->productMode ? $this->cookie->productMode : 'all'; + $productGroup = array(); + $products = $this->dao->select('id, status, name')->from(TABLE_PRODUCT)->where('id')->in(array_keys($products))->orderBy('`order`')->fetchAll(); + foreach($products as $product) + { + if($productMode == 'noclosed' and $product->status == 'closed') continue; + if($product->status != 'closed') + { + $productGroup[' '][$product->id] = $product->name; + } + elseif($product->status == 'closed') + { + $productGroup[$this->lang->product->statusList['closed']][$product->id] = $product->name; + } + } + + /** + * 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\""; + $selectHtml = html::selectGroup('productID', $productGroup, $productID, "tabindex=2 $onchange"); + + 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; + } + + /** + * Save order + * + * @access public + * @return void + */ + public function saveOrder() + { + foreach($_POST as $productID => $order) + { + $this->dao->update(TABLE_PRODUCT)->set('`order`')->eq($order)->where('id')->eq($productID)->exec(); + } + } + + /** + * 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. */ + $privProducts = $this->getPrivProducts(); + return isset($privProducts[$product->id]) ? true : 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 = 'noclosed')->andWhere('status')->ne('closed')->fi() + ->beginIF($status != 'all' and $status != 'noclosed')->andWhere('status')->in($status)->fi() + ->beginIF($limit > 0)->limit($limit)->fi() + ->orderBy('`order` asc') + ->fetchAll('id'); + } + + /** + * Get product pairs. + * + * @param string $mode + * @return array + */ + public function getPairs($mode = '') + { + $orderBy = !empty($this->config->product->orderBy) ? $this->config->product->orderBy : 'isClosed, `order`'; + $mode .= $this->cookie->productMode; + $products = $this->dao->select('*, IF(INSTR(" closed", status) < 2, 0, 1) AS isClosed') + ->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); + } + + /** + * Close product. + * + * @param int $productID. + * @access public + * @return void + */ + public function close($productID) + { + $oldProduct = $this->getById($productID); + $now = helper::now(); + $product= fixer::input('post') + ->setDefault('status', 'closed') + ->remove('comment')->get(); + + $this->dao->update(TABLE_PRODUCT)->data($product) + ->autoCheck() + ->where('id')->eq((int)$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->QD] = $product->QD; + $members[$product->RD] = $product->RD; + $members[$product->createdBy] = $product->createdBy; + + /* Set projects and teams as static thus we can only query sql one times. */ + static $projects, $teams; + if(empty($projects)) + { + $projects = $this->dao->select('t1.project, t1.product')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t2.deleted')->eq(0) + ->fetchGroup('product', 'project'); + } + if(empty($teams)) + { + $teams = $this->dao->select('t1.project, t1.account')->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t2.deleted')->eq(0) + ->fetchGroup('project', 'account'); + } + + if(!isset($projects[$product->id])) return $members; + $productProjects = $projects[$product->id]; + + $projectTeams = array(); + foreach(array_keys($productProjects) as $projectID) $projectTeams = array_merge($projectTeams, array_keys($teams[$projectID])); + + return array_flip(array_merge($members, $projectTeams)); + } + + /** + * Get product stat by id + * + * @param int $productID + * @access public + * @return object|bool + */ + public function getStatByID($productID) + { + $product = $this->getById($productID); + if(!$this->checkPriv($product)) return false; + $stories = $this->dao->select('product, status, count(status) AS count')->from(TABLE_STORY)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->groupBy('product, status')->fetchAll('status'); + /* Padding the stories to sure all status have records. */ + foreach(array_keys($this->lang->story->statusList) as $status) + { + $stories[$status] = isset($stories[$status]) ? $stories[$status]->count : 0; + } + + $plans = $this->dao->select('count(*) AS count')->from(TABLE_PRODUCTPLAN)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->andWhere('end')->gt(helper::now())->fetch(); + $bulids = $this->dao->select('count(*) AS count')->from(TABLE_BUILD)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); + $cases = $this->dao->select('count(*) AS count')->from(TABLE_CASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); + $bugs = $this->dao->select('count(*) AS count')->from(TABLE_BUG)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); + $docs = $this->dao->select('count(*) AS count')->from(TABLE_DOC)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); + $releases = $this->dao->select('count(*) AS count')->from(TABLE_RELEASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetch(); + $projects = $this->dao->select('count("t1.*") AS count')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t2.deleted')->eq(0) + ->andWhere('t1.product')->eq($productID) + ->fetch(); + + $product->stories = $stories; + $product->plans = $plans ? $plans->count : 0; + $product->releases = $releases ? $releases->count : 0; + $product->bulids = $bulids ? $bulids->count : 0; + $product->cases = $cases ? $cases->count : 0; + $product->projects = $projects ? $projects->count : 0; + $product->bugs = $bugs ? $bugs->count : 0; + $product->docs = $docs ? $docs->count : 0; + + return $product; + } + + /** + * Get product stats. + * + * @access public + * @return array + */ + public function getStats() + { + $this->loadModel('report'); + $this->loadModel('story'); + $this->loadModel('bug'); + + $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(); + + $bugs = $this->dao->select('product,count(*) AS conut') + ->from(TABLE_BUG) + ->where('deleted')->eq(0) + ->andWhere('product')->in(array_keys($products)) + ->groupBy('product') + ->fetchPairs(); + $unResolved = $this->dao->select('product,count(*) AS count') + ->from(TABLE_BUG) + ->where('status')->eq('active') + ->andwhere('deleted')->eq(0) + ->andWhere('product')->in(array_keys($products)) + ->groupBy('product') + ->fetchPairs(); + $assignToNull = $this->dao->select('product,count(*) AS count') + ->from(TABLE_BUG) + ->where('AssignedTo')->eq('') + ->andwhere('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; + + $product->bugs = isset($bugs[$product->id]) ? $bugs[$product->id] : 0; + $product->unResolved = isset($unResolved[$product->id]) ? $unResolved[$product->id] : 0; + $product->assignToNull = isset($assignToNull[$product->id]) ? $assignToNull[$product->id] : 0; + $stats[] = $product; + } + } + else + { + unset($products[$key]); + } + } + + return $stats; + } + + public function getPrivProducts() + { + $account = ',' . $this->app->user->account . ','; + static $products; + if($products === null) + { + $groupSql = ''; + foreach($this->app->user->groups as $group) $groupSql .= "INSTR(CONCAT(',', t1.whitelist, ','), ',$group,') > 0 OR "; + $groupSql = !empty($groupSql) ? '(' . substr($groupSql, 0, strlen($groupSql) - 4) . ')' : '1 != 1'; + $products = $this->dao->select('distinct t1.id')->from(TABLE_PRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product') + ->leftJoin(TABLE_TEAM)->alias('t3')->on('t2.project = t3.project') + ->leftJoin(TABLE_PROJECT)->alias('t4')->on('t2.project = t4.id') + ->beginIF(strpos($this->app->company->admins, $account) !== false)->where('t1.deleted')->eq(0)->fi() + ->beginIF(strpos($this->app->company->admins, $account) === false) + ->where('t1.acl')->eq('open') + ->orWhere("(t1.acl = 'custom' AND $groupSql)") + ->orWhere('t1.PO')->eq($this->app->user->account) + ->orWhere('t1.QD')->eq($this->app->user->account) + ->orWhere('t1.RD')->eq($this->app->user->account) + ->orWhere('t1.createdBy')->eq($this->app->user->account) + ->orWhere('t3.account')->eq($this->app->user->account) + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t4.deleted')->eq(0) + ->fi() + ->fetchAll('id'); + } + return $products; + } + + /** + * Get the summary of product's stories. + * + * @param array $stories + * @access public + * @return string. + */ + public function summary($stories) + { + $totalEstimate = 0.0; + foreach($stories as $key => $story) $totalEstimate += $story->estimate; + return sprintf($this->lang->product->storySummary, count($stories), $totalEstimate); + } + + /** + * Judge an action is clickable or not. + * + * @param object $product + * @param string $action + * @access public + * @return void + */ + public function isClickable($product, $action) + { + $action = strtolower($action); + + if($action == 'close') return $product->status != 'closed'; + + return true; + } +} diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index 9076f28243..35229ccbe1 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -1,141 +1,141 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          -
          - inlink('browse',"productID=$productID"), $lang->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;?> -
          -
          - - - - -
          -
          -
          '>
          -
          - - - - - - -
          -
          -
          - -
          - tree->manage);?> - tree->fix, 'hiddenwin');?> -
          -
          -
          - - - - recTotal}&recPerPage={$pager->recPerPage}";?> - - - - - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - $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);?> - story->priList[$story->pri];?>'>story->priList[$story->pri]?>title);?>planTitle;?>story->sourceList[$story->source];?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - id}"; - common::printIcon('story', 'change', $vars, $story, 'list'); - common::printIcon('story', 'review', $vars, $story, 'list'); - common::printIcon('story', 'edit', "storyID=$story->id", $story, 'list'); - common::printIcon('story', 'createCase', "productID=$story->product&module=0&from=¶m=0&$vars", $story, 'list', 'createCase'); - ?> -
          -
          - createLink('story', 'batchEdit', "from=productBrowse&productID=$productID&projectID=0&orderBy=$orderBy"); - echo html::commonButton($lang->story->batchEdit, "onclick=\"changeAction('productStoryForm', 'batchEdit', '$actionLink')\""); - } - if(common::hasPriv('story', 'batchClose') and strtolower($browseType) != 'closedbyme' and strtolower($browseType) != 'closedstory') - { - $actionLink = $this->createLink('story', 'batchClose', "from=productBrowse&productID=$productID&projectID=0&orderBy=$orderBy"); - echo html::commonButton($lang->story->batchClose, "onclick=\"changeAction('productStoryForm', 'batchClose', '$actionLink')\""); - } - } - echo $summary; - ?> -
          - show();?> -
          -
          -
          - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          +
          + inlink('browse',"productID=$productID"), $lang->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;?> +
          +
          + + + + +
          +
          +
          '>
          +
          + + + + + + +
          +
          +
          + +
          + tree->manage);?> + tree->fix, 'hiddenwin');?> +
          +
          +
          + + + + recTotal}&recPerPage={$pager->recPerPage}";?> + + + + + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id"); + $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);?> + story->priList[$story->pri];?>'>story->priList[$story->pri]?>title);?>planTitle;?>story->sourceList[$story->source];?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + id}"; + common::printIcon('story', 'change', $vars, $story, 'list'); + common::printIcon('story', 'review', $vars, $story, 'list'); + common::printIcon('story', 'edit', "storyID=$story->id", $story, 'list'); + common::printIcon('story', 'createCase', "productID=$story->product&module=0&from=¶m=0&$vars", $story, 'list', 'createCase'); + ?> +
          +
          + createLink('story', 'batchEdit', "from=productBrowse&productID=$productID&projectID=0&orderBy=$orderBy"); + echo html::commonButton($lang->story->batchEdit, "onclick=\"changeAction('productStoryForm', 'batchEdit', '$actionLink')\""); + } + if(common::hasPriv('story', 'batchClose') and strtolower($browseType) != 'closedbyme' and strtolower($browseType) != 'closedstory') + { + $actionLink = $this->createLink('story', 'batchClose', "from=productBrowse&productID=$productID&projectID=0&orderBy=$orderBy"); + echo html::commonButton($lang->story->batchClose, "onclick=\"changeAction('productStoryForm', 'batchClose', '$actionLink')\""); + } + } + echo $summary; + ?> +
          + show();?> +
          +
          +
          + + diff --git a/module/product/view/close.html.php b/module/product/view/close.html.php index b56c8d5b58..0ffa3cb17e 100644 --- a/module/product/view/close.html.php +++ b/module/product/view/close.html.php @@ -1,27 +1,27 @@ - - * @package product - * @version $Id: close.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package product + * @version $Id: close.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/product/view/create.html.php b/module/product/view/create.html.php index 9dbb9e1a44..80c755001e 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->QD;?>
          product->RD;?>
          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->QD;?>
          product->RD;?>
          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 7acc498fa2..69f816b622 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");?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module;?>title);?>addedBy];?>addedDate;?> - id}"; - common::printIcon('doc', 'edit', $vars); - common::printIcon('doc', 'delete', $vars, '', 'button', '', 'hiddenwin'); - ?> -
          -
          - + + * @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");?>
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module;?>title);?>addedBy];?>addedDate;?> + id}"; + common::printIcon('doc', 'edit', $vars); + common::printIcon('doc', 'delete', $vars, '', 'button', '', 'hiddenwin'); + ?> +
          +
          + diff --git a/module/product/view/dynamic.html.php b/module/product/view/dynamic.html.php index a87bd6a3a3..5e813d872e 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-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();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2013 青岛易软天创网络科技有限公司 (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 f637c11756..5a49b51dbf 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->QD;?>QD, "class='select-3'");?>
          product->RD;?>RD, "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->QD;?>QD, "class='select-3'");?>
          product->RD;?>RD, "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 3c610046a3..30f5dffb66 100644 --- a/module/product/view/index.html.php +++ b/module/product/view/index.html.php @@ -1,60 +1,60 @@ - - * @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;?>product->bugs;?>bug->unResolved;?>bug->assignToNull;?>
          createLink('product', 'view', 'product=' . $product->id), $product->name);?>stories['active']?>stories['changed']?>stories['draft']?>stories['closed']?>plans?>releases?>bugs?>unResolved;?>assignToNull;?>
          -
          - - - + + * @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;?>product->bugs;?>bug->unResolved;?>bug->assignToNull;?>
          createLink('product', 'view', 'product=' . $product->id), $product->name);?>stories['active']?>stories['changed']?>stories['draft']?>stories['closed']?>plans?>releases?>bugs?>unResolved;?>assignToNull;?>
          +
          + + + diff --git a/module/product/view/order.html.php b/module/product/view/order.html.php index dd0c448d41..79a45f92d0 100644 --- a/module/product/view/order.html.php +++ b/module/product/view/order.html.php @@ -1,32 +1,32 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - - - - - -
          product->id?>product->name?>product->order?>
          id?>name?>id, $product->order, "size='5'")?>
          -
          - - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + + + + + +
          product->id?>product->name?>product->order?>
          id?>name?>id, $product->order, "size='5'")?>
          +
          + + diff --git a/module/product/view/project.html.php b/module/product/view/project.html.php index 9f658d4545..e9cbbcd493 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 3503464a9a..e959eedfc2 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 45f752c27f..f3ebc08dc3 100644 --- a/module/product/view/view.html.php +++ b/module/product/view/view.html.php @@ -1,157 +1,157 @@ - - * @package product - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          deleted) echo "class='deleted'";?>>PRODUCT #id . ' ' . $product->name;?>
          -
          - id"; - $browseLink = $this->session->productList ? $this->session->productList : inlink('browse', "productID=$product->id"); - if(!$product->deleted) - { - ob_start(); - common::printIcon('product', 'close', "productID=$product->id", $product); - - common::printDivider(); - common::printIcon('product', 'edit', $params); - common::printIcon('product', 'delete', $params, '', 'button', '', 'hiddenwin'); - common::printRPN($browseLink); - - $actionLinks = ob_get_contents(); - ob_end_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
          -
          - - - - - - - -
          -
          - product->desc;?> -
          desc;?>
          -
          - - -
          -
          - product->basicInfo?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          product->name;?>deleted) echo "class='deleted'";?>>name;?>
          product->code;?>code;?>
          product->PO;?>PO];?>
          product->QD;?>QD];?>
          product->RD;?>RD];?>
          product->status;?>product->statusList[$product->status];?>
          product->acl;?>product->aclList[$product->acl];?>
          product->whitelist;?> - whitelist); - foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; - ?> -
          story->openedBy?>createdBy];?>
          story->openedDate?>createdDate;?>
          -
          -
          - product->otherInfo?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          story->statusList['active'] . $lang->story->common;?>stories['active']?>
          story->statusList['changed'] . $lang->story->common;?>stories['changed']?>
          story->statusList['draft'] . $lang->story->common;?>stories['draft']?>
          story->statusList['closed'] . $lang->story->common;?>stories['closed']?>
          product->plans?>plans?>
          product->projects?>projects?>
          product->bugs?>bugs?>
          product->docs?>docs?>
          product->cases?>cases?>
          product->bulids?>bulids?>
          product->releases?>releases?>
          -
          -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          deleted) echo "class='deleted'";?>>PRODUCT #id . ' ' . $product->name;?>
          +
          + id"; + $browseLink = $this->session->productList ? $this->session->productList : inlink('browse', "productID=$product->id"); + if(!$product->deleted) + { + ob_start(); + common::printIcon('product', 'close', "productID=$product->id", $product); + + common::printDivider(); + common::printIcon('product', 'edit', $params); + common::printIcon('product', 'delete', $params, '', 'button', '', 'hiddenwin'); + common::printRPN($browseLink); + + $actionLinks = ob_get_contents(); + ob_end_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
          +
          + + + + + + + +
          +
          + product->desc;?> +
          desc;?>
          +
          + + +
          +
          + product->basicInfo?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          product->name;?>deleted) echo "class='deleted'";?>>name;?>
          product->code;?>code;?>
          product->PO;?>PO];?>
          product->QD;?>QD];?>
          product->RD;?>RD];?>
          product->status;?>product->statusList[$product->status];?>
          product->acl;?>product->aclList[$product->acl];?>
          product->whitelist;?> + whitelist); + foreach($whitelist as $groupID) if(isset($groups[$groupID])) echo $groups[$groupID] . ' '; + ?> +
          story->openedBy?>createdBy];?>
          story->openedDate?>createdDate;?>
          +
          +
          + product->otherInfo?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          story->statusList['active'] . $lang->story->common;?>stories['active']?>
          story->statusList['changed'] . $lang->story->common;?>stories['changed']?>
          story->statusList['draft'] . $lang->story->common;?>stories['draft']?>
          story->statusList['closed'] . $lang->story->common;?>stories['closed']?>
          product->plans?>plans?>
          product->projects?>projects?>
          product->bugs?>bugs?>
          product->docs?>docs?>
          product->cases?>cases?>
          product->bulids?>bulids?>
          product->releases?>releases?>
          +
          +
          + diff --git a/module/productplan/control.php b/module/productplan/control.php index 968f234880..45b5a05d9e 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', 'view', "planID=$planID"), '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); - $products = $this->product->getPairs(); - $this->view->header->title = $products[$product] . $this->lang->colon . $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, true); - if(!$plan) die(js::error($this->lang->notFound) . js::locate('back')); - $this->commonAction($plan->product); - $products = $this->product->getPairs(); - $this->view->header->title = "PLAN #$plan->id $plan->title/" . $products[$plan->product]; - $this->view->position[] = $this->lang->productplan->view; - $this->view->planStories= $this->loadModel('story')->getPlanStories($planID); - $this->view->products = $products; - $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', 'view', "planID=$planID"), '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); + $products = $this->product->getPairs(); + $this->view->header->title = $products[$product] . $this->lang->colon . $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, true); + if(!$plan) die(js::error($this->lang->notFound) . js::locate('back')); + $this->commonAction($plan->product); + $products = $this->product->getPairs(); + $this->view->header->title = "PLAN #$plan->id $plan->title/" . $products[$plan->product]; + $this->view->position[] = $this->lang->productplan->view; + $this->view->planStories= $this->loadModel('story')->getPlanStories($planID); + $this->view->products = $products; + $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 3bc477f89c..0dbc268d58 100644 --- a/module/productplan/lang/en.php +++ b/module/productplan/lang/en.php @@ -1,41 +1,41 @@ - - * @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->basicInfo ='Basic Info'; - -$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->endList[14] = 'Two Weeks'; -$lang->productplan->endList[31] = 'One Month'; -$lang->productplan->endList[62] = 'Two Months'; -$lang->productplan->endList[93] = 'Three Months'; -$lang->productplan->endList[186] = 'Half Of Year'; -$lang->productplan->endList[365] = 'One Year'; + + * @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->basicInfo ='Basic Info'; + +$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->endList[14] = 'Two Weeks'; +$lang->productplan->endList[31] = 'One Month'; +$lang->productplan->endList[62] = 'Two Months'; +$lang->productplan->endList[93] = 'Three Months'; +$lang->productplan->endList[186] = 'Half Of Year'; +$lang->productplan->endList[365] = 'One Year'; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index 9d7a1f32fb..01900eb412 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -1,41 +1,41 @@ - - * @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->basicInfo ='基本信息'; - -$lang->productplan->id = '编号'; -$lang->productplan->product = '产品'; -$lang->productplan->title = '名称'; -$lang->productplan->desc = '描述'; -$lang->productplan->begin = '开始日期'; -$lang->productplan->end = '结束日期'; - -$lang->productplan->endList[14] = '两星期'; -$lang->productplan->endList[31] = '一个月'; -$lang->productplan->endList[62] = '两个月'; -$lang->productplan->endList[93] = '三个月'; -$lang->productplan->endList[186] = '半年'; -$lang->productplan->endList[365] = '一年'; + + * @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->basicInfo ='基本信息'; + +$lang->productplan->id = '编号'; +$lang->productplan->product = '产品'; +$lang->productplan->title = '名称'; +$lang->productplan->desc = '描述'; +$lang->productplan->begin = '开始日期'; +$lang->productplan->end = '结束日期'; + +$lang->productplan->endList[14] = '两星期'; +$lang->productplan->endList[31] = '一个月'; +$lang->productplan->endList[62] = '两个月'; +$lang->productplan->endList[93] = '三个月'; +$lang->productplan->endList[186] = '半年'; +$lang->productplan->endList[365] = '一年'; diff --git a/module/productplan/lang/zh-tw.php b/module/productplan/lang/zh-tw.php index 7330681836..7b4de10767 100644 --- a/module/productplan/lang/zh-tw.php +++ b/module/productplan/lang/zh-tw.php @@ -1,34 +1,34 @@ - - * @package productplan - * @version $Id: zh-tw.php 3238 2012-07-02 01:44:49Z wwccss $ - * @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->basicInfo ='基本信息'; - -$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 3238 2012-07-02 01:44:49Z wwccss $ + * @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->basicInfo ='基本信息'; + +$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 1af43ac99b..138a7c274d 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -1,152 +1,152 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> -dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch(); - if($setImgSize) $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(); - } - - /** - * Get plans for products - * - * @param int $products - * @access public - * @return void - */ - public function getForProducts($products) - { - return array('' => '') + $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) - ->where('product')->in(array_keys($products)) - ->andWhere('deleted')->eq(0) - ->orderBy('begin')->fetchPairs(); - } - - /** - * Create a plan. - * - * @access public - * @return int - */ - public function create() - { - $plan = fixer::input('post')->stripTags('title')->remove('delta')->get(); - $this->dao->insert(TABLE_PRODUCTPLAN) - ->data($plan) - ->autoCheck() - ->batchCheck($this->config->productplan->create->requiredFields, 'notempty') - ->check('end', 'gt', $plan->begin) - ->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') - ->check('end', 'gt', $plan->begin) - ->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(); + if($setImgSize) $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(); + } + + /** + * Get plans for products + * + * @param int $products + * @access public + * @return void + */ + public function getForProducts($products) + { + return array('' => '') + $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) + ->where('product')->in(array_keys($products)) + ->andWhere('deleted')->eq(0) + ->orderBy('begin')->fetchPairs(); + } + + /** + * Create a plan. + * + * @access public + * @return int + */ + public function create() + { + $plan = fixer::input('post')->stripTags('title')->remove('delta')->get(); + $this->dao->insert(TABLE_PRODUCTPLAN) + ->data($plan) + ->autoCheck() + ->batchCheck($this->config->productplan->create->requiredFields, 'notempty') + ->check('end', 'gt', $plan->begin) + ->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') + ->check('end', 'gt', $plan->begin) + ->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 2a677134fa..8f92fdd36f 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");?>
          -
          idAB;?>productplan->begin;?>productplan->end;?>productplan->title;?>productplan->desc;?>actions;?>
          id"), $plan->id);?>begin;?>end;?>id"), $plan->title);?>desc;?> - id", '', 'list'); - common::printIcon('productplan', 'edit', "planID=$plan->id", '', 'list'); - common::printIcon('productplan', 'delete', "planID=$plan->id", '', 'list', '', 'hiddenwin'); - ?> -
          - + + * @package plan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          productplan->browse;?>
          +
          id");?>
          +
          idAB;?>productplan->begin;?>productplan->end;?>productplan->title;?>productplan->desc;?>actions;?>
          id"), $plan->id);?>begin;?>end;?>id"), $plan->title);?>desc;?> + id", '', 'list'); + common::printIcon('productplan', 'edit', "planID=$plan->id", '', 'list'); + common::printIcon('productplan', 'delete', "planID=$plan->id", '', 'list', '', 'hiddenwin'); + ?> +
          + diff --git a/module/productplan/view/create.html.php b/module/productplan/view/create.html.php index a5e7623dd7..222732a058 100644 --- a/module/productplan/view/create.html.php +++ b/module/productplan/view/create.html.php @@ -1,54 +1,54 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - -
          productplan->create;?>
          productplan->product;?>name;?>
          productplan->title;?>
          productplan->begin;?>
          productplan->end;?> - - productplan->endList , '', "onclick='computeEndDate(this.value)'");?> -
          productplan->desc;?>
          - id); - ?> -
          -
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + +
          productplan->create;?>
          productplan->product;?>name;?>
          productplan->title;?>
          productplan->begin;?>
          productplan->end;?> + + productplan->endList , '', "onclick='computeEndDate(this.value)'");?> +
          productplan->desc;?>
          + id); + ?> +
          +
          + diff --git a/module/productplan/view/edit.html.php b/module/productplan/view/edit.html.php index fe45bcc4a9..967c95ad4c 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 abe2761889..e825a62c2f 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;?>'>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;?>'>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;?>'>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;?>'>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 2a80adb231..89e77337cc 100644 --- a/module/productplan/view/view.html.php +++ b/module/productplan/view/view.html.php @@ -1,96 +1,96 @@ - - * @package productplan - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - -
          deleted) echo "class='deleted'";?>>PLAN #id . ' ' . $plan->title;?>
          -
          - productplan->desc;?> -
          desc;?>
          -
          - -
          - session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id"); - if(!$plan->deleted) - { - common::printIcon('productplan', 'linkStory',"planID=$plan->id"); - common::printIcon('productplan', 'edit', "planID=$plan->id"); - common::printIcon('productplan', 'delete', "planID=$plan->id", '', 'button', '', 'hiddenwin'); - } - common::printRPN($browseLink); - ?> -
          - - - - - - - - - - - - - - - - - - - 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?>'>pri;?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          product->storySummary, count($planStories), $totalEstimate);?>
          -
          -
          - productplan->basicInfo?> - - - - - - - - - - -
          productplan->title;?>title;?> -
          productplan->begin;?>begin;?> -
          productplan->end;?>end;?> -
          -
          -
          - + + * @package productplan + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + +
          deleted) echo "class='deleted'";?>>PLAN #id . ' ' . $plan->title;?>
          +
          + productplan->desc;?> +
          desc;?>
          +
          + +
          + session->productPlanList ? $this->session->productPlanList : inlink('browse', "planID=$plan->id"); + if(!$plan->deleted) + { + common::printIcon('productplan', 'linkStory',"planID=$plan->id"); + common::printIcon('productplan', 'edit', "planID=$plan->id"); + common::printIcon('productplan', 'delete', "planID=$plan->id", '', 'button', '', 'hiddenwin'); + } + common::printRPN($browseLink); + ?> +
          + + + + + + + + + + + + + + + + + + + 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?>'>pri;?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>id", $lang->productplan->unlinkStory, 'hiddenwin');?>
          product->storySummary, count($planStories), $totalEstimate);?>
          +
          +
          + productplan->basicInfo?> + + + + + + + + + + +
          productplan->title;?>title;?> +
          productplan->begin;?>begin;?> +
          productplan->end;?>end;?> +
          +
          +
          + diff --git a/module/project/control.php b/module/project/control.php index 85c3283e61..ada00f3a13 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -1,1516 +1,1516 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -class project extends control -{ - public $projects; - - /** - * Construct function, Set projects. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - if($this->methodName != 'computeburn') - { - $this->projects = $this->project->getPairs(); - if(!$this->projects and $this->methodName != 'create') $this->locate($this->createLink('project', 'create')); - } - } - - /** - * The index page. - * - * @param string $locate yes|no locate to the browse page or not. - * @param string $status the projects status, if locate is no, then get projects by the $status. - * @param int $projectID - * @access public - * @return void - */ - public function index($locate = 'yes', $status = 'all', $projectID = 0) - { - if(empty($this->projects)) $this->locate($this->createLink('project', 'create')); - if($locate == 'yes') $this->locate($this->createLink('project', 'task')); - - $this->commonAction($projectID); - $this->session->set('projectList', $this->app->getURI(true)); - - $this->app->loadLang('my'); - $this->view->projectStats = $this->project->getProjectStats($status); - - $this->display(); - } - - /** - * Browse a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function browse($projectID = 0) - { - $this->locate($this->createLink($this->moduleName, 'task', "projectID=$projectID")); - } - - /** - * Common actions. - * - * @param int $projectID - * @access public - * @return object current object - */ - public function commonAction($projectID = 0, $extra = '') - { - $this->loadModel('product'); - - /* Get projects and products info. */ - $projectID = $this->project->saveState($projectID, array_keys($this->projects)); - $project = $this->project->getById($projectID); - $products = $this->project->getProducts($project->id); - $childProjects = $this->project->getChildProjects($project->id); - $teamMembers = $this->project->getTeamMembers($project->id); - $actions = $this->loadModel('action')->getList('project', $project->id); - - /* Set menu. */ - $this->project->setMenu($this->projects, $project->id, $extra); - - /* Assign. */ - $this->view->projects = $this->projects; - $this->view->project = $project; - $this->view->childProjects = $childProjects; - $this->view->products = $products; - $this->view->teamMembers = $teamMembers; - $this->view->actions = $actions; - - return $project; - } - - /** - * Tasks of a project. - * - * @param int $projectID - * @param string $status - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function task($projectID = 0, $status = 'all', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 100, $pageID = 1) - { - $this->loadModel('tree'); - - /* Set browseType, productID, moduleID and queryID. */ - $browseType = strtolower($status); - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - $moduleID = ($status == 'byModule') ? (int)$param : 0; - $project = $this->commonAction($projectID, $status); - $projectID = $project->id; - - /* Save to session. */ - $uri = $this->app->getURI(true); - $this->app->session->set('taskList', $uri); - $this->app->session->set('storyList', $uri); - $this->app->session->set('projectList', $uri); - - /* Process the order by field. */ - if(!$orderBy) $orderBy = $this->cookie->projectTaskOrder ? $this->cookie->projectTaskOrder : 'status,id_desc'; - setcookie('projectTaskOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); - - /* Header and position. */ - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->task; - $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $this->view->position[] = $this->lang->project->task; - - /* Load pager and get tasks. */ - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $tasks = array(); - if($status == 'byModule') - { - $tasks = $this->loadModel('task')->getTasksByModule($projectID, $this->tree->getAllChildID($moduleID), $orderBy, $pager); - } - elseif($browseType != "bysearch") - { - $status = $status == 'byProject' ? 'all' : $status; - $tasks = $this->loadModel('task')->getProjectTasks($projectID, $status, $orderBy, $pager); - } - else - { - if($queryID) - { - $query = $this->loadModel('search')->getQuery($queryID); - if($query) - { - $this->session->set('taskQuery', $query->sql); - $this->session->set('taskForm', $query->form); - } - else - { - $this->session->set('taskQuery', ' 1 = 1'); - } - } - else - { - if($this->session->taskQuery == false) $this->session->set('taskQuery', ' 1 = 1'); - } - /* Limit current project when no project. */ - if(strpos($this->session->taskQuery, "`project` =") === false) $this->session->set('taskQuery', $this->session->taskQuery . " AND `project` = $projectID"); - - $projectIDs = array_keys($this->project->getPairs()); - $projectQuery = "`project` in (" . implode($projectIDs, ',') . ")"; - $taskQuery = str_replace("`project` = 'all'", $projectQuery, $this->session->taskQuery); // Search all project. - $taskQuery = $this->loadModel('search')->replaceDynamic($taskQuery); - - $this->session->set('taskQueryCondition', $taskQuery); - $this->session->set('taskOnlyCondition', true); - $this->session->set('taskOrderBy', $orderBy); - $tasks = $this->project->getSearchTasks($taskQuery, $pager, $orderBy); - } - - /* Build the search form. */ - $this->config->project->search['actionURL'] = $this->createLink('project', 'task', "projectID=$projectID&status=bySearch¶m=myQueryID"); - $this->config->project->search['queryID'] = $queryID; - $this->config->project->search['params']['project']['values'] = array(''=>'', $projectID => $this->projects[$projectID], 'all' => $this->lang->project->allProject); - $this->config->project->search['params']['module']['values'] = $this->tree->getOptionMenu($projectID, $viewType = 'task', $startModuleID = 0); - $this->loadModel('search')->setSearchParams($this->config->project->search); - - /* Assign. */ - $this->view->tasks = $tasks; - $this->view->summary = $this->project->summary($tasks); - $this->view->tabID = 'task'; - $this->view->pager = $pager; - $this->view->recTotal = $pager->recTotal; - $this->view->recPerPage = $pager->recPerPage; - $this->view->orderBy = $orderBy; - $this->view->browseType = $browseType; - $this->view->status = $status; - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->view->param = $param; - $this->view->projectID = $projectID; - $this->view->project = $project; - $this->view->moduleID = $moduleID; - $this->view->moduleTree = $this->tree->getTreeMenu($projectID, $viewType = 'task', $startModuleID = 0, array('treeModel', 'createTaskLink')); - $this->view->projectTree = $this->project->tree(); - - $this->display(); - } - - /** - * Browse tasks in group. - * - * @param int $projectID - * @param string $groupBy the field to group by - * @access public - * @return void - */ - public function grouptask($projectID = 0, $groupBy = 'story') - { - $project = $this->commonAction($projectID); - $projectID = $project->id; - - /* Save session. */ - $this->app->session->set('taskList', $this->app->getURI(true)); - $this->app->session->set('storyList', $this->app->getURI(true)); - - /* Header and session. */ - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->task; - $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $this->view->position[] = $this->lang->project->task; - - /* Get tasks and group them. */ - $tasks = $this->loadModel('task')->getProjectTasks($projectID, $status = 'all', $groupBy ? $groupBy : 'story'); - $groupBy = strtolower(str_replace('`', '', $groupBy)); - $taskLang = $this->lang->task; - $groupByList = array(); - $groupTasks = array(); - - /* Get users. */ - $users = $this->loadModel('user')->getPairs('noletter'); - foreach($tasks as $task) - { - if($groupBy == '') - { - $groupTasks[$task->story][] = $task; - $groupByList[$task->story] = $task->storyTitle; - } - elseif($groupBy == 'story') - { - $groupTasks[$task->story][] = $task; - $groupByList[$task->story] = $task->storyTitle; - } - elseif($groupBy == 'status') - { - $groupTasks[$taskLang->statusList[$task->status]][] = $task; - } - elseif($groupBy == 'assignedto') - { - $groupTasks[$task->assignedToRealName][] = $task; - } - elseif($groupBy == 'openedby') - { - $groupTasks[$users[$task->openedBy]][] = $task; - } - elseif($groupBy == 'finishedby') - { - $groupTasks[$users[$task->finishedBy]][] = $task; - } - elseif($groupBy == 'closedby') - { - $groupTasks[$users[$task->closedBy]][] = $task; - } - elseif($groupBy == 'type') - { - $groupTasks[$taskLang->typeList[$task->type]][] = $task; - } - else - { - $groupTasks[$task->$groupBy][] = $task; - } - } - - /* Assign. */ - $this->view->members = $this->project->getTeamMembers($projectID); - $this->view->tasks = $groupTasks; - $this->view->tabID = 'task'; - $this->view->groupByList = $groupByList; - $this->view->browseType = 'group'; - $this->view->groupBy = $groupBy; - $this->view->orderBy = $groupBy; - $this->view->projectID = $projectID; - $this->view->users = $users; - $this->display(); - } - - /** - * Import tasks undoned from other projects. - * - * @param int $projectID - * @access public - * @return void - */ - public function importTask($toProject, $fromProject = 0) - { - if(!empty($_POST)) - { - $this->project->importTask($toProject,$fromProject); - die(js::locate(inlink('task', "projectID=$toProject"), 'parent')); - } - - $project = $this->commonAction($toProject); - $projects = $this->project->getProjectsToImport(); - unset($projects[$toProject]); - - $fromProject = ($fromProject == 0 and !empty($projects)) ? key($projects) : $fromProject; - - /* Save session. */ - $this->app->session->set('taskList', $this->app->getURI(true)); - $this->app->session->set('storyList', $this->app->getURI(true)); - - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->importTask; - $this->view->position[] = html::a(inlink('browse', "projectID=$toProject"), $project->name); - $this->view->position[] = $this->lang->project->importTask; - $this->view->tasks2Imported = $this->project->getTasks2Imported($fromProject); - $this->view->projects = $projects; - $this->view->projectID = $project->id; - $this->view->fromProject = $fromProject; - $this->display(); - } - - /** - * Import from Bug. - * - * @param int $projectID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function importBug($projectID = 0, $browseType = 'all', $param = 0, $recTotal = 0, $recPerPage = 30, $pageID = 1) - { - if(!empty($_POST)) - { - $mails = $this->project->importBug($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($this->createLink('project', 'importBug', "projectID=$projectID"), 'parent')); - } - - /* Set browseType, productID, moduleID and queryID. */ - $browseType = strtolower($browseType); - $queryID = ($browseType == 'bysearch') ? (int)$param : 0; - - /* Save to session. */ - $uri = $this->app->getURI(true); - $this->app->session->set('bugList', $uri); - $this->app->session->set('storyList', $uri); - $this->app->session->set('projectList', $uri); - - $this->loadModel('bug'); - $projects = $this->project->getPairs(); - $this->project->setMenu($projects, $projectID); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - - $header['title'] = $projects[$projectID] . $this->lang->colon . $this->lang->project->importBug; - $position[] = html::a($this->createLink('project', 'task', "projectID=$projectID"), $projects[$projectID]); - $position[] = $this->lang->project->importBug; - - /* Get users, products and projects.*/ - $users = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); - $products = $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('product'); - if(!empty($products)) - { - unset($projects); - $projects = $this->dao->select('t1.project, t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.product')->in(array_keys($products)) - ->fetchPairs('project'); - } - else - { - $projectName = $projects[$projectID]; - unset($projects); - $projects[$projectID] = $projectName; - } - - /* Get bugs.*/ - $bugs = array(); - if($browseType != "bysearch") - { - $bugs = $this->bug->getActiveBugs($pager, $projectID, array_keys($products)); - } - else - { - 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'); - } - $bugQuery = str_replace("`product` = 'all'", "`product`" . helper::dbIN(array_keys($products)), $this->session->bugQuery); // Search all project. - $bugs = $this->project->getSearchBugs($products, $projectID, $bugQuery, $pager, 'id_desc'); - } - - /* Build the search form. */ - $this->config->bug->search['actionURL'] = $this->createLink('project', 'importBug', "projectID=$projectID&browseType=bySearch¶m=myQueryID"); - $this->config->bug->search['queryID'] = $queryID; - if(!empty($products)) - { - $this->config->bug->search['params']['product']['values'] = array(''=>'') + $products + array('all'=>$this->lang->project->aboveAllProduct); - } - else - { - $this->config->bug->search['params']['product']['values'] = array(''=>''); - } - $this->config->bug->search['params']['project']['values'] = array(''=>'') + $projects + array('all'=>$this->lang->project->aboveAllProject); - $this->config->bug->search['module'] = 'importBug'; - unset($this->config->bug->search['fields']['resolvedBy']); - unset($this->config->bug->search['fields']['closedBy']); - unset($this->config->bug->search['fields']['status']); - unset($this->config->bug->search['fields']['toTask']); - unset($this->config->bug->search['fields']['toStory']); - unset($this->config->bug->search['fields']['severity']); - unset($this->config->bug->search['fields']['resolution']); - unset($this->config->bug->search['fields']['resolvedBuild']); - unset($this->config->bug->search['fields']['resolvedDate']); - unset($this->config->bug->search['fields']['closedDate']); - unset($this->config->bug->search['params']['resolvedBy']); - unset($this->config->bug->search['params']['closedBy']); - unset($this->config->bug->search['params']['status']); - unset($this->config->bug->search['params']['toTask']); - unset($this->config->bug->search['params']['toStory']); - unset($this->config->bug->search['params']['severity']); - unset($this->config->bug->search['params']['resolution']); - unset($this->config->bug->search['params']['resolvedBuild']); - unset($this->config->bug->search['params']['resolvedDate']); - unset($this->config->bug->search['params']['closedDate']); - $this->loadModel('search')->setSearchParams($this->config->bug->search); - - /* Assign. */ - $this->view->header = $header; - $this->view->pager = $pager; - $this->view->bugs = $bugs; - $this->view->recTotal = $pager->recTotal; - $this->view->recPerPage = $pager->recPerPage; - $this->view->browseType = $browseType; - $this->view->param = $param; - $this->view->users = $users; - $this->view->projectID = $projectID; - $this->display(); - } - - /** - * Browse stories of a project. - * - * @param int $projectID - * @param string $orderBy - * @access public - * @return void - */ - public function story($projectID = 0, $orderBy = '') - { - /* Load these models. */ - $this->loadModel('story'); - $this->loadModel('user'); - $this->loadModel('task'); - - /* Save session. */ - $this->app->session->set('storyList', $this->app->getURI(true)); - - /* Process the order by field. */ - if(!$orderBy) $orderBy = $this->cookie->projectStoryOrder ? $this->cookie->projectStoryOrder : 'pri'; - setcookie('projectStoryOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); - - $project = $this->commonAction($projectID); - - /* Header and position. */ - $header['title'] = $project->name . $this->lang->colon . $this->lang->project->story; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $position[] = $this->lang->project->story; - - /* The pager. */ - $stories = $this->story->getProjectStories($projectID, $orderBy); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', false); - $storyTasks = $this->task->getStoryTaskCounts(array_keys($stories), $projectID); - $users = $this->user->getPairs('noletter'); - - /* Save storyIDs session for get the pre and next story. */ - $storyIDs = ''; - foreach($stories as $story) $storyIDs .= ',' . $story->id; - $this->session->set('storyIDs', $storyIDs . ','); - - /* Get project's product. */ - $productID = 0; - $products = $this->loadModel('product')->getProductsByProject($projectID); - if($products) $productID = key($products); - - /* Assign. */ - $this->view->header = $header; - $this->view->position = $position; - $this->view->productID = $productID; - $this->view->stories = $stories; - $this->view->orderBy = $orderBy; - $this->view->storyTasks = $storyTasks; - $this->view->tabID = 'story'; - $this->view->users = $users; - - $this->display(); - } - - /** - * Browse bugs of a project. - * - * @param int $projectID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function bug($projectID = 0, $orderBy = 'status,id_desc', $build = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Load these two models. */ - $this->loadModel('bug'); - $this->loadModel('user'); - - /* Save session. */ - $this->session->set('bugList', $this->app->getURI(true)); - - $project = $this->commonAction($projectID); - $products = $this->project->getProducts($project->id); - $productID = key($products); // Get the first product for creating bug. - - /* Header and position. */ - $header['title'] = $project->name . $this->lang->colon . $this->lang->project->bug; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $position[] = $this->lang->project->bug; - - /* Load pager and get bugs, user. */ - $this->app->loadClass('pager', $static = true); - $pager = new pager($recTotal, $recPerPage, $pageID); - $bugs = $this->bug->getProjectBugs($projectID, $orderBy, $pager, $build); - $users = $this->user->getPairs('noletter'); - - /* Assign. */ - $this->view->header = $header; - $this->view->position = $position; - $this->view->bugs = $bugs; - $this->view->tabID = 'bug'; - $this->view->build = $this->loadModel('build')->getById($build); - $this->view->buildID = $this->view->build ? $this->view->build->id : 0; - $this->view->pager = $pager; - $this->view->orderBy = $orderBy; - $this->view->users = $users; - $this->view->productID = $productID; - - $this->display(); - } - - /** - * Browse builds of a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function build($projectID = 0) - { - $this->loadModel('testtask'); - $this->session->set('buildList', $this->app->getURI(true)); - - $project = $this->commonAction($projectID); - - /* Header and position. */ - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->build; - $this->view->position[] = html::a(inlink('browse', "projectID=$projectID"), $project->name); - $this->view->position[] = $this->lang->project->build; - - /* Get builds. */ - $this->view->builds = $this->loadModel('build')->getProjectBuilds((int)$projectID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - - $this->display(); - } - - /** - * Browse test tasks of project. - * - * @param int $projectID - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function testtask($projectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $this->loadModel('testtask'); - /* Save session. */ - $this->session->set('testtaskList', $this->app->getURI(true)); - - $project = $this->commonAction($projectID); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - $this->view->header->title = $this->projects[$projectID] . $this->lang->colon . $this->lang->testtask->common; - $this->view->position[] = html::a($this->createLink('project', 'testtask', "projectID=$projectID"), $this->projects[$projectID]); - $this->view->position[] = $this->lang->testtask->common; - $this->view->projectID = $projectID; - $this->view->projectName = $this->projects[$projectID]; - $this->view->pager = $pager; - $this->view->orderBy = $orderBy; - $this->view->tasks = $this->testtask->getProjectTasks($projectID); - $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); - - $this->display(); - } - - /** - * Browse burndown chart of a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function burn($projectID = 0) - { - $this->loadModel('report'); - $project = $this->commonAction($projectID); - $projectInfo = $this->project->getByID($project->id); - $maxDays = $this->config->project->maxBurnDay; - - /* Header and position. */ - $header['title'] = $project->name . $this->lang->colon . $this->lang->project->burn; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $position[] = $this->lang->project->burn; - - /* Create charts by flash. */ - //$dataXML = $this->report->createSingleXML($this->project->getBurnData($project->id), $this->lang->project->charts->burn->graph, $this->lang->report->singleColor); - //$charts = $this->report->createJSChart('line', $dataXML, 700, 350); - - /* Create charts by flot. */ - $sets = $this->project->getBurnDataFlot($project->id); - $count = count($sets); - $dataJSON = $this->report->createSingleJSON($sets); - - $limitJSON = '[]'; - $reflineJSON = '[]'; - $beginMicTime = $this->project->getMicTime($projectInfo->begin); - $endMicTime = $this->project->getMicTime($projectInfo->end); - $maxDayMicTime = $this->project->getMicTime(strtotime($projectInfo->begin) + $maxDays * 24 * 3600); - $minDayMicTime = $this->project->getMicTime(time() - $maxDays * 24 * 3600); - if($projectInfo->days <= $maxDays) - { - $limitJSON = "[[$beginMicTime, 0], [$endMicTime, 0]]"; - $firstBurn = reset($sets); - $firstTime = isset($firstBurn->value) ? $firstBurn->value : 0; - $reflineJSON = "[[$beginMicTime, $firstTime], [$endMicTime, 0]]"; - } - elseif($count <= $maxDays) - { - $limitJSON = "[[$beginMicTime, 0], [$maxDayMicTime, 0]]"; - } - - $flotJSON['data'] = $dataJSON; - $flotJSON['limit'] = $limitJSON; - $flotJSON['refline'] = $reflineJSON; - - $charts = $this->report->createJSChartFlot($project->name, $flotJSON, $count, 900, 400); - - /* Assign. */ - $this->view->header = $header; - $this->view->position = $position; - $this->view->tabID = 'burn'; - $this->view->charts = $charts; - $this->view->projectID = $projectID; - - $this->display(); - } - - /** - * Get data of burndown chart. - * - * @param int $projectID - * @access public - * @return void - */ - public function burnData($projectID = 0) - { - $this->loadModel('report'); - $sets = $this->project->getBurnData($projectID); - die($this->report->createSingleXML($sets, $this->lang->project->charts->burn->graph)); - } - - /** - * Compute burndown datas. - * - * @param string $reload - * @access public - * @return void - */ - public function computeBurn($reload = 'no') - { - $this->view->burns = $this->project->computeBurn(); - if($reload == 'yes') die(js::reload('parent')); - die($this->display()); - } - - /** - * Browse team of a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function team($projectID = 0) - { - $project = $this->commonAction($projectID); - - $header['title'] = $project->name . $this->lang->colon . $this->lang->project->team; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $position[] = $this->lang->project->team; - - $this->view->header = $header; - $this->view->position = $position; - - $this->display(); - } - - /** - * Docs of a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function doc($projectID) - { - $this->project->setMenu($this->projects, $projectID); - $this->session->set('docList', $this->app->getURI(true)); - - $project = $this->dao->findById($projectID)->from(TABLE_PROJECT)->fetch(); - $this->view->header->title = $this->lang->project->doc; - $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $project->name); - $this->view->position[] = $this->lang->project->doc; - $this->view->project = $project; - $this->view->docs = $this->loadModel('doc')->getProjectDocs($projectID); - $this->view->modules = $this->doc->getProjectModulePairs(); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Create a project. - * - * @access public - * @return void - */ - public function create($projectID = '', $copyProjectID = '') - { - if($projectID) - { - $this->view->tips = $this->fetch('project', 'tips', "projectID=$projectID"); - $this->view->projectID = $projectID; - $this->display(); - exit; - } - - $name = ''; - $code = ''; - $team = ''; - $products = ''; - $whitelist = ''; - $acl = 'open'; - - if($copyProjectID) - { - $copyProject = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($copyProjectID)->fetch(); - $name = $copyProject->name; - $code = $copyProject->code; - $team = $copyProject->team; - $acl = $copyProject->acl; - $whitelist = $copyProject->whitelist; - $products = join(',', array_keys($this->project->getProducts($copyProjectID))); - } - - if(!empty($_POST)) - { - $projectID = $copyProjectID == '' ? $this->project->create() : $this->project->create($copyProjectID); - $this->project->updateProducts($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - $this->loadModel('action')->create('project', $projectID, 'opened'); - die(js::locate($this->createLink('project', 'create', "projectID=$projectID"), 'parent')); - } - - $this->project->setMenu($this->projects, key($this->projects)); - - $this->view->header->title = $this->lang->project->create; - $this->view->position[] = $this->view->header->title; - $this->view->projects = array('' => '') + $this->projects; - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->allProducts = $this->loadModel('product')->getPairs(); - $this->view->name = $name; - $this->view->code = $code; - $this->view->team = $team; - $this->view->products = $products ; - $this->view->whitelist = $whitelist; - $this->view->acl = $acl ; - $this->view->copyProjectID = $copyProjectID; - $this->display(); - } - - /** - * Edit a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function edit($projectID) - { - $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); - if(!empty($_POST)) - { - $changes = $this->project->update($projectID); - $this->project->updateProducts($projectID); - if(dao::isError()) die(js::error(dao::getError())); - if($changes) - { - $actionID = $this->loadModel('action')->create('project', $projectID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - /* Set menu. */ - $this->project->setMenu($this->projects, $projectID); - - $projects = array('' => '') + $this->projects; - $project = $this->project->getById($projectID); - $managers = $this->project->getDefaultManagers($projectID); - - /* Remove current project from the projects. */ - unset($projects[$projectID]); - - $header['title'] = $this->lang->project->edit . $this->lang->colon . $project->name; - $position[] = html::a($browseProjectLink, $project->name); - $position[] = $this->lang->project->edit; - - $linkedProducts = $this->project->getProducts($project->id); - $linkedProducts = join(',', array_keys($linkedProducts)); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->projects = $projects; - $this->view->project = $project; - $this->view->poUsers = $this->loadModel('user')->getPairs('noclosed,nodeleted,pofirst'); - $this->view->pmUsers = $this->user->getPairs('noclosed,nodeleted,pmfirst'); - $this->view->qdUsers = $this->user->getPairs('noclosed,nodeleted,qdfirst'); - $this->view->rdUsers = $this->user->getPairs('noclosed,nodeleted,devfirst'); - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->allProducts = $this->loadModel('product')->getPairs(); - $this->view->linkedProducts = $linkedProducts; - - $this->display(); - } - - /** - * Start project. - * - * @param int $projectID - * @access public - * @return void - */ - public function start($projectID) - { - $this->commonAction($projectID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->project->start($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('project', $projectID, 'Started', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->start; - $this->view->position[] = $this->lang->project->start; - $this->display(); - } - - /** - * Delay project. - * - * @param int $projectID - * @access public - * @return void - */ - public function delay($projectID) - { - $this->commonAction($projectID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->project->delay($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('project', $projectID, 'Delayed', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->delay; - $this->view->position[] = $this->lang->project->delay; - $this->display(); - } - - /** - * Suspend project. - * - * @param int $projectID - * @access public - * @return void - */ - public function suspend($projectID) - { - $this->commonAction($projectID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->project->suspend($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('project', $projectID, 'Suspended', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->suspend; - $this->view->position[] = $this->lang->project->suspend; - $this->display(); - } - - /** - * Activate project. - * - * @param int $projectID - * @access public - * @return void - */ - public function activate($projectID) - { - $this->commonAction($projectID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->project->activate($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('project', $projectID, 'Activated', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->activate; - $this->view->position[] = $this->lang->project->activate; - $this->display(); - } - - /** - * Close project. - * - * @param int $projectID - * @access public - * @return void - */ - public function close($projectID) - { - $this->commonAction($projectID); - - if(!empty($_POST)) - { - $this->loadModel('action'); - $changes = $this->project->close($projectID); - if(dao::isError()) die(js::error(dao::getError())); - - if($this->post->comment != '' or !empty($changes)) - { - $actionID = $this->action->create('project', $projectID, 'Closed', $this->post->comment); - $this->action->logHistory($actionID, $changes); - } - die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); - } - - $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->suspend; - $this->view->position[] = $this->lang->project->suspend; - $this->display(); - } - - /** - * View a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function view($projectID) - { - $project = $this->project->getById($projectID, true); - if(!$project) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Set menu. */ - $this->project->setMenu($this->projects, $project->id); - - $this->view->header->title = $this->lang->project->view; - $this->view->position[] = $this->view->header->title; - - $this->view->project = $project; - $this->view->products = $this->project->getProducts($project->id); - $this->view->groups = $this->loadModel('group')->getPairs(); - $this->view->actions = $this->loadModel('action')->getList('project', $projectID); - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - - $this->display(); - } - - /** - * Delete a project. - * - * @param int $projectID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function delete($projectID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm(sprintf($this->lang->project->confirmDelete, $this->projects[$projectID]), $this->createLink('project', 'delete', "projectID=$projectID&confirm=yes")); - exit; - } - else - { - $this->project->delete(TABLE_PROJECT, $projectID); - $this->session->set('project', ''); - die(js::locate(inlink('index'), 'parent')); - } - } - - /** - * Order project - * - * @param int $projectID - * @access public - * @return void - */ - public function order($projectID) - { - if($_POST) - { - $this->project->saveOrder(); - die(js::reload('parent')); - } - $project = $this->commonAction($projectID); - $this->project->setMenu($this->projects, $project->id); - $this->view->projects = $this->project->getList(); - $this->view->projectID = $project->id; - $this->display(); - } - - /** - * Send email. - * - * @param int $taskID - * @param int $actionID - * @access public - * @return void - */ - public function sendmail($taskID, $actionID) - { - /* Set toList and ccList. */ - $task = $this->loadModel('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()); - } - - /** - * Manage products. - * - * @param int $projectID - * @access public - * @return void - */ - public function manageProducts($projectID) - { - $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); - if(!empty($_POST)) - { - $this->project->updateProducts($projectID); - if(dao::isError()) dis(js::error(dao::getError())); - die(js::locate($browseProjectLink)); - } - - $this->loadModel('product'); - $project = $this->project->getById($projectID); - - /* Set menu. */ - $this->project->setMenu($this->projects, $project->id); - - /* Title and position. */ - $header['title'] = $this->lang->project->manageProducts . $this->lang->colon . $project->name; - $position[] = html::a($browseProjectLink, $project->name); - $position[] = $this->lang->project->manageProducts; - - $allProducts = $this->product->getPairs(); - $linkedProducts = $this->project->getProducts($project->id); - $linkedProducts = join(',', array_keys($linkedProducts)); - - /* Assign. */ - $this->view->header = $header; - $this->view->position = $position; - $this->view->allProducts = $allProducts; - $this->view->linkedProducts = $linkedProducts; - - $this->display(); - } - - /** - * Manage childs projects. - * - * @param int $projectID - * @access public - * @return void - */ - public function manageChilds($projectID) - { - $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); - if(!empty($_POST)) - { - $this->project->updateChilds($projectID); - die(js::locate($browseProjectLink)); - } - $project = $this->project->getById($projectID); - $projects = $this->projects; - unset($projects[$projectID]); - unset($projects[$project->parent]); - if(empty($projects)) $this->locate($browseProjectLink); - - /* Header and position. */ - $header['title'] = $this->lang->project->manageChilds . $this->lang->colon . $project->name; - $position[] = html::a($browseProjectLink, $project->name); - $position[] = $this->lang->project->manageChilds; - - $childProjects = $this->project->getChildProjects($project->id); - $childProjects = join(",", array_keys($childProjects)); - - /* Set menu. */ - $this->project->setMenu($this->projects, $project->id); - - /* Assign. */ - $this->view->header = $header; - $this->view->position = $position; - $this->view->projects = $projects; - $this->view->childProjects = $childProjects; - - $this->display(); - } - - /** - * Manage members of the project. - * - * @param int $projectID - * @param int $team2Import the team to import. - * @access public - * @return void - */ - public function manageMembers($projectID = 0, $team2Import = 0) - { - if(!empty($_POST)) - { - $this->project->manageMembers($projectID); - $this->locate($this->createLink('project', 'team', "projectID=$projectID")); - exit; - } - $this->loadModel('user'); - - $project = $this->project->getById($projectID); - $users = $this->user->getPairs('noclosed, nodeleted, devfirst'); - $roles = $this->user->getUserRoles(array_keys($users)); - $currentMembers = $this->project->getTeamMembers($projectID); - $members2Import = $this->project->getMembers2Import($team2Import, array_keys($currentMembers)); - $teams2Import = $this->project->getTeams2Import($this->app->user->account, $projectID); - $teams2Import = array($this->lang->project->copyTeam) + $teams2Import; - - /* The deleted members. */ - foreach($currentMembers as $account => $member) - { - if(!isset($users[$member->account])) $member->account .= $this->lang->user->deleted; - } - - /* Set menu. */ - $this->project->setMenu($this->projects, $project->id); - - $header['title'] = $this->lang->project->manageMembers . $this->lang->colon . $project->name; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); - $position[] = $this->lang->project->manageMembers; - $this->view->header = $header; - $this->view->position = $position; - - $this->view->project = $project; - $this->view->users = $users; - $this->view->roles = $roles; - $this->view->currentMembers = $currentMembers; - $this->view->members2Import = $members2Import; - $this->view->teams2Import = $teams2Import; - $this->view->team2Import = $team2Import; - $this->display(); - } - - /** - * Unlink a memeber. - * - * @param int $projectID - * @param string $account - * @param string $confirm yes|no - * @access public - * @return void - */ - public function unlinkMember($projectID, $account, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->project->confirmUnlinkMember, $this->inlink('unlinkMember', "projectID=$projectID&account=$account&confirm=yes"))); - } - else - { - $this->project->unlinkMember($projectID, $account); - die(js::locate($this->inlink('team', "projectID=$projectID"), 'parent')); - } - } - - /** - * Link stories to a project. - * - * @param int $projectID - * @access public - * @return void - */ - public function linkStory($projectID = 0, $browseType = '', $param = 0) - { - $this->loadModel('story'); - $this->loadModel('product'); - - /* Get projects and products. */ - $project = $this->project->getById($projectID); - $products = $this->project->getProducts($projectID); - $browseLink = $this->createLink('project', 'story', "projectID=$projectID"); - - $this->session->set('storyList', $this->app->getURI(true)); // Save session. - $this->project->setMenu($this->projects, $project->id); // Set menu. - - if(empty($products)) - { - echo js::alert($this->lang->project->errorNoLinkedProducts); - die(js::locate($this->createLink('project', 'manageproducts', "projectID=$projectID"))); - } - - if(!empty($_POST)) - { - $this->project->linkStory($projectID); - die(js::locate($browseLink, 'parent')); - } - - $queryID = ($browseType == 'bySearch') ? (int)$param : 0; - - /* Build search form. */ - unset($this->config->product->search['fields']['module']); - $this->config->product->search['actionURL'] = $this->createLink('project', 'linkStory', "projectID=$projectID&browseType=bySearch&queryID=myQueryID"); - $this->config->product->search['queryID'] = $queryID; - $this->config->product->search['params']['product']['values'] = $products + array('all' => $this->lang->product->allProductsOfProject); - $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getForProducts($products); - $this->loadModel('search')->setSearchParams($this->config->product->search); - - $header['title'] = $project->name . $this->lang->colon . $this->lang->project->linkStory; - $position[] = html::a($browseLink, $project->name); - $position[] = $this->lang->project->linkStory; - - if($browseType == 'bySearch') - { - $allStories = $this->story->getBySearch('', $queryID, 'id', null, $projectID); - } - else - { - $allStories = $this->story->getProductStories(array_keys($products), $moduleID = '0', $status = 'active'); - } - $prjStories = $this->story->getProjectStoryPairs($projectID); - - $this->view->header = $header; - $this->view->position = $position; - $this->view->project = $project; - $this->view->products = $products; - $this->view->allStories = $allStories; - $this->view->prjStories = $prjStories; - $this->view->browseType = $browseType; - $this->view->users = $this->loadModel('user')->getPairs('noletter'); - $this->display(); - } - - /** - * Unlink a story. - * - * @param int $projectID - * @param int $storyID - * @param string $confirm yes|no - * @access public - * @return void - */ - public function unlinkStory($projectID, $storyID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->project->confirmUnlinkStory, $this->createLink('project', 'unlinkstory', "projectID=$projectID&storyID=$storyID&confirm=yes")); - exit; - } - else - { - $this->project->unlinkStory($projectID, $storyID); - echo js::locate($this->app->session->storyList, 'parent'); - exit; - } - } - - /** - * Project dynamic. - * - * @param string $type - * @param string $orderBy - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function dynamic($projectID = 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); - - /* Set the menu. If the projectID = 0, use the indexMenu instead. */ - $this->project->setMenu($this->projects, $projectID); - if($projectID == 0) - { - $this->projects = array('0' => $this->lang->project->selectProject) + $this->projects; - unset($this->lang->project->menu); - $this->lang->project->menu = $this->lang->project->indexMenu; - $this->lang->project->menu->list = $this->project->select($this->projects, 0, 'project', 'dynamic'); - } - - /* 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. */ - $project = $this->project->getByID($projectID); - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->dynamic; - $this->view->position[] = $this->lang->project->dynamic; - - /* Assign. */ - $this->view->projectID = $projectID; - $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, 'all', $projectID); - $this->display(); - } - - /** - * AJAX: get products of a project in html select. - * - * @param int $projectID - * @access public - * @return void - */ - public function ajaxGetProducts($projectID) - { - $products = $this->project->getProducts($projectID); - die(html::select('product', $products, '', 'class="select-3"')); - } - - /** - * AJAX: get team members of the project. - * - * @param int $projectID - * @access public - * @return void - */ - public function ajaxGetMembers($projectID) - { - $users = $this->project->getTeamMemberPairs($projectID); - die(html::select('assignedTo', $users, '')); - } - - /** - * When create a project, help the user. - * - * @param int $projectID - * @access public - * @return void - */ - public function tips($projectID) - { - $this->view->projectID = $projectID; - $this->display('project', 'tips'); - } -} + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +class project extends control +{ + public $projects; + + /** + * Construct function, Set projects. + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + if($this->methodName != 'computeburn') + { + $this->projects = $this->project->getPairs(); + if(!$this->projects and $this->methodName != 'create') $this->locate($this->createLink('project', 'create')); + } + } + + /** + * The index page. + * + * @param string $locate yes|no locate to the browse page or not. + * @param string $status the projects status, if locate is no, then get projects by the $status. + * @param int $projectID + * @access public + * @return void + */ + public function index($locate = 'yes', $status = 'all', $projectID = 0) + { + if(empty($this->projects)) $this->locate($this->createLink('project', 'create')); + if($locate == 'yes') $this->locate($this->createLink('project', 'task')); + + $this->commonAction($projectID); + $this->session->set('projectList', $this->app->getURI(true)); + + $this->app->loadLang('my'); + $this->view->projectStats = $this->project->getProjectStats($status); + + $this->display(); + } + + /** + * Browse a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function browse($projectID = 0) + { + $this->locate($this->createLink($this->moduleName, 'task', "projectID=$projectID")); + } + + /** + * Common actions. + * + * @param int $projectID + * @access public + * @return object current object + */ + public function commonAction($projectID = 0, $extra = '') + { + $this->loadModel('product'); + + /* Get projects and products info. */ + $projectID = $this->project->saveState($projectID, array_keys($this->projects)); + $project = $this->project->getById($projectID); + $products = $this->project->getProducts($project->id); + $childProjects = $this->project->getChildProjects($project->id); + $teamMembers = $this->project->getTeamMembers($project->id); + $actions = $this->loadModel('action')->getList('project', $project->id); + + /* Set menu. */ + $this->project->setMenu($this->projects, $project->id, $extra); + + /* Assign. */ + $this->view->projects = $this->projects; + $this->view->project = $project; + $this->view->childProjects = $childProjects; + $this->view->products = $products; + $this->view->teamMembers = $teamMembers; + $this->view->actions = $actions; + + return $project; + } + + /** + * Tasks of a project. + * + * @param int $projectID + * @param string $status + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function task($projectID = 0, $status = 'all', $param = 0, $orderBy = '', $recTotal = 0, $recPerPage = 100, $pageID = 1) + { + $this->loadModel('tree'); + + /* Set browseType, productID, moduleID and queryID. */ + $browseType = strtolower($status); + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + $moduleID = ($status == 'byModule') ? (int)$param : 0; + $project = $this->commonAction($projectID, $status); + $projectID = $project->id; + + /* Save to session. */ + $uri = $this->app->getURI(true); + $this->app->session->set('taskList', $uri); + $this->app->session->set('storyList', $uri); + $this->app->session->set('projectList', $uri); + + /* Process the order by field. */ + if(!$orderBy) $orderBy = $this->cookie->projectTaskOrder ? $this->cookie->projectTaskOrder : 'status,id_desc'; + setcookie('projectTaskOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); + + /* Header and position. */ + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->task; + $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $this->view->position[] = $this->lang->project->task; + + /* Load pager and get tasks. */ + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $tasks = array(); + if($status == 'byModule') + { + $tasks = $this->loadModel('task')->getTasksByModule($projectID, $this->tree->getAllChildID($moduleID), $orderBy, $pager); + } + elseif($browseType != "bysearch") + { + $status = $status == 'byProject' ? 'all' : $status; + $tasks = $this->loadModel('task')->getProjectTasks($projectID, $status, $orderBy, $pager); + } + else + { + if($queryID) + { + $query = $this->loadModel('search')->getQuery($queryID); + if($query) + { + $this->session->set('taskQuery', $query->sql); + $this->session->set('taskForm', $query->form); + } + else + { + $this->session->set('taskQuery', ' 1 = 1'); + } + } + else + { + if($this->session->taskQuery == false) $this->session->set('taskQuery', ' 1 = 1'); + } + /* Limit current project when no project. */ + if(strpos($this->session->taskQuery, "`project` =") === false) $this->session->set('taskQuery', $this->session->taskQuery . " AND `project` = $projectID"); + + $projectIDs = array_keys($this->project->getPairs()); + $projectQuery = "`project` in (" . implode($projectIDs, ',') . ")"; + $taskQuery = str_replace("`project` = 'all'", $projectQuery, $this->session->taskQuery); // Search all project. + $taskQuery = $this->loadModel('search')->replaceDynamic($taskQuery); + + $this->session->set('taskQueryCondition', $taskQuery); + $this->session->set('taskOnlyCondition', true); + $this->session->set('taskOrderBy', $orderBy); + $tasks = $this->project->getSearchTasks($taskQuery, $pager, $orderBy); + } + + /* Build the search form. */ + $this->config->project->search['actionURL'] = $this->createLink('project', 'task', "projectID=$projectID&status=bySearch¶m=myQueryID"); + $this->config->project->search['queryID'] = $queryID; + $this->config->project->search['params']['project']['values'] = array(''=>'', $projectID => $this->projects[$projectID], 'all' => $this->lang->project->allProject); + $this->config->project->search['params']['module']['values'] = $this->tree->getOptionMenu($projectID, $viewType = 'task', $startModuleID = 0); + $this->loadModel('search')->setSearchParams($this->config->project->search); + + /* Assign. */ + $this->view->tasks = $tasks; + $this->view->summary = $this->project->summary($tasks); + $this->view->tabID = 'task'; + $this->view->pager = $pager; + $this->view->recTotal = $pager->recTotal; + $this->view->recPerPage = $pager->recPerPage; + $this->view->orderBy = $orderBy; + $this->view->browseType = $browseType; + $this->view->status = $status; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->param = $param; + $this->view->projectID = $projectID; + $this->view->project = $project; + $this->view->moduleID = $moduleID; + $this->view->moduleTree = $this->tree->getTreeMenu($projectID, $viewType = 'task', $startModuleID = 0, array('treeModel', 'createTaskLink')); + $this->view->projectTree = $this->project->tree(); + + $this->display(); + } + + /** + * Browse tasks in group. + * + * @param int $projectID + * @param string $groupBy the field to group by + * @access public + * @return void + */ + public function grouptask($projectID = 0, $groupBy = 'story') + { + $project = $this->commonAction($projectID); + $projectID = $project->id; + + /* Save session. */ + $this->app->session->set('taskList', $this->app->getURI(true)); + $this->app->session->set('storyList', $this->app->getURI(true)); + + /* Header and session. */ + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->task; + $this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $this->view->position[] = $this->lang->project->task; + + /* Get tasks and group them. */ + $tasks = $this->loadModel('task')->getProjectTasks($projectID, $status = 'all', $groupBy ? $groupBy : 'story'); + $groupBy = strtolower(str_replace('`', '', $groupBy)); + $taskLang = $this->lang->task; + $groupByList = array(); + $groupTasks = array(); + + /* Get users. */ + $users = $this->loadModel('user')->getPairs('noletter'); + foreach($tasks as $task) + { + if($groupBy == '') + { + $groupTasks[$task->story][] = $task; + $groupByList[$task->story] = $task->storyTitle; + } + elseif($groupBy == 'story') + { + $groupTasks[$task->story][] = $task; + $groupByList[$task->story] = $task->storyTitle; + } + elseif($groupBy == 'status') + { + $groupTasks[$taskLang->statusList[$task->status]][] = $task; + } + elseif($groupBy == 'assignedto') + { + $groupTasks[$task->assignedToRealName][] = $task; + } + elseif($groupBy == 'openedby') + { + $groupTasks[$users[$task->openedBy]][] = $task; + } + elseif($groupBy == 'finishedby') + { + $groupTasks[$users[$task->finishedBy]][] = $task; + } + elseif($groupBy == 'closedby') + { + $groupTasks[$users[$task->closedBy]][] = $task; + } + elseif($groupBy == 'type') + { + $groupTasks[$taskLang->typeList[$task->type]][] = $task; + } + else + { + $groupTasks[$task->$groupBy][] = $task; + } + } + + /* Assign. */ + $this->view->members = $this->project->getTeamMembers($projectID); + $this->view->tasks = $groupTasks; + $this->view->tabID = 'task'; + $this->view->groupByList = $groupByList; + $this->view->browseType = 'group'; + $this->view->groupBy = $groupBy; + $this->view->orderBy = $groupBy; + $this->view->projectID = $projectID; + $this->view->users = $users; + $this->display(); + } + + /** + * Import tasks undoned from other projects. + * + * @param int $projectID + * @access public + * @return void + */ + public function importTask($toProject, $fromProject = 0) + { + if(!empty($_POST)) + { + $this->project->importTask($toProject,$fromProject); + die(js::locate(inlink('task', "projectID=$toProject"), 'parent')); + } + + $project = $this->commonAction($toProject); + $projects = $this->project->getProjectsToImport(); + unset($projects[$toProject]); + + $fromProject = ($fromProject == 0 and !empty($projects)) ? key($projects) : $fromProject; + + /* Save session. */ + $this->app->session->set('taskList', $this->app->getURI(true)); + $this->app->session->set('storyList', $this->app->getURI(true)); + + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->importTask; + $this->view->position[] = html::a(inlink('browse', "projectID=$toProject"), $project->name); + $this->view->position[] = $this->lang->project->importTask; + $this->view->tasks2Imported = $this->project->getTasks2Imported($fromProject); + $this->view->projects = $projects; + $this->view->projectID = $project->id; + $this->view->fromProject = $fromProject; + $this->display(); + } + + /** + * Import from Bug. + * + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function importBug($projectID = 0, $browseType = 'all', $param = 0, $recTotal = 0, $recPerPage = 30, $pageID = 1) + { + if(!empty($_POST)) + { + $mails = $this->project->importBug($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($this->createLink('project', 'importBug', "projectID=$projectID"), 'parent')); + } + + /* Set browseType, productID, moduleID and queryID. */ + $browseType = strtolower($browseType); + $queryID = ($browseType == 'bysearch') ? (int)$param : 0; + + /* Save to session. */ + $uri = $this->app->getURI(true); + $this->app->session->set('bugList', $uri); + $this->app->session->set('storyList', $uri); + $this->app->session->set('projectList', $uri); + + $this->loadModel('bug'); + $projects = $this->project->getPairs(); + $this->project->setMenu($projects, $projectID); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + + $header['title'] = $projects[$projectID] . $this->lang->colon . $this->lang->project->importBug; + $position[] = html::a($this->createLink('project', 'task', "projectID=$projectID"), $projects[$projectID]); + $position[] = $this->lang->project->importBug; + + /* Get users, products and projects.*/ + $users = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + $products = $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('product'); + if(!empty($products)) + { + unset($projects); + $projects = $this->dao->select('t1.project, t2.name')->from(TABLE_PROJECTPRODUCT)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.product')->in(array_keys($products)) + ->fetchPairs('project'); + } + else + { + $projectName = $projects[$projectID]; + unset($projects); + $projects[$projectID] = $projectName; + } + + /* Get bugs.*/ + $bugs = array(); + if($browseType != "bysearch") + { + $bugs = $this->bug->getActiveBugs($pager, $projectID, array_keys($products)); + } + else + { + 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'); + } + $bugQuery = str_replace("`product` = 'all'", "`product`" . helper::dbIN(array_keys($products)), $this->session->bugQuery); // Search all project. + $bugs = $this->project->getSearchBugs($products, $projectID, $bugQuery, $pager, 'id_desc'); + } + + /* Build the search form. */ + $this->config->bug->search['actionURL'] = $this->createLink('project', 'importBug', "projectID=$projectID&browseType=bySearch¶m=myQueryID"); + $this->config->bug->search['queryID'] = $queryID; + if(!empty($products)) + { + $this->config->bug->search['params']['product']['values'] = array(''=>'') + $products + array('all'=>$this->lang->project->aboveAllProduct); + } + else + { + $this->config->bug->search['params']['product']['values'] = array(''=>''); + } + $this->config->bug->search['params']['project']['values'] = array(''=>'') + $projects + array('all'=>$this->lang->project->aboveAllProject); + $this->config->bug->search['module'] = 'importBug'; + unset($this->config->bug->search['fields']['resolvedBy']); + unset($this->config->bug->search['fields']['closedBy']); + unset($this->config->bug->search['fields']['status']); + unset($this->config->bug->search['fields']['toTask']); + unset($this->config->bug->search['fields']['toStory']); + unset($this->config->bug->search['fields']['severity']); + unset($this->config->bug->search['fields']['resolution']); + unset($this->config->bug->search['fields']['resolvedBuild']); + unset($this->config->bug->search['fields']['resolvedDate']); + unset($this->config->bug->search['fields']['closedDate']); + unset($this->config->bug->search['params']['resolvedBy']); + unset($this->config->bug->search['params']['closedBy']); + unset($this->config->bug->search['params']['status']); + unset($this->config->bug->search['params']['toTask']); + unset($this->config->bug->search['params']['toStory']); + unset($this->config->bug->search['params']['severity']); + unset($this->config->bug->search['params']['resolution']); + unset($this->config->bug->search['params']['resolvedBuild']); + unset($this->config->bug->search['params']['resolvedDate']); + unset($this->config->bug->search['params']['closedDate']); + $this->loadModel('search')->setSearchParams($this->config->bug->search); + + /* Assign. */ + $this->view->header = $header; + $this->view->pager = $pager; + $this->view->bugs = $bugs; + $this->view->recTotal = $pager->recTotal; + $this->view->recPerPage = $pager->recPerPage; + $this->view->browseType = $browseType; + $this->view->param = $param; + $this->view->users = $users; + $this->view->projectID = $projectID; + $this->display(); + } + + /** + * Browse stories of a project. + * + * @param int $projectID + * @param string $orderBy + * @access public + * @return void + */ + public function story($projectID = 0, $orderBy = '') + { + /* Load these models. */ + $this->loadModel('story'); + $this->loadModel('user'); + $this->loadModel('task'); + + /* Save session. */ + $this->app->session->set('storyList', $this->app->getURI(true)); + + /* Process the order by field. */ + if(!$orderBy) $orderBy = $this->cookie->projectStoryOrder ? $this->cookie->projectStoryOrder : 'pri'; + setcookie('projectStoryOrder', $orderBy, $this->config->cookieLife, $this->config->webRoot); + + $project = $this->commonAction($projectID); + + /* Header and position. */ + $header['title'] = $project->name . $this->lang->colon . $this->lang->project->story; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $position[] = $this->lang->project->story; + + /* The pager. */ + $stories = $this->story->getProjectStories($projectID, $orderBy); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story', false); + $storyTasks = $this->task->getStoryTaskCounts(array_keys($stories), $projectID); + $users = $this->user->getPairs('noletter'); + + /* Save storyIDs session for get the pre and next story. */ + $storyIDs = ''; + foreach($stories as $story) $storyIDs .= ',' . $story->id; + $this->session->set('storyIDs', $storyIDs . ','); + + /* Get project's product. */ + $productID = 0; + $products = $this->loadModel('product')->getProductsByProject($projectID); + if($products) $productID = key($products); + + /* Assign. */ + $this->view->header = $header; + $this->view->position = $position; + $this->view->productID = $productID; + $this->view->stories = $stories; + $this->view->orderBy = $orderBy; + $this->view->storyTasks = $storyTasks; + $this->view->tabID = 'story'; + $this->view->users = $users; + + $this->display(); + } + + /** + * Browse bugs of a project. + * + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function bug($projectID = 0, $orderBy = 'status,id_desc', $build = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Load these two models. */ + $this->loadModel('bug'); + $this->loadModel('user'); + + /* Save session. */ + $this->session->set('bugList', $this->app->getURI(true)); + + $project = $this->commonAction($projectID); + $products = $this->project->getProducts($project->id); + $productID = key($products); // Get the first product for creating bug. + + /* Header and position. */ + $header['title'] = $project->name . $this->lang->colon . $this->lang->project->bug; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $position[] = $this->lang->project->bug; + + /* Load pager and get bugs, user. */ + $this->app->loadClass('pager', $static = true); + $pager = new pager($recTotal, $recPerPage, $pageID); + $bugs = $this->bug->getProjectBugs($projectID, $orderBy, $pager, $build); + $users = $this->user->getPairs('noletter'); + + /* Assign. */ + $this->view->header = $header; + $this->view->position = $position; + $this->view->bugs = $bugs; + $this->view->tabID = 'bug'; + $this->view->build = $this->loadModel('build')->getById($build); + $this->view->buildID = $this->view->build ? $this->view->build->id : 0; + $this->view->pager = $pager; + $this->view->orderBy = $orderBy; + $this->view->users = $users; + $this->view->productID = $productID; + + $this->display(); + } + + /** + * Browse builds of a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function build($projectID = 0) + { + $this->loadModel('testtask'); + $this->session->set('buildList', $this->app->getURI(true)); + + $project = $this->commonAction($projectID); + + /* Header and position. */ + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->build; + $this->view->position[] = html::a(inlink('browse', "projectID=$projectID"), $project->name); + $this->view->position[] = $this->lang->project->build; + + /* Get builds. */ + $this->view->builds = $this->loadModel('build')->getProjectBuilds((int)$projectID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + + $this->display(); + } + + /** + * Browse test tasks of project. + * + * @param int $projectID + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function testtask($projectID = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $this->loadModel('testtask'); + /* Save session. */ + $this->session->set('testtaskList', $this->app->getURI(true)); + + $project = $this->commonAction($projectID); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + $this->view->header->title = $this->projects[$projectID] . $this->lang->colon . $this->lang->testtask->common; + $this->view->position[] = html::a($this->createLink('project', 'testtask', "projectID=$projectID"), $this->projects[$projectID]); + $this->view->position[] = $this->lang->testtask->common; + $this->view->projectID = $projectID; + $this->view->projectName = $this->projects[$projectID]; + $this->view->pager = $pager; + $this->view->orderBy = $orderBy; + $this->view->tasks = $this->testtask->getProjectTasks($projectID); + $this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter'); + + $this->display(); + } + + /** + * Browse burndown chart of a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function burn($projectID = 0) + { + $this->loadModel('report'); + $project = $this->commonAction($projectID); + $projectInfo = $this->project->getByID($project->id); + $maxDays = $this->config->project->maxBurnDay; + + /* Header and position. */ + $header['title'] = $project->name . $this->lang->colon . $this->lang->project->burn; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $position[] = $this->lang->project->burn; + + /* Create charts by flash. */ + //$dataXML = $this->report->createSingleXML($this->project->getBurnData($project->id), $this->lang->project->charts->burn->graph, $this->lang->report->singleColor); + //$charts = $this->report->createJSChart('line', $dataXML, 700, 350); + + /* Create charts by flot. */ + $sets = $this->project->getBurnDataFlot($project->id); + $count = count($sets); + $dataJSON = $this->report->createSingleJSON($sets); + + $limitJSON = '[]'; + $reflineJSON = '[]'; + $beginMicTime = $this->project->getMicTime($projectInfo->begin); + $endMicTime = $this->project->getMicTime($projectInfo->end); + $maxDayMicTime = $this->project->getMicTime(strtotime($projectInfo->begin) + $maxDays * 24 * 3600); + $minDayMicTime = $this->project->getMicTime(time() - $maxDays * 24 * 3600); + if($projectInfo->days <= $maxDays) + { + $limitJSON = "[[$beginMicTime, 0], [$endMicTime, 0]]"; + $firstBurn = reset($sets); + $firstTime = isset($firstBurn->value) ? $firstBurn->value : 0; + $reflineJSON = "[[$beginMicTime, $firstTime], [$endMicTime, 0]]"; + } + elseif($count <= $maxDays) + { + $limitJSON = "[[$beginMicTime, 0], [$maxDayMicTime, 0]]"; + } + + $flotJSON['data'] = $dataJSON; + $flotJSON['limit'] = $limitJSON; + $flotJSON['refline'] = $reflineJSON; + + $charts = $this->report->createJSChartFlot($project->name, $flotJSON, $count, 900, 400); + + /* Assign. */ + $this->view->header = $header; + $this->view->position = $position; + $this->view->tabID = 'burn'; + $this->view->charts = $charts; + $this->view->projectID = $projectID; + + $this->display(); + } + + /** + * Get data of burndown chart. + * + * @param int $projectID + * @access public + * @return void + */ + public function burnData($projectID = 0) + { + $this->loadModel('report'); + $sets = $this->project->getBurnData($projectID); + die($this->report->createSingleXML($sets, $this->lang->project->charts->burn->graph)); + } + + /** + * Compute burndown datas. + * + * @param string $reload + * @access public + * @return void + */ + public function computeBurn($reload = 'no') + { + $this->view->burns = $this->project->computeBurn(); + if($reload == 'yes') die(js::reload('parent')); + die($this->display()); + } + + /** + * Browse team of a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function team($projectID = 0) + { + $project = $this->commonAction($projectID); + + $header['title'] = $project->name . $this->lang->colon . $this->lang->project->team; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $position[] = $this->lang->project->team; + + $this->view->header = $header; + $this->view->position = $position; + + $this->display(); + } + + /** + * Docs of a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function doc($projectID) + { + $this->project->setMenu($this->projects, $projectID); + $this->session->set('docList', $this->app->getURI(true)); + + $project = $this->dao->findById($projectID)->from(TABLE_PROJECT)->fetch(); + $this->view->header->title = $this->lang->project->doc; + $this->view->position[] = html::a($this->createLink($this->moduleName, 'browse'), $project->name); + $this->view->position[] = $this->lang->project->doc; + $this->view->project = $project; + $this->view->docs = $this->loadModel('doc')->getProjectDocs($projectID); + $this->view->modules = $this->doc->getProjectModulePairs(); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Create a project. + * + * @access public + * @return void + */ + public function create($projectID = '', $copyProjectID = '') + { + if($projectID) + { + $this->view->tips = $this->fetch('project', 'tips', "projectID=$projectID"); + $this->view->projectID = $projectID; + $this->display(); + exit; + } + + $name = ''; + $code = ''; + $team = ''; + $products = ''; + $whitelist = ''; + $acl = 'open'; + + if($copyProjectID) + { + $copyProject = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($copyProjectID)->fetch(); + $name = $copyProject->name; + $code = $copyProject->code; + $team = $copyProject->team; + $acl = $copyProject->acl; + $whitelist = $copyProject->whitelist; + $products = join(',', array_keys($this->project->getProducts($copyProjectID))); + } + + if(!empty($_POST)) + { + $projectID = $copyProjectID == '' ? $this->project->create() : $this->project->create($copyProjectID); + $this->project->updateProducts($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + $this->loadModel('action')->create('project', $projectID, 'opened'); + die(js::locate($this->createLink('project', 'create', "projectID=$projectID"), 'parent')); + } + + $this->project->setMenu($this->projects, key($this->projects)); + + $this->view->header->title = $this->lang->project->create; + $this->view->position[] = $this->view->header->title; + $this->view->projects = array('' => '') + $this->projects; + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->allProducts = $this->loadModel('product')->getPairs(); + $this->view->name = $name; + $this->view->code = $code; + $this->view->team = $team; + $this->view->products = $products ; + $this->view->whitelist = $whitelist; + $this->view->acl = $acl ; + $this->view->copyProjectID = $copyProjectID; + $this->display(); + } + + /** + * Edit a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function edit($projectID) + { + $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); + if(!empty($_POST)) + { + $changes = $this->project->update($projectID); + $this->project->updateProducts($projectID); + if(dao::isError()) die(js::error(dao::getError())); + if($changes) + { + $actionID = $this->loadModel('action')->create('project', $projectID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + /* Set menu. */ + $this->project->setMenu($this->projects, $projectID); + + $projects = array('' => '') + $this->projects; + $project = $this->project->getById($projectID); + $managers = $this->project->getDefaultManagers($projectID); + + /* Remove current project from the projects. */ + unset($projects[$projectID]); + + $header['title'] = $this->lang->project->edit . $this->lang->colon . $project->name; + $position[] = html::a($browseProjectLink, $project->name); + $position[] = $this->lang->project->edit; + + $linkedProducts = $this->project->getProducts($project->id); + $linkedProducts = join(',', array_keys($linkedProducts)); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->projects = $projects; + $this->view->project = $project; + $this->view->poUsers = $this->loadModel('user')->getPairs('noclosed,nodeleted,pofirst'); + $this->view->pmUsers = $this->user->getPairs('noclosed,nodeleted,pmfirst'); + $this->view->qdUsers = $this->user->getPairs('noclosed,nodeleted,qdfirst'); + $this->view->rdUsers = $this->user->getPairs('noclosed,nodeleted,devfirst'); + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->allProducts = $this->loadModel('product')->getPairs(); + $this->view->linkedProducts = $linkedProducts; + + $this->display(); + } + + /** + * Start project. + * + * @param int $projectID + * @access public + * @return void + */ + public function start($projectID) + { + $this->commonAction($projectID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->project->start($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('project', $projectID, 'Started', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->start; + $this->view->position[] = $this->lang->project->start; + $this->display(); + } + + /** + * Delay project. + * + * @param int $projectID + * @access public + * @return void + */ + public function delay($projectID) + { + $this->commonAction($projectID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->project->delay($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('project', $projectID, 'Delayed', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->delay; + $this->view->position[] = $this->lang->project->delay; + $this->display(); + } + + /** + * Suspend project. + * + * @param int $projectID + * @access public + * @return void + */ + public function suspend($projectID) + { + $this->commonAction($projectID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->project->suspend($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('project', $projectID, 'Suspended', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->suspend; + $this->view->position[] = $this->lang->project->suspend; + $this->display(); + } + + /** + * Activate project. + * + * @param int $projectID + * @access public + * @return void + */ + public function activate($projectID) + { + $this->commonAction($projectID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->project->activate($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('project', $projectID, 'Activated', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->activate; + $this->view->position[] = $this->lang->project->activate; + $this->display(); + } + + /** + * Close project. + * + * @param int $projectID + * @access public + * @return void + */ + public function close($projectID) + { + $this->commonAction($projectID); + + if(!empty($_POST)) + { + $this->loadModel('action'); + $changes = $this->project->close($projectID); + if(dao::isError()) die(js::error(dao::getError())); + + if($this->post->comment != '' or !empty($changes)) + { + $actionID = $this->action->create('project', $projectID, 'Closed', $this->post->comment); + $this->action->logHistory($actionID, $changes); + } + die(js::locate($this->createLink('project', 'view', "projectID=$projectID"), 'parent')); + } + + $this->view->header->title = $this->view->project->name . $this->lang->colon .$this->lang->project->suspend; + $this->view->position[] = $this->lang->project->suspend; + $this->display(); + } + + /** + * View a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function view($projectID) + { + $project = $this->project->getById($projectID, true); + if(!$project) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Set menu. */ + $this->project->setMenu($this->projects, $project->id); + + $this->view->header->title = $this->lang->project->view; + $this->view->position[] = $this->view->header->title; + + $this->view->project = $project; + $this->view->products = $this->project->getProducts($project->id); + $this->view->groups = $this->loadModel('group')->getPairs(); + $this->view->actions = $this->loadModel('action')->getList('project', $projectID); + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + + $this->display(); + } + + /** + * Delete a project. + * + * @param int $projectID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function delete($projectID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm(sprintf($this->lang->project->confirmDelete, $this->projects[$projectID]), $this->createLink('project', 'delete', "projectID=$projectID&confirm=yes")); + exit; + } + else + { + $this->project->delete(TABLE_PROJECT, $projectID); + $this->session->set('project', ''); + die(js::locate(inlink('index'), 'parent')); + } + } + + /** + * Order project + * + * @param int $projectID + * @access public + * @return void + */ + public function order($projectID) + { + if($_POST) + { + $this->project->saveOrder(); + die(js::reload('parent')); + } + $project = $this->commonAction($projectID); + $this->project->setMenu($this->projects, $project->id); + $this->view->projects = $this->project->getList(); + $this->view->projectID = $project->id; + $this->display(); + } + + /** + * Send email. + * + * @param int $taskID + * @param int $actionID + * @access public + * @return void + */ + public function sendmail($taskID, $actionID) + { + /* Set toList and ccList. */ + $task = $this->loadModel('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()); + } + + /** + * Manage products. + * + * @param int $projectID + * @access public + * @return void + */ + public function manageProducts($projectID) + { + $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); + if(!empty($_POST)) + { + $this->project->updateProducts($projectID); + if(dao::isError()) dis(js::error(dao::getError())); + die(js::locate($browseProjectLink)); + } + + $this->loadModel('product'); + $project = $this->project->getById($projectID); + + /* Set menu. */ + $this->project->setMenu($this->projects, $project->id); + + /* Title and position. */ + $header['title'] = $this->lang->project->manageProducts . $this->lang->colon . $project->name; + $position[] = html::a($browseProjectLink, $project->name); + $position[] = $this->lang->project->manageProducts; + + $allProducts = $this->product->getPairs(); + $linkedProducts = $this->project->getProducts($project->id); + $linkedProducts = join(',', array_keys($linkedProducts)); + + /* Assign. */ + $this->view->header = $header; + $this->view->position = $position; + $this->view->allProducts = $allProducts; + $this->view->linkedProducts = $linkedProducts; + + $this->display(); + } + + /** + * Manage childs projects. + * + * @param int $projectID + * @access public + * @return void + */ + public function manageChilds($projectID) + { + $browseProjectLink = $this->createLink('project', 'browse', "projectID=$projectID"); + if(!empty($_POST)) + { + $this->project->updateChilds($projectID); + die(js::locate($browseProjectLink)); + } + $project = $this->project->getById($projectID); + $projects = $this->projects; + unset($projects[$projectID]); + unset($projects[$project->parent]); + if(empty($projects)) $this->locate($browseProjectLink); + + /* Header and position. */ + $header['title'] = $this->lang->project->manageChilds . $this->lang->colon . $project->name; + $position[] = html::a($browseProjectLink, $project->name); + $position[] = $this->lang->project->manageChilds; + + $childProjects = $this->project->getChildProjects($project->id); + $childProjects = join(",", array_keys($childProjects)); + + /* Set menu. */ + $this->project->setMenu($this->projects, $project->id); + + /* Assign. */ + $this->view->header = $header; + $this->view->position = $position; + $this->view->projects = $projects; + $this->view->childProjects = $childProjects; + + $this->display(); + } + + /** + * Manage members of the project. + * + * @param int $projectID + * @param int $team2Import the team to import. + * @access public + * @return void + */ + public function manageMembers($projectID = 0, $team2Import = 0) + { + if(!empty($_POST)) + { + $this->project->manageMembers($projectID); + $this->locate($this->createLink('project', 'team', "projectID=$projectID")); + exit; + } + $this->loadModel('user'); + + $project = $this->project->getById($projectID); + $users = $this->user->getPairs('noclosed, nodeleted, devfirst'); + $roles = $this->user->getUserRoles(array_keys($users)); + $currentMembers = $this->project->getTeamMembers($projectID); + $members2Import = $this->project->getMembers2Import($team2Import, array_keys($currentMembers)); + $teams2Import = $this->project->getTeams2Import($this->app->user->account, $projectID); + $teams2Import = array($this->lang->project->copyTeam) + $teams2Import; + + /* The deleted members. */ + foreach($currentMembers as $account => $member) + { + if(!isset($users[$member->account])) $member->account .= $this->lang->user->deleted; + } + + /* Set menu. */ + $this->project->setMenu($this->projects, $project->id); + + $header['title'] = $this->lang->project->manageMembers . $this->lang->colon . $project->name; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name); + $position[] = $this->lang->project->manageMembers; + $this->view->header = $header; + $this->view->position = $position; + + $this->view->project = $project; + $this->view->users = $users; + $this->view->roles = $roles; + $this->view->currentMembers = $currentMembers; + $this->view->members2Import = $members2Import; + $this->view->teams2Import = $teams2Import; + $this->view->team2Import = $team2Import; + $this->display(); + } + + /** + * Unlink a memeber. + * + * @param int $projectID + * @param string $account + * @param string $confirm yes|no + * @access public + * @return void + */ + public function unlinkMember($projectID, $account, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->project->confirmUnlinkMember, $this->inlink('unlinkMember', "projectID=$projectID&account=$account&confirm=yes"))); + } + else + { + $this->project->unlinkMember($projectID, $account); + die(js::locate($this->inlink('team', "projectID=$projectID"), 'parent')); + } + } + + /** + * Link stories to a project. + * + * @param int $projectID + * @access public + * @return void + */ + public function linkStory($projectID = 0, $browseType = '', $param = 0) + { + $this->loadModel('story'); + $this->loadModel('product'); + + /* Get projects and products. */ + $project = $this->project->getById($projectID); + $products = $this->project->getProducts($projectID); + $browseLink = $this->createLink('project', 'story', "projectID=$projectID"); + + $this->session->set('storyList', $this->app->getURI(true)); // Save session. + $this->project->setMenu($this->projects, $project->id); // Set menu. + + if(empty($products)) + { + echo js::alert($this->lang->project->errorNoLinkedProducts); + die(js::locate($this->createLink('project', 'manageproducts', "projectID=$projectID"))); + } + + if(!empty($_POST)) + { + $this->project->linkStory($projectID); + die(js::locate($browseLink, 'parent')); + } + + $queryID = ($browseType == 'bySearch') ? (int)$param : 0; + + /* Build search form. */ + unset($this->config->product->search['fields']['module']); + $this->config->product->search['actionURL'] = $this->createLink('project', 'linkStory', "projectID=$projectID&browseType=bySearch&queryID=myQueryID"); + $this->config->product->search['queryID'] = $queryID; + $this->config->product->search['params']['product']['values'] = $products + array('all' => $this->lang->product->allProductsOfProject); + $this->config->product->search['params']['plan']['values'] = $this->loadModel('productplan')->getForProducts($products); + $this->loadModel('search')->setSearchParams($this->config->product->search); + + $header['title'] = $project->name . $this->lang->colon . $this->lang->project->linkStory; + $position[] = html::a($browseLink, $project->name); + $position[] = $this->lang->project->linkStory; + + if($browseType == 'bySearch') + { + $allStories = $this->story->getBySearch('', $queryID, 'id', null, $projectID); + } + else + { + $allStories = $this->story->getProductStories(array_keys($products), $moduleID = '0', $status = 'active'); + } + $prjStories = $this->story->getProjectStoryPairs($projectID); + + $this->view->header = $header; + $this->view->position = $position; + $this->view->project = $project; + $this->view->products = $products; + $this->view->allStories = $allStories; + $this->view->prjStories = $prjStories; + $this->view->browseType = $browseType; + $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->display(); + } + + /** + * Unlink a story. + * + * @param int $projectID + * @param int $storyID + * @param string $confirm yes|no + * @access public + * @return void + */ + public function unlinkStory($projectID, $storyID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->project->confirmUnlinkStory, $this->createLink('project', 'unlinkstory', "projectID=$projectID&storyID=$storyID&confirm=yes")); + exit; + } + else + { + $this->project->unlinkStory($projectID, $storyID); + echo js::locate($this->app->session->storyList, 'parent'); + exit; + } + } + + /** + * Project dynamic. + * + * @param string $type + * @param string $orderBy + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function dynamic($projectID = 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); + + /* Set the menu. If the projectID = 0, use the indexMenu instead. */ + $this->project->setMenu($this->projects, $projectID); + if($projectID == 0) + { + $this->projects = array('0' => $this->lang->project->selectProject) + $this->projects; + unset($this->lang->project->menu); + $this->lang->project->menu = $this->lang->project->indexMenu; + $this->lang->project->menu->list = $this->project->select($this->projects, 0, 'project', 'dynamic'); + } + + /* 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. */ + $project = $this->project->getByID($projectID); + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->project->dynamic; + $this->view->position[] = $this->lang->project->dynamic; + + /* Assign. */ + $this->view->projectID = $projectID; + $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, 'all', $projectID); + $this->display(); + } + + /** + * AJAX: get products of a project in html select. + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetProducts($projectID) + { + $products = $this->project->getProducts($projectID); + die(html::select('product', $products, '', 'class="select-3"')); + } + + /** + * AJAX: get team members of the project. + * + * @param int $projectID + * @access public + * @return void + */ + public function ajaxGetMembers($projectID) + { + $users = $this->project->getTeamMemberPairs($projectID); + die(html::select('assignedTo', $users, '')); + } + + /** + * When create a project, help the user. + * + * @param int $projectID + * @access public + * @return void + */ + public function tips($projectID) + { + $this->view->projectID = $projectID; + $this->display('project', 'tips'); + } +} diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 8221f28d79..1a49384ae9 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -1,206 +1,206 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -/* Fields. */ -$lang->project->common = 'Project'; -$lang->project->id = 'ID'; -$lang->project->company = 'Company'; -$lang->project->fromproject = 'FromProject'; -$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->day = 'day'; -$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->QD = 'Quality director'; -$lang->project->RD = 'Release director'; -$lang->project->acl = 'Access limitation'; -$lang->project->teamname = 'Team name'; -$lang->project->order = 'Project order'; -$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->project->createStory = "Create story"; -$lang->project->all = 'All'; - -$lang->project->start = 'Start'; -$lang->project->activate = 'Activate'; -$lang->project->delay = 'Delay'; -$lang->project->suspend = 'Suspend'; -$lang->project->close = 'Close'; - -$lang->project->endList[14] = 'Two Weeks'; -$lang->project->endList[31] = 'One Month'; -$lang->project->endList[62] = 'Two Months'; -$lang->project->endList[93] = 'Three Months'; -$lang->project->endList[186] = 'Half Of Year'; -$lang->project->endList[365] = 'One Year'; - -$lang->team = new stdclass(); -$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'; - -$lang->project->basicInfo = 'Basic info'; -$lang->project->otherInfo = 'Other info'; - -/* Lists. */ -$lang->project->statusList['wait'] = 'Pending'; -$lang->project->statusList['doing'] = 'Progressing'; -$lang->project->statusList['suspended'] = 'Suspended'; -$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'; -$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->copy = "Copy a project"; -$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 = 'Transfer 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->statusSelects[''] = 'More'; -$lang->project->statusSelects['finishedbyme'] = 'Mydone'; -$lang->project->statusSelects['wait'] = 'Pending'; -$lang->project->statusSelects['doing'] = 'Progressing'; -$lang->project->statusSelects['done'] = 'Done'; -$lang->project->statusSelects['closed'] = 'Closed'; -$lang->project->statusSelects['delayed'] = 'Delayed'; -$lang->project->statusSelects['needconfirm'] = 'Story changed'; -$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->moduleTask = 'Module'; -$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 = "Total tasks shown: %s. Pending: %s. In progress: %s. Estimate: %s hrs. Consumed: %s hrs. Hours left: %s."; -$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->batchWBS = "Batch 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'; -$lang->project->copyTeam = 'Copy a team'; - -/* 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 = new stdclass(); -$lang->project->charts->burn = new stdclass(); -$lang->project->charts->burn->graph = new stdclass(); -$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; - -$lang->project->placeholder = new stdclass(); -$lang->project->placeholder->code = 'Project code'; - -$lang->project->selectGroup = new stdclass(); -$lang->project->selectGroup->doing = '(Doing)'; -$lang->project->selectGroup->suspended = '(Suspended)'; -$lang->project->selectGroup->done = '(Done)'; - -$lang->project->projectTasks = 'ProjectTasks'; + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +/* Fields. */ +$lang->project->common = 'Project'; +$lang->project->id = 'ID'; +$lang->project->company = 'Company'; +$lang->project->fromproject = 'FromProject'; +$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->day = 'day'; +$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->QD = 'Quality director'; +$lang->project->RD = 'Release director'; +$lang->project->acl = 'Access limitation'; +$lang->project->teamname = 'Team name'; +$lang->project->order = 'Project order'; +$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->project->createStory = "Create story"; +$lang->project->all = 'All'; + +$lang->project->start = 'Start'; +$lang->project->activate = 'Activate'; +$lang->project->delay = 'Delay'; +$lang->project->suspend = 'Suspend'; +$lang->project->close = 'Close'; + +$lang->project->endList[14] = 'Two Weeks'; +$lang->project->endList[31] = 'One Month'; +$lang->project->endList[62] = 'Two Months'; +$lang->project->endList[93] = 'Three Months'; +$lang->project->endList[186] = 'Half Of Year'; +$lang->project->endList[365] = 'One Year'; + +$lang->team = new stdclass(); +$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'; + +$lang->project->basicInfo = 'Basic info'; +$lang->project->otherInfo = 'Other info'; + +/* Lists. */ +$lang->project->statusList['wait'] = 'Pending'; +$lang->project->statusList['doing'] = 'Progressing'; +$lang->project->statusList['suspended'] = 'Suspended'; +$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'; +$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->copy = "Copy a project"; +$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 = 'Transfer 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->statusSelects[''] = 'More'; +$lang->project->statusSelects['finishedbyme'] = 'Mydone'; +$lang->project->statusSelects['wait'] = 'Pending'; +$lang->project->statusSelects['doing'] = 'Progressing'; +$lang->project->statusSelects['done'] = 'Done'; +$lang->project->statusSelects['closed'] = 'Closed'; +$lang->project->statusSelects['delayed'] = 'Delayed'; +$lang->project->statusSelects['needconfirm'] = 'Story changed'; +$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->moduleTask = 'Module'; +$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 = "Total tasks shown: %s. Pending: %s. In progress: %s. Estimate: %s hrs. Consumed: %s hrs. Hours left: %s."; +$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->batchWBS = "Batch 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'; +$lang->project->copyTeam = 'Copy a team'; + +/* 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 = new stdclass(); +$lang->project->charts->burn = new stdclass(); +$lang->project->charts->burn->graph = new stdclass(); +$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; + +$lang->project->placeholder = new stdclass(); +$lang->project->placeholder->code = 'Project code'; + +$lang->project->selectGroup = new stdclass(); +$lang->project->selectGroup->doing = '(Doing)'; +$lang->project->selectGroup->suspended = '(Suspended)'; +$lang->project->selectGroup->done = '(Done)'; + +$lang->project->projectTasks = 'ProjectTasks'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index aa217f81d3..7ec508c71a 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -1,206 +1,206 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -/* 字段列表。*/ -$lang->project->common = '项目视图'; -$lang->project->id = '项目编号'; -$lang->project->company = '所属公司'; -$lang->project->fromproject = '所属项目'; -$lang->project->iscat = '作为目录'; -$lang->project->type = '项目类型'; -$lang->project->parent = '上级项目'; -$lang->project->name = '项目名称'; -$lang->project->code = '项目代号'; -$lang->project->begin = '开始日期'; -$lang->project->end = '结束日期'; -$lang->project->days = '可用工作日'; -$lang->project->day = '天'; -$lang->project->status = '项目状态'; -$lang->project->statge = '所处阶段'; -$lang->project->pri = '优先级'; -$lang->project->desc = '项目描述'; -$lang->project->goal = '项目目标'; -$lang->project->openedBy = '由谁创建'; -$lang->project->openedDate = '创建日期'; -$lang->project->closedBy = '由谁关闭'; -$lang->project->closedDate = '关闭日期'; -$lang->project->canceledBy = '由谁取消'; -$lang->project->canceledDate = '取消日期'; -$lang->project->PO = '产品负责人'; -$lang->project->PM = '项目负责人'; -$lang->project->QD = '测试负责人'; -$lang->project->RD = '发布负责人'; -$lang->project->acl = '访问控制'; -$lang->project->teamname = '团队名称'; -$lang->project->order = '项目排序'; -$lang->project->products = '相关产品'; -$lang->project->childProjects = '子项目'; -$lang->project->whitelist = '分组白名单'; -$lang->project->totalEstimate = '总预计'; -$lang->project->totalConsumed = '总消耗'; -$lang->project->totalLeft = '总剩余'; -$lang->project->progess = '进度'; -$lang->project->viewBug = '查看bug'; -$lang->project->noProduct = '无产品项目'; -$lang->project->select = '--请选择项目--'; -$lang->project->createStory = "新增需求"; -$lang->project->all = '所有'; - -$lang->project->start = '开始'; -$lang->project->activate = '激活'; -$lang->project->delay = '延期'; -$lang->project->suspend = '挂起'; -$lang->project->close = '结束'; - -$lang->project->endList[14] = '两星期'; -$lang->project->endList[31] = '一个月'; -$lang->project->endList[62] = '两个月'; -$lang->project->endList[93] = '三个月'; -$lang->project->endList[186] = '半年'; -$lang->project->endList[365] = '一年'; - -$lang->team = new stdclass(); -$lang->team->account = '用户'; -$lang->team->role = '角色'; -$lang->team->join = '加盟日'; -$lang->team->hours = '可用工时/天'; -$lang->team->days = '可用工日'; -$lang->team->totalHours = '总计'; - -$lang->project->basicInfo = '基本信息'; -$lang->project->otherInfo = '其他信息'; - -/* 字段取值列表。*/ -$lang->project->statusList['wait'] = '未开始'; -$lang->project->statusList['doing'] = '进行中'; -$lang->project->statusList['suspended'] = '已挂起'; -$lang->project->statusList['done'] = '已完成'; - -$lang->project->aclList['open'] = '默认设置(有项目视图权限,即可访问)'; -$lang->project->aclList['private'] = '私有项目(只有项目团队成员才能访问)'; -$lang->project->aclList['custom'] = '自定义白名单(团队成员和白名单的成员可以访问)'; - -/* 方法列表。*/ -$lang->project->index = "项目首页"; -$lang->project->task = '任务列表'; -$lang->project->groupTask = '分组浏览任务'; -$lang->project->story = '需求列表'; -$lang->project->bug = 'Bug列表'; -$lang->project->dynamic = '动态'; -$lang->project->build = '版本列表'; -$lang->project->testtask = '测试申请'; -$lang->project->burn = '燃尽图'; -$lang->project->computeBurn = '更新燃尽图'; -$lang->project->burnData = '燃尽图数据'; -$lang->project->team = '团队成员'; -$lang->project->doc = '文档列表'; -$lang->project->manageProducts = '关联产品'; -$lang->project->linkStory = '关联需求'; -$lang->project->view = "基本信息"; -$lang->project->create = "添加项目"; -$lang->project->copy = "复制项目"; -$lang->project->delete = "删除项目"; -$lang->project->browse = "浏览项目"; -$lang->project->edit = "编辑项目"; -$lang->project->manageMembers = '团队管理'; -$lang->project->unlinkMember = '移除成员'; -$lang->project->unlinkStory = '移除需求'; -$lang->project->importTask = '转入任务'; -$lang->project->importBug = '导入Bug'; -$lang->project->ajaxGetProducts = '接口:获得项目产品列表'; - -/* 分组浏览。*/ -$lang->project->allTasks = '所有'; -$lang->project->assignedToMe = '指派给我'; - -$lang->project->statusSelects[''] = '更多'; -$lang->project->statusSelects['finishedbyme'] = '我完成'; -$lang->project->statusSelects['wait'] = '未开始'; -$lang->project->statusSelects['doing'] = '进行中'; -$lang->project->statusSelects['done'] = '已完成'; -$lang->project->statusSelects['closed'] = '已关闭'; -$lang->project->statusSelects['delayed'] = '已延期'; -$lang->project->statusSelects['needconfirm'] = '需求变动'; -$lang->project->groups[''] = '分组查看'; -$lang->project->groups['story'] = '需求分组'; -$lang->project->groups['status'] = '状态分组'; -$lang->project->groups['pri'] = '优先级分组'; -$lang->project->groups['openedby'] = '创建者分组'; -$lang->project->groups['assignedTo'] = '指派给分组'; -$lang->project->groups['finishedby'] = '完成者分组'; -$lang->project->groups['closedby'] = '关闭者分组'; -$lang->project->groups['estimate'] = '预计分组'; -$lang->project->groups['consumed'] = '已消耗分组'; -$lang->project->groups['left'] = '剩余分组'; -$lang->project->groups['type'] = '类型分组'; -$lang->project->groups['deadline'] = '截止分组'; - -$lang->project->moduleTask = '按模块'; -$lang->project->byQuery = '搜索'; - -/* 查询条件列表。*/ -$lang->project->allProject = '所有项目'; -$lang->project->aboveAllProduct = '以上所有产品'; -$lang->project->aboveAllProject = '以上所有项目'; - -/* 页面提示。*/ -$lang->project->selectProject = "请选择项目"; -$lang->project->beginAndEnd = '起止时间'; -$lang->project->lblStats = '工时统计'; -$lang->project->stats = '可用工时%s工时
          总共预计%s工时
          已经消耗%s工时
          预计剩余%s工时'; -$lang->project->oneLineStats = "项目%s, 代号为%s, 相关产品为%s%s开始,%s结束,总预计%s工时,已消耗%s工时,预计剩余%s工时。"; -$lang->project->taskSummary = "本页共 %s 个任务,未开始%s,进行中%s,总预计%s工时,已消耗%s工时,剩余%s工时。"; -$lang->project->memberHours = "%s共有 %s 个可用工时,"; -$lang->project->groupSummary = "本组共 %s 个任务,未开始%s,进行中%s,总预计%s工时,已消耗%s工时,剩余%s工时。"; -$lang->project->wbs = "分解任务"; -$lang->project->batchWBS = "批量分解"; -$lang->project->largeBurnChart = '点击查看大图'; -$lang->project->howToUpdateBurn = "如何更新?"; -$lang->project->whyNoStories = "看起来没有需求可以关联。请检查下项目关联的产品中有没有需求,而且要确保它们已经审核通过。"; -$lang->project->doneProjects = '已结束'; -$lang->project->unDoneProjects = '未结束'; -$lang->project->copyTeam = '复制团队'; - -/* 交互提示。*/ -$lang->project->confirmDelete = '您确定删除项目[%s]吗?'; -$lang->project->confirmUnlinkMember = '您确定从该项目中移除该用户吗?'; -$lang->project->confirmUnlinkStory = '您确定从该项目中移除该需求吗?'; -$lang->project->errorNoLinkedProducts = '该项目没有关联的产品,系统将转到产品关联页面'; -$lang->project->accessDenied = '您无权访问该项目!'; -$lang->project->tips = '提示'; -$lang->project->afterInfo = '项目添加成功,您现在可以进行以下操作:'; -$lang->project->setTeam = '设置团队'; -$lang->project->linkStory = '关联需求'; -$lang->project->createTask = '添加任务'; -$lang->project->goback = '返回项目首页(5秒后将自动跳转)'; - -/* 统计。*/ -$lang->project->charts = new stdclass(); -$lang->project->charts->burn = new stdclass(); -$lang->project->charts->burn->graph = new stdclass(); -$lang->project->charts->burn->graph->caption = "燃尽图"; -$lang->project->charts->burn->graph->xAxisName = "日期"; -$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; - -$lang->project->placeholder = new stdclass(); -$lang->project->placeholder->code = '团队内部的简称'; - -$lang->project->selectGroup = new stdclass(); -$lang->project->selectGroup->doing = '(进行中)'; -$lang->project->selectGroup->suspended = '(已挂起)'; -$lang->project->selectGroup->done = '(已结束)'; - -$lang->project->projectTasks = '按项目'; + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +/* 字段列表。*/ +$lang->project->common = '项目视图'; +$lang->project->id = '项目编号'; +$lang->project->company = '所属公司'; +$lang->project->fromproject = '所属项目'; +$lang->project->iscat = '作为目录'; +$lang->project->type = '项目类型'; +$lang->project->parent = '上级项目'; +$lang->project->name = '项目名称'; +$lang->project->code = '项目代号'; +$lang->project->begin = '开始日期'; +$lang->project->end = '结束日期'; +$lang->project->days = '可用工作日'; +$lang->project->day = '天'; +$lang->project->status = '项目状态'; +$lang->project->statge = '所处阶段'; +$lang->project->pri = '优先级'; +$lang->project->desc = '项目描述'; +$lang->project->goal = '项目目标'; +$lang->project->openedBy = '由谁创建'; +$lang->project->openedDate = '创建日期'; +$lang->project->closedBy = '由谁关闭'; +$lang->project->closedDate = '关闭日期'; +$lang->project->canceledBy = '由谁取消'; +$lang->project->canceledDate = '取消日期'; +$lang->project->PO = '产品负责人'; +$lang->project->PM = '项目负责人'; +$lang->project->QD = '测试负责人'; +$lang->project->RD = '发布负责人'; +$lang->project->acl = '访问控制'; +$lang->project->teamname = '团队名称'; +$lang->project->order = '项目排序'; +$lang->project->products = '相关产品'; +$lang->project->childProjects = '子项目'; +$lang->project->whitelist = '分组白名单'; +$lang->project->totalEstimate = '总预计'; +$lang->project->totalConsumed = '总消耗'; +$lang->project->totalLeft = '总剩余'; +$lang->project->progess = '进度'; +$lang->project->viewBug = '查看bug'; +$lang->project->noProduct = '无产品项目'; +$lang->project->select = '--请选择项目--'; +$lang->project->createStory = "新增需求"; +$lang->project->all = '所有'; + +$lang->project->start = '开始'; +$lang->project->activate = '激活'; +$lang->project->delay = '延期'; +$lang->project->suspend = '挂起'; +$lang->project->close = '结束'; + +$lang->project->endList[14] = '两星期'; +$lang->project->endList[31] = '一个月'; +$lang->project->endList[62] = '两个月'; +$lang->project->endList[93] = '三个月'; +$lang->project->endList[186] = '半年'; +$lang->project->endList[365] = '一年'; + +$lang->team = new stdclass(); +$lang->team->account = '用户'; +$lang->team->role = '角色'; +$lang->team->join = '加盟日'; +$lang->team->hours = '可用工时/天'; +$lang->team->days = '可用工日'; +$lang->team->totalHours = '总计'; + +$lang->project->basicInfo = '基本信息'; +$lang->project->otherInfo = '其他信息'; + +/* 字段取值列表。*/ +$lang->project->statusList['wait'] = '未开始'; +$lang->project->statusList['doing'] = '进行中'; +$lang->project->statusList['suspended'] = '已挂起'; +$lang->project->statusList['done'] = '已完成'; + +$lang->project->aclList['open'] = '默认设置(有项目视图权限,即可访问)'; +$lang->project->aclList['private'] = '私有项目(只有项目团队成员才能访问)'; +$lang->project->aclList['custom'] = '自定义白名单(团队成员和白名单的成员可以访问)'; + +/* 方法列表。*/ +$lang->project->index = "项目首页"; +$lang->project->task = '任务列表'; +$lang->project->groupTask = '分组浏览任务'; +$lang->project->story = '需求列表'; +$lang->project->bug = 'Bug列表'; +$lang->project->dynamic = '动态'; +$lang->project->build = '版本列表'; +$lang->project->testtask = '测试申请'; +$lang->project->burn = '燃尽图'; +$lang->project->computeBurn = '更新燃尽图'; +$lang->project->burnData = '燃尽图数据'; +$lang->project->team = '团队成员'; +$lang->project->doc = '文档列表'; +$lang->project->manageProducts = '关联产品'; +$lang->project->linkStory = '关联需求'; +$lang->project->view = "基本信息"; +$lang->project->create = "添加项目"; +$lang->project->copy = "复制项目"; +$lang->project->delete = "删除项目"; +$lang->project->browse = "浏览项目"; +$lang->project->edit = "编辑项目"; +$lang->project->manageMembers = '团队管理'; +$lang->project->unlinkMember = '移除成员'; +$lang->project->unlinkStory = '移除需求'; +$lang->project->importTask = '转入任务'; +$lang->project->importBug = '导入Bug'; +$lang->project->ajaxGetProducts = '接口:获得项目产品列表'; + +/* 分组浏览。*/ +$lang->project->allTasks = '所有'; +$lang->project->assignedToMe = '指派给我'; + +$lang->project->statusSelects[''] = '更多'; +$lang->project->statusSelects['finishedbyme'] = '我完成'; +$lang->project->statusSelects['wait'] = '未开始'; +$lang->project->statusSelects['doing'] = '进行中'; +$lang->project->statusSelects['done'] = '已完成'; +$lang->project->statusSelects['closed'] = '已关闭'; +$lang->project->statusSelects['delayed'] = '已延期'; +$lang->project->statusSelects['needconfirm'] = '需求变动'; +$lang->project->groups[''] = '分组查看'; +$lang->project->groups['story'] = '需求分组'; +$lang->project->groups['status'] = '状态分组'; +$lang->project->groups['pri'] = '优先级分组'; +$lang->project->groups['openedby'] = '创建者分组'; +$lang->project->groups['assignedTo'] = '指派给分组'; +$lang->project->groups['finishedby'] = '完成者分组'; +$lang->project->groups['closedby'] = '关闭者分组'; +$lang->project->groups['estimate'] = '预计分组'; +$lang->project->groups['consumed'] = '已消耗分组'; +$lang->project->groups['left'] = '剩余分组'; +$lang->project->groups['type'] = '类型分组'; +$lang->project->groups['deadline'] = '截止分组'; + +$lang->project->moduleTask = '按模块'; +$lang->project->byQuery = '搜索'; + +/* 查询条件列表。*/ +$lang->project->allProject = '所有项目'; +$lang->project->aboveAllProduct = '以上所有产品'; +$lang->project->aboveAllProject = '以上所有项目'; + +/* 页面提示。*/ +$lang->project->selectProject = "请选择项目"; +$lang->project->beginAndEnd = '起止时间'; +$lang->project->lblStats = '工时统计'; +$lang->project->stats = '可用工时%s工时
          总共预计%s工时
          已经消耗%s工时
          预计剩余%s工时'; +$lang->project->oneLineStats = "项目%s, 代号为%s, 相关产品为%s%s开始,%s结束,总预计%s工时,已消耗%s工时,预计剩余%s工时。"; +$lang->project->taskSummary = "本页共 %s 个任务,未开始%s,进行中%s,总预计%s工时,已消耗%s工时,剩余%s工时。"; +$lang->project->memberHours = "%s共有 %s 个可用工时,"; +$lang->project->groupSummary = "本组共 %s 个任务,未开始%s,进行中%s,总预计%s工时,已消耗%s工时,剩余%s工时。"; +$lang->project->wbs = "分解任务"; +$lang->project->batchWBS = "批量分解"; +$lang->project->largeBurnChart = '点击查看大图'; +$lang->project->howToUpdateBurn = "如何更新?"; +$lang->project->whyNoStories = "看起来没有需求可以关联。请检查下项目关联的产品中有没有需求,而且要确保它们已经审核通过。"; +$lang->project->doneProjects = '已结束'; +$lang->project->unDoneProjects = '未结束'; +$lang->project->copyTeam = '复制团队'; + +/* 交互提示。*/ +$lang->project->confirmDelete = '您确定删除项目[%s]吗?'; +$lang->project->confirmUnlinkMember = '您确定从该项目中移除该用户吗?'; +$lang->project->confirmUnlinkStory = '您确定从该项目中移除该需求吗?'; +$lang->project->errorNoLinkedProducts = '该项目没有关联的产品,系统将转到产品关联页面'; +$lang->project->accessDenied = '您无权访问该项目!'; +$lang->project->tips = '提示'; +$lang->project->afterInfo = '项目添加成功,您现在可以进行以下操作:'; +$lang->project->setTeam = '设置团队'; +$lang->project->linkStory = '关联需求'; +$lang->project->createTask = '添加任务'; +$lang->project->goback = '返回项目首页(5秒后将自动跳转)'; + +/* 统计。*/ +$lang->project->charts = new stdclass(); +$lang->project->charts->burn = new stdclass(); +$lang->project->charts->burn->graph = new stdclass(); +$lang->project->charts->burn->graph->caption = "燃尽图"; +$lang->project->charts->burn->graph->xAxisName = "日期"; +$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; + +$lang->project->placeholder = new stdclass(); +$lang->project->placeholder->code = '团队内部的简称'; + +$lang->project->selectGroup = new stdclass(); +$lang->project->selectGroup->doing = '(进行中)'; +$lang->project->selectGroup->suspended = '(已挂起)'; +$lang->project->selectGroup->done = '(已结束)'; + +$lang->project->projectTasks = '按项目'; diff --git a/module/project/lang/zh-tw.php b/module/project/lang/zh-tw.php index ccfdf0ffd1..6f790c907c 100644 --- a/module/project/lang/zh-tw.php +++ b/module/project/lang/zh-tw.php @@ -1,199 +1,199 @@ - - * @package project - * @version $Id: zh-tw.php 3835 2012-12-17 10:26:50Z wwccss $ - * @link http://www.zentao.net - */ -/* 欄位列表。*/ -$lang->project->common = '項目視圖'; -$lang->project->id = '項目編號'; -$lang->project->company = '所屬公司'; -$lang->project->fromproject = '所屬項目'; -$lang->project->iscat = '作為目錄'; -$lang->project->type = '項目類型'; -$lang->project->parent = '上級項目'; -$lang->project->name = '項目名稱'; -$lang->project->code = '項目代號'; -$lang->project->begin = '開始日期'; -$lang->project->end = '結束日期'; -$lang->project->days = '可用工作日'; -$lang->project->day = '天'; -$lang->project->status = '項目狀態'; -$lang->project->statge = '所處階段'; -$lang->project->pri = '優先順序'; -$lang->project->desc = '項目描述'; -$lang->project->goal = '項目目標'; -$lang->project->openedBy = '由誰創建'; -$lang->project->openedDate = '創建日期'; -$lang->project->closedBy = '由誰關閉'; -$lang->project->closedDate = '關閉日期'; -$lang->project->canceledBy = '由誰取消'; -$lang->project->canceledDate = '取消日期'; -$lang->project->PO = '產品負責人'; -$lang->project->PM = '項目負責人'; -$lang->project->QD = '測試負責人'; -$lang->project->RD = '發佈負責人'; -$lang->project->acl = '訪問控制'; -$lang->project->teamname = '團隊名稱'; -$lang->project->order = '項目排序'; -$lang->project->products = '相關產品'; -$lang->project->childProjects = '子項目'; -$lang->project->whitelist = '分組白名單'; -$lang->project->totalEstimate = '總預計'; -$lang->project->totalConsumed = '總消耗'; -$lang->project->totalLeft = '總剩餘'; -$lang->project->progess = '進度'; -$lang->project->viewBug = '查看bug'; -$lang->project->createTesttask= '提交測試'; -$lang->project->noProduct = '無產品項目'; -$lang->project->select = '--請選擇項目--'; -$lang->project->createStory = "新增需求"; - -$lang->project->endList[14] = '兩星期'; -$lang->project->endList[31] = '一個月'; -$lang->project->endList[62] = '兩個月'; -$lang->project->endList[93] = '三個月'; -$lang->project->endList[186] = '半年'; -$lang->project->endList[365] = '一年'; - -$lang->team = new stdclass(); -$lang->team->account = '用戶'; -$lang->team->role = '角色'; -$lang->team->join = '加盟日'; -$lang->team->hours = '可用工時/天'; -$lang->team->days = '可用工日'; -$lang->team->totalHours = '總計'; - -$lang->project->basicInfo = '基本信息'; -$lang->project->otherInfo = '其他信息'; - -/* 欄位取值列表。*/ -$lang->project->statusList[''] = ''; -$lang->project->statusList['wait'] = '未開始'; -$lang->project->statusList['doing'] = '進行中'; -$lang->project->statusList['done'] = '已完成'; - -$lang->project->aclList['open'] = '預設設置(有項目視圖權限,即可訪問)'; -$lang->project->aclList['private'] = '私有項目(只有項目團隊成員才能訪問)'; -$lang->project->aclList['custom'] = '自定義白名單(團隊成員和白名單的成員可以訪問)'; - -/* 方法列表。*/ -$lang->project->index = "項目首頁"; -$lang->project->task = '任務列表'; -$lang->project->groupTask = '分組瀏覽任務'; -$lang->project->story = '需求列表'; -$lang->project->bug = 'Bug列表'; -$lang->project->dynamic = '動態'; -$lang->project->build = '版本列表'; -$lang->project->testtask = '測試申請'; -$lang->project->burn = '燃盡圖'; -$lang->project->computeBurn = '更新燃盡圖'; -$lang->project->burnData = '燃盡圖數據'; -$lang->project->team = '團隊成員'; -$lang->project->doc = '文檔列表'; -$lang->project->manageProducts = '關聯產品'; -$lang->project->linkStory = '關聯需求'; -$lang->project->view = "基本信息"; -$lang->project->create = "添加項目"; -$lang->project->copy = "複製項目"; -$lang->project->delete = "刪除項目"; -$lang->project->browse = "瀏覽項目"; -$lang->project->edit = "編輯項目"; -$lang->project->manageMembers = '團隊管理'; -$lang->project->unlinkMember = '移除成員'; -$lang->project->unlinkStory = '移除需求'; -$lang->project->importTask = '轉入任務'; -$lang->project->importBug = '導入Bug'; -$lang->project->ajaxGetProducts = '介面:獲得項目產品列表'; - -/* 分組瀏覽。*/ -$lang->project->allTasks = '所有'; -$lang->project->assignedToMe = '指派給我'; - -$lang->project->statusSelects[''] = '更多'; -$lang->project->statusSelects['finishedbyme'] = '我完成'; -$lang->project->statusSelects['wait'] = '未開始'; -$lang->project->statusSelects['doing'] = '進行中'; -$lang->project->statusSelects['done'] = '已完成'; -$lang->project->statusSelects['closed'] = '已關閉'; -$lang->project->statusSelects['delayed'] = '已延期'; -$lang->project->statusSelects['needconfirm'] = '需求變動'; -$lang->project->groups[''] = '分組查看'; -$lang->project->groups['story'] = '需求分組'; -$lang->project->groups['status'] = '狀態分組'; -$lang->project->groups['pri'] = '優先順序分組'; -$lang->project->groups['openedby'] = '創建者分組'; -$lang->project->groups['assignedTo'] = '指派給分組'; -$lang->project->groups['finishedby'] = '完成者分組'; -$lang->project->groups['closedby'] = '關閉者分組'; -$lang->project->groups['estimate'] = '預計分組'; -$lang->project->groups['consumed'] = '已消耗分組'; -$lang->project->groups['left'] = '剩餘分組'; -$lang->project->groups['type'] = '類型分組'; -$lang->project->groups['deadline'] = '截止分組'; - -$lang->project->moduleTask = '按模組'; -$lang->project->byQuery = '搜索'; - -/* 查詢條件列表。*/ -$lang->project->allProject = '所有項目'; -$lang->project->aboveAllProduct = '以上所有產品'; -$lang->project->aboveAllProject = '以上所有項目'; - -/* 頁面提示。*/ -$lang->project->selectProject = "請選擇項目"; -$lang->project->beginAndEnd = '起止時間'; -$lang->project->lblStats = '工時統計'; -$lang->project->stats = '可用工時%s工時
          總共預計%s工時
          已經消耗%s工時
          預計剩餘%s工時'; -$lang->project->oneLineStats = "項目%s, 代號為%s, 相關產品為%s%s開始,%s結束,總預計%s工時,已消耗%s工時,預計剩餘%s工時。"; -$lang->project->taskSummary = "本頁共 %s 個任務,未開始%s,進行中%s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; -$lang->project->memberHours = "%s共有 %s 個可用工時,"; -$lang->project->groupSummary = "本組共 %s 個任務,未開始%s,進行中%s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; -$lang->project->wbs = "分解任務"; -$lang->project->batchWBS = "批量分解"; -$lang->project->largeBurnChart = '點擊查看大圖'; -$lang->project->howToUpdateBurn = "如何更新?"; -$lang->project->whyNoStories = "看起來沒有需求可以關聯。請檢查下項目關聯的產品中有沒有需求,而且要確保它們已經審核通過。"; -$lang->project->doneProjects = '已結束'; -$lang->project->unDoneProjects = '未結束'; -$lang->project->copyTeam = '複製團隊'; - -/* 交互提示。*/ -$lang->project->confirmDelete = '您確定刪除項目[%s]嗎?'; -$lang->project->confirmUnlinkMember = '您確定從該項目中移除該用戶嗎?'; -$lang->project->confirmUnlinkStory = '您確定從該項目中移除該需求嗎?'; -$lang->project->errorNoLinkedProducts = '該項目沒有關聯的產品,系統將轉到產品關聯頁面'; -$lang->project->accessDenied = '您無權訪問該項目!'; -$lang->project->tips = '提示'; -$lang->project->afterInfo = '項目添加成功,您現在可以進行以下操作:'; -$lang->project->setTeam = '設置團隊'; -$lang->project->linkStory = '關聯需求'; -$lang->project->createTask = '添加任務'; -$lang->project->goback = '返回項目首頁(5秒後將自動跳轉)'; - -/* 統計。*/ -$lang->project->charts = new stdclass(); -$lang->project->charts->burn = new stdclass(); -$lang->project->charts->burn->graph = new stdclass(); -$lang->project->charts->burn->graph->caption = "燃盡圖"; -$lang->project->charts->burn->graph->xAxisName = "日期"; -$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; - -$lang->project->placeholder = new stdclass(); -$lang->project->placeholder->code = '團隊內部的簡稱'; - -$lang->project->selectGroup = new stdclass(); -$lang->project->selectGroup->doing = '(進行中)'; -$lang->project->selectGroup->done = '(已結束)'; - -$lang->project->projectTasks = '按項目'; + + * @package project + * @version $Id: zh-tw.php 3835 2012-12-17 10:26:50Z wwccss $ + * @link http://www.zentao.net + */ +/* 欄位列表。*/ +$lang->project->common = '項目視圖'; +$lang->project->id = '項目編號'; +$lang->project->company = '所屬公司'; +$lang->project->fromproject = '所屬項目'; +$lang->project->iscat = '作為目錄'; +$lang->project->type = '項目類型'; +$lang->project->parent = '上級項目'; +$lang->project->name = '項目名稱'; +$lang->project->code = '項目代號'; +$lang->project->begin = '開始日期'; +$lang->project->end = '結束日期'; +$lang->project->days = '可用工作日'; +$lang->project->day = '天'; +$lang->project->status = '項目狀態'; +$lang->project->statge = '所處階段'; +$lang->project->pri = '優先順序'; +$lang->project->desc = '項目描述'; +$lang->project->goal = '項目目標'; +$lang->project->openedBy = '由誰創建'; +$lang->project->openedDate = '創建日期'; +$lang->project->closedBy = '由誰關閉'; +$lang->project->closedDate = '關閉日期'; +$lang->project->canceledBy = '由誰取消'; +$lang->project->canceledDate = '取消日期'; +$lang->project->PO = '產品負責人'; +$lang->project->PM = '項目負責人'; +$lang->project->QD = '測試負責人'; +$lang->project->RD = '發佈負責人'; +$lang->project->acl = '訪問控制'; +$lang->project->teamname = '團隊名稱'; +$lang->project->order = '項目排序'; +$lang->project->products = '相關產品'; +$lang->project->childProjects = '子項目'; +$lang->project->whitelist = '分組白名單'; +$lang->project->totalEstimate = '總預計'; +$lang->project->totalConsumed = '總消耗'; +$lang->project->totalLeft = '總剩餘'; +$lang->project->progess = '進度'; +$lang->project->viewBug = '查看bug'; +$lang->project->createTesttask= '提交測試'; +$lang->project->noProduct = '無產品項目'; +$lang->project->select = '--請選擇項目--'; +$lang->project->createStory = "新增需求"; + +$lang->project->endList[14] = '兩星期'; +$lang->project->endList[31] = '一個月'; +$lang->project->endList[62] = '兩個月'; +$lang->project->endList[93] = '三個月'; +$lang->project->endList[186] = '半年'; +$lang->project->endList[365] = '一年'; + +$lang->team = new stdclass(); +$lang->team->account = '用戶'; +$lang->team->role = '角色'; +$lang->team->join = '加盟日'; +$lang->team->hours = '可用工時/天'; +$lang->team->days = '可用工日'; +$lang->team->totalHours = '總計'; + +$lang->project->basicInfo = '基本信息'; +$lang->project->otherInfo = '其他信息'; + +/* 欄位取值列表。*/ +$lang->project->statusList[''] = ''; +$lang->project->statusList['wait'] = '未開始'; +$lang->project->statusList['doing'] = '進行中'; +$lang->project->statusList['done'] = '已完成'; + +$lang->project->aclList['open'] = '預設設置(有項目視圖權限,即可訪問)'; +$lang->project->aclList['private'] = '私有項目(只有項目團隊成員才能訪問)'; +$lang->project->aclList['custom'] = '自定義白名單(團隊成員和白名單的成員可以訪問)'; + +/* 方法列表。*/ +$lang->project->index = "項目首頁"; +$lang->project->task = '任務列表'; +$lang->project->groupTask = '分組瀏覽任務'; +$lang->project->story = '需求列表'; +$lang->project->bug = 'Bug列表'; +$lang->project->dynamic = '動態'; +$lang->project->build = '版本列表'; +$lang->project->testtask = '測試申請'; +$lang->project->burn = '燃盡圖'; +$lang->project->computeBurn = '更新燃盡圖'; +$lang->project->burnData = '燃盡圖數據'; +$lang->project->team = '團隊成員'; +$lang->project->doc = '文檔列表'; +$lang->project->manageProducts = '關聯產品'; +$lang->project->linkStory = '關聯需求'; +$lang->project->view = "基本信息"; +$lang->project->create = "添加項目"; +$lang->project->copy = "複製項目"; +$lang->project->delete = "刪除項目"; +$lang->project->browse = "瀏覽項目"; +$lang->project->edit = "編輯項目"; +$lang->project->manageMembers = '團隊管理'; +$lang->project->unlinkMember = '移除成員'; +$lang->project->unlinkStory = '移除需求'; +$lang->project->importTask = '轉入任務'; +$lang->project->importBug = '導入Bug'; +$lang->project->ajaxGetProducts = '介面:獲得項目產品列表'; + +/* 分組瀏覽。*/ +$lang->project->allTasks = '所有'; +$lang->project->assignedToMe = '指派給我'; + +$lang->project->statusSelects[''] = '更多'; +$lang->project->statusSelects['finishedbyme'] = '我完成'; +$lang->project->statusSelects['wait'] = '未開始'; +$lang->project->statusSelects['doing'] = '進行中'; +$lang->project->statusSelects['done'] = '已完成'; +$lang->project->statusSelects['closed'] = '已關閉'; +$lang->project->statusSelects['delayed'] = '已延期'; +$lang->project->statusSelects['needconfirm'] = '需求變動'; +$lang->project->groups[''] = '分組查看'; +$lang->project->groups['story'] = '需求分組'; +$lang->project->groups['status'] = '狀態分組'; +$lang->project->groups['pri'] = '優先順序分組'; +$lang->project->groups['openedby'] = '創建者分組'; +$lang->project->groups['assignedTo'] = '指派給分組'; +$lang->project->groups['finishedby'] = '完成者分組'; +$lang->project->groups['closedby'] = '關閉者分組'; +$lang->project->groups['estimate'] = '預計分組'; +$lang->project->groups['consumed'] = '已消耗分組'; +$lang->project->groups['left'] = '剩餘分組'; +$lang->project->groups['type'] = '類型分組'; +$lang->project->groups['deadline'] = '截止分組'; + +$lang->project->moduleTask = '按模組'; +$lang->project->byQuery = '搜索'; + +/* 查詢條件列表。*/ +$lang->project->allProject = '所有項目'; +$lang->project->aboveAllProduct = '以上所有產品'; +$lang->project->aboveAllProject = '以上所有項目'; + +/* 頁面提示。*/ +$lang->project->selectProject = "請選擇項目"; +$lang->project->beginAndEnd = '起止時間'; +$lang->project->lblStats = '工時統計'; +$lang->project->stats = '可用工時%s工時
          總共預計%s工時
          已經消耗%s工時
          預計剩餘%s工時'; +$lang->project->oneLineStats = "項目%s, 代號為%s, 相關產品為%s%s開始,%s結束,總預計%s工時,已消耗%s工時,預計剩餘%s工時。"; +$lang->project->taskSummary = "本頁共 %s 個任務,未開始%s,進行中%s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; +$lang->project->memberHours = "%s共有 %s 個可用工時,"; +$lang->project->groupSummary = "本組共 %s 個任務,未開始%s,進行中%s,總預計%s工時,已消耗%s工時,剩餘%s工時。"; +$lang->project->wbs = "分解任務"; +$lang->project->batchWBS = "批量分解"; +$lang->project->largeBurnChart = '點擊查看大圖'; +$lang->project->howToUpdateBurn = "如何更新?"; +$lang->project->whyNoStories = "看起來沒有需求可以關聯。請檢查下項目關聯的產品中有沒有需求,而且要確保它們已經審核通過。"; +$lang->project->doneProjects = '已結束'; +$lang->project->unDoneProjects = '未結束'; +$lang->project->copyTeam = '複製團隊'; + +/* 交互提示。*/ +$lang->project->confirmDelete = '您確定刪除項目[%s]嗎?'; +$lang->project->confirmUnlinkMember = '您確定從該項目中移除該用戶嗎?'; +$lang->project->confirmUnlinkStory = '您確定從該項目中移除該需求嗎?'; +$lang->project->errorNoLinkedProducts = '該項目沒有關聯的產品,系統將轉到產品關聯頁面'; +$lang->project->accessDenied = '您無權訪問該項目!'; +$lang->project->tips = '提示'; +$lang->project->afterInfo = '項目添加成功,您現在可以進行以下操作:'; +$lang->project->setTeam = '設置團隊'; +$lang->project->linkStory = '關聯需求'; +$lang->project->createTask = '添加任務'; +$lang->project->goback = '返回項目首頁(5秒後將自動跳轉)'; + +/* 統計。*/ +$lang->project->charts = new stdclass(); +$lang->project->charts->burn = new stdclass(); +$lang->project->charts->burn->graph = new stdclass(); +$lang->project->charts->burn->graph->caption = "燃盡圖"; +$lang->project->charts->burn->graph->xAxisName = "日期"; +$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; + +$lang->project->placeholder = new stdclass(); +$lang->project->placeholder->code = '團隊內部的簡稱'; + +$lang->project->selectGroup = new stdclass(); +$lang->project->selectGroup->doing = '(進行中)'; +$lang->project->selectGroup->done = '(已結束)'; + +$lang->project->projectTasks = '按項目'; diff --git a/module/project/model.php b/module/project/model.php index dc7ec863f0..eff5a99683 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1,1400 +1,1400 @@ - - * @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 all teams of all projects and group by projects, save it as static. */ - static $teams; - if(empty($teams)) $teams = $this->dao->select('project, account')->from(TABLE_TEAM)->fetchGroup('project', 'account'); - $currentTeam = isset($teams[$project->id]) ? $teams[$project->id] : array(); - - /* If project is private, only members can access. */ - if($project->acl == 'private') - { - return isset($currentTeam[$this->app->user->account]); - } - - /* Project's acl is custom, check the groups. */ - if($project->acl == 'custom') - { - if(isset($currentTeam[$this->app->user->account])) return true; - $userGroups = $this->app->user->groups; - $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 - * @param string $extra - * @access public - * @return void - */ - public function setMenu($projects, $projectID, $extra = '') - { - /* Check the privilege. */ - $project = $this->getById($projectID); - if($projects and !isset($projects[$projectID]) and !$this->checkPriv($project)) - { - echo(js::alert($this->lang->project->accessDenied)); - die(js::locate('back')); - } - - $moduleName = $this->app->getModuleName(); - $methodName = $this->app->getMethodName(); - - if($this->cookie->projectMode == 'noclosed' and $project->status == 'done') - { - setcookie('projectMode', 'all'); - $this->cookie->projectMode = 'all'; - } - - $selectHtml = $this->select($projects, $projectID, $moduleName, $methodName, $extra); - foreach($this->lang->project->menu as $key => $menu) - { - $replace = $key == 'list' ? $selectHtml : $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 - * @param string $extra - * @access public - * @return string - */ - public function select($projects, $projectID, $currentModule, $currentMethod, $extra = '') - { - $projectMode = $this->cookie->projectMode ? $this->cookie->projectMode : 'all'; - $products = $this->loadModel('product')->getPairs('nocode'); - $productGroup = $this->getProductGroupList(); - $selectGroup = array(); - foreach($productGroup as $projects) - { - foreach($projects as $project) - { - if($projectMode == 'noclosed' and ($project->status == 'done' or $project->status == 'suspended')) continue; - - if($project->product) - { - $product = isset($products[$project->product]) ? $products[$project->product] : ''; - $selectGroup[$product][$project->id] = $project->name; - } - else - { - $selectGroup[$this->lang->project->noProduct][$project->id] = $project->name; - } - } - } - - /* See product's model method:select. */ - $switchCode = "switchProject($('#projectID').val(), '$currentModule', '$currentMethod', '$extra');"; - $onchange = "onchange=\"$switchCode\""; - $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; - $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; - $selectHtml = html::selectGroup('projectID', $selectGroup, $projectID, "tabindex=2 $onchange $onkeypress"); - return $selectHtml; - } - - /** - * Get project tree menu. - * - * @access public - * @return void - */ - public function tree() - { - $products = $this->loadModel('product')->getPairs('nocode'); - $productGroup = $this->getProductGroupList(); - $projectTree = "
            "; - foreach($productGroup as $productID => $projects) - { - if(!isset($products[$productID]) and $productID != '') continue; - $productName = isset($products[$productID]) ? $products[$productID] : $this->lang->project->noProduct; - $projectTree .= "
          • $productName
              "; - - foreach($projects as $project) - { - if($project->status != 'done') - { - $projectTree .= "
            • " . html::a(inlink('task', "projectID=$project->id"), $project->name, '', "id='project$project->id'") . "
            • "; - } - } - - - $hasDone = false; - foreach($projects as $project) - { - if($project->status == 'done') - { - $hasDone = true; - break; - } - } - if($hasDone) - { - $projectTree .= "
            • {$this->lang->project->selectGroup->done}
                "; - foreach($projects as $project) - { - if($project->status == 'done') - { - $projectTree .= "
              • " . html::a(inlink('task', "projectID=$project->id"), $project->name, '', "id='project$project->id'") . "
              • "; - } - } - $projectTree .= "
            • "; - } - - $projectTree .= "
          • "; - } - - $projectTree .= "
          "; - - return $projectTree; - } - - /** - * 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; - } - - /** - * Save order - * - * @access public - * @return void - */ - public function saveOrder() - { - foreach($_POST as $projectID => $order) - { - $this->dao->update(TABLE_PROJECT)->set('`order`')->eq($order)->where('id')->eq($projectID)->exec(); - } - } - - /** - * Create a project. - * - * @access public - * @return void - */ - public function create($copyProjectID = '') - { - $this->lang->project->team = $this->lang->project->teamname; - $project = fixer::input('post') - ->setDefault('status', 'wait') - ->stripTags('name, code, team') - ->setIF($this->post->acl != 'custom', 'whitelist', '') - ->join('whitelist', ',') - ->remove('products, workDays, delta') - ->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(); - $today = helper::today(); - $creatorExists = false; - - /* Copy team of project. */ - if($copyProjectID != '') - { - $members = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($copyProjectID)->fetchAll(); - foreach($members as $member) - { - $member->project = $projectID; - $member->join = $today; - $this->dao->insert(TABLE_TEAM)->data($member)->exec(); - if($member->account == $this->app->user->account) $creatorExists = true; - } - } - - /* Add the creator to team. */ - if($copyProjectID == '' or !$creatorExists) - { - $member->project = $projectID; - $member->account = $this->app->user->account; - $member->join = $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 == 'QD' or $fieldName == 'RD' ) - { - if(!empty($value) and !isset($team[$value])) - { - $member->project = (int)$projectID; - $member->account = $value; - $member->join = helper::today(); - $member->role = $this->lang->project->$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); - } - - /** - * Start project. - * - * @param int $projectID - * @access public - * @return void - */ - public function start($projectID) - { - $oldProject = $this->getById($projectID); - $now = helper::now(); - $project = fixer::input('post') - ->setDefault('status', 'doing') - ->remove('comment')->get(); - - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck() - ->where('id')->eq((int)$projectID) - ->exec(); - - if(!dao::isError()) return common::createChanges($oldProject, $project); - } - - /** - * Delay project. - * - * @param int $projectID - * @access public - * @return void - */ - public function delay($projectID) - { - $oldProject = $this->getById($projectID); - $now = helper::now(); - $project = fixer::input('post')->remove('comment')->get(); - - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck() - ->where('id')->eq((int)$projectID) - ->exec(); - - if(!dao::isError()) return common::createChanges($oldProject, $project); - } - - /** - * Suspend project. - * - * @param int $projectID - * @access public - * @return void - */ - public function suspend($projectID) - { - $oldProject = $this->getById($projectID); - $now = helper::now(); - $project = fixer::input('post') - ->setDefault('status', 'suspended') - ->remove('comment')->get(); - - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck() - ->where('id')->eq((int)$projectID) - ->exec(); - - if(!dao::isError()) return common::createChanges($oldProject, $project); - } - - /** - * Activate project. - * - * @param int $projectID - * @access public - * @return void - */ - public function activate($projectID) - { - $oldProject = $this->getById($projectID); - $now = helper::now(); - $project = fixer::input('post') - ->setDefault('status', 'doing') - ->remove('comment')->get(); - - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck() - ->where('id')->eq((int)$projectID) - ->exec(); - - if(!dao::isError()) return common::createChanges($oldProject, $project); - } - - /** - * Close project. - * - * @param int $projectID - * @access public - * @return void - */ - public function close($projectID) - { - $oldProject = $this->getById($projectID); - $now = helper::now(); - $project = fixer::input('post') - ->setDefault('status', 'done') - ->remove('comment')->get(); - - $this->dao->update(TABLE_PROJECT)->data($project) - ->autoCheck() - ->where('id')->eq((int)$projectID) - ->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 : 'isDone, `order`, status'; - $mode .= $this->cookie->projectMode; - /* Order by status's content whether or not done */ - $projects = $this->dao->select('*, IF(INSTR(" done", status) < 2, 0, 1) AS isDone')->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 - * @param int $productID - * @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('`order`, status') - ->beginIF($limit)->limit($limit)->fi() - ->fetchAll('id'); - } - else - { - return $this->dao->select('*, IF(INSTR(" done", status) < 2, 0, 1) AS isDone')->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($this->config->project->orderBy) - ->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,t1.status, t2.product')->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project') - ->where('t1.deleted')->eq(0) - ->orderBy('t1.order') - ->fetchGroup('product'); - - $projects = $this->getList(); - - foreach($list as $id => $product) - { - foreach($product as $ID => $project) - { - if(!$this->checkPriv($projects[$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, $itemCounts = 30) - { - /* Init vars. */ - $projects = $this->getList($status, 0, $productID); - $projectKeys = array_keys($projects); - $stats = array(); - $hours = array(); - $emptyHour = array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0); - - /* Get all tasks and compute totalEstimate, totalConsumed, totalLeft, progress according to them. */ - $tasks = $this->dao->select('id, project, estimate, consumed, `left`, status, closedReason') - ->from(TABLE_TASK) - ->where('project')->in($projectKeys) - ->andWhere('deleted')->eq(0) - ->fetchGroup('project', 'id'); - - /* Compute totalEstimate, totalConsumed, totalLeft. */ - foreach($tasks as $projectID => $projectTasks) - { - $hour = (object)$emptyHour; - foreach($projectTasks as $task) - { - $hour->totalEstimate += $task->estimate; - $hour->totalConsumed += $task->consumed; - $hour->totalLeft += ($task->status != 'cancel' and $task->closedReason != 'cancel') ? $task->left : 0; - } - $hours[$projectID] = $hour; - } - - /* Compute totalReal and progress. */ - 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 burndown charts datas. */ - $burns = $this->dao->select('project, date AS name, `left` AS value') - ->from(TABLE_BURN) - ->where('project')->in($projectKeys) - ->orderBy('date desc') - ->fetchGroup('project', 'name'); - - foreach($burns as $projectID => $projectBurns) - { - /* If projectBurns > $itemCounts, split it, else call processBurnData() to pad burns. */ - $begin = $projects[$projectID]->begin; - $end = $projects[$projectID]->end; - if(count($projectBurns) >= $itemCounts) $projectBurns = array_slice($projectBurns, 0, $itemCounts); - if(count($projectBurns) < $itemCounts) $projectBurns = $this->processBurnData($projectBurns, $itemCounts, $begin, $end); - - /* Shorter names. */ - foreach($projectBurns as $projectBurn) - { - $projectBurn->name = substr($projectBurn->name, 5); - unset($projectBurn->project); - } - - ksort($projectBurns); - $burns[$projectID] = $projectBurns; - } - - /* Process projects. */ - foreach($projects as $key => $project) - { - if(!$this->checkPriv($project)) - { - unset($projects[$key]); - continue; - } - - // Process the end time. - $project->end = date(DT_DATE4, strtotime($project->end)); - - /* Process the burns. */ - $project->burns = array(); - $burnData = isset($burns[$project->id]) ? $burns[$project->id] : array(); - foreach($burnData as $data) $project->burns[] = $data->value; - - /* Process the hours. */ - $project->hours = isset($hours[$project->id]) ? $hours[$project->id] : (object)$emptyHour; - - $stats[] = $project; - } - - return $stats; - } - - /** - * Get project by id. - * - * @param int $projectID - * @param bool $setImgSize - * @access public - * @return void - */ - public function getById($projectID, $setImgSize = false) - { - $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); - - if($setImgSize) $project->desc = $this->loadModel('file')->setImgSize($project->desc); - if($setImgSize) $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,QD,RD')->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->QD = ''; - $managers->RD = ''; - 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(); - } - - /** - * Get projects to import - * - * @access public - * @return void - */ - public function getProjectsToImport() - { - $projects = $this->dao->select('distinct t1.*')->from(TABLE_PROJECT)->alias('t1') - ->leftJoin(TABLE_TASK)->alias('t2')->on('t1.id=t2.project') - ->where('t2.status')->notIN('done,closed') - ->orderBy('id desc') - ->fetchAll('id'); - - $pairs = array(); - $now = date('Y-m-d'); - foreach($projects as $id => $project) - { - if($this->checkPriv($project) and ($project->status == 'done' or $project->end < $now)) $pairs[$id] = ucfirst(substr($project->code, 0, 1)) . ':' . $project->name; - } - return $pairs; - } - - /** - * 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'); - // $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->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($fromProject) - { - $this->loadModel('task'); - $tasks = array(); - $projectTasks = $this->task->getProjectTasks($fromProject, 'wait,doing,cancel'); - $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 = new stdclass(); - $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; - } - - /** - * Get teams which can be imported. - * - * @param string $account - * @param int $currentProject - * @access public - * @return array - */ - public function getTeams2Import($account, $currentProject) - { - return $this->dao->select('t1.project, t2.name as projectName') - ->from(TABLE_TEAM)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.account')->eq($account) - ->andWhere('t1.project')->ne($currentProject) - ->groupBy('t1.project') - ->orderBy('t1.project DESC') - ->fetchPairs(); - } - - /** - * Get members of a project who can be imported. - * - * @param int $project - * @param array $currentMembers - * @access public - * @return array - */ - public function getMembers2Import($project, $currentMembers) - { - return $this->dao->select('account, role, hours') - ->from(TABLE_TEAM) - ->where('project')->eq($project) - ->andWhere('account')->notIN($currentMembers) - ->fetchAll('account'); - } - - /** - * 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 = new stdclass(); - $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'") - ->andWhere('status')->notin('done,suspended') - ->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 - * @param string $mode noempty: skip the dates without burn down data. - * @access public - * @return array - */ - public function getBurnData($projectID = 0, $itemCounts = 30, $mode = 'noempty') - { - /* 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'); - $this->processBurnData($sets, $itemCounts, $project->begin, $project->end, $mode); - } - - foreach($sets as $set) $set->name = substr($set->name, 5); - return $sets; - } - - /** - * Get burn data for flot - * - * @param int $projectID - * @param int $itemCounts - * @access public - * @return void - */ - public function getBurnDataFlot($projectID = 0, $itemCounts = 30) - { - /* Get project and burn counts. */ - $project = $this->getById($projectID); - - /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ - $sets = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID)->orderBy('date DESC')->fetchAll('name'); - - $count = 0; - $burnData = array(); - foreach($sets as $date => $set) - { - if($count > $itemCounts) break; - if($date > $project->end) continue; - - $set->name = $this->getMicTime($set->name); - $burnData[$date] = $set; - $count++; - } - $burnData = array_reverse($burnData); - - return $burnData; - } - - /** - * Get microsecond from date. - * - * @param string|int $date - * @access public - * @return void - */ - public function getMicTime($date) - { - if(is_numeric($date)) return (string)$date . '000'; - return (string)strtotime("$date UTC") . '000'; - } - - /** - * Process burndown datas when the sets is smaller than the itemCounts. - * - * @param array $sets - * @param int $itemCounts - * @param date $begin - * @param date $end - * @param string $mode - * @access public - * @return array - */ - public function processBurnData($sets, $itemCounts, $begin, $end, $mode = 'noempty') - { - $burnCounts = count($sets); - $current = helper::today(); - - if($end != '0000-00-00') - { - $period = helper::diffDate($end, $begin) + 1; - $counts = $period > $itemCounts ? $itemCounts : $period; - } - else - { - $counts = $itemCounts; - } - - for($i = 0; $i < $counts - $burnCounts; $i ++) - { - if(helper::diffDate($current, $end) > 0) break; - if(!isset($sets[$current]) and $mode != 'noempty') - { - $sets[$current]->name = $current; - $sets[$current]->value = ''; - } - $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); - $current = $nextDay; - } - 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(); - $this->loadModel('task')->processTasks($tasks); - 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 the summary of project. - * - * @param array $tasks - * @access public - * @return string - */ - public function summary($tasks) - { - $taskSum = $statusWait = $statusDone = $statusDoing = $statusClosed = $statusCancel = 0; - $totalEstimate = $totalConsumed = $totalLeft = 0.0; - foreach($tasks as $task) - { - $totalEstimate += $task->estimate; - $totalConsumed += $task->consumed; - $totalLeft += (($task->status == 'cancel' or $task->closedReason == 'cancel') ? 0 : $task->left); - $statusVar = 'status' . ucfirst($task->status); - $$statusVar ++; - } - - return sprintf($this->lang->project->taskSummary, count($tasks), $statusWait, $statusDoing, $totalEstimate, $totalConsumed, $totalLeft); - } - - /** - * Judge an action is clickable or not. - * - * @param object $project - * @param string $action - * @access public - * @return bool - */ - public function isClickable($project, $action) - { - $action = strtolower($action); - - if($action == 'start') return $project->status == 'wait'; - if($action == 'close') return $project->status != 'done'; - if($action == 'suspend') return $project->status == 'wait' or $project->status == 'doing'; - if($action == 'delay') return $project->status == 'wait' or $project->status == 'doing'; - if($action == 'activate') return $project->status == 'suspended' or $project->status == 'done'; - - return true; - } -} + + * @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 all teams of all projects and group by projects, save it as static. */ + static $teams; + if(empty($teams)) $teams = $this->dao->select('project, account')->from(TABLE_TEAM)->fetchGroup('project', 'account'); + $currentTeam = isset($teams[$project->id]) ? $teams[$project->id] : array(); + + /* If project is private, only members can access. */ + if($project->acl == 'private') + { + return isset($currentTeam[$this->app->user->account]); + } + + /* Project's acl is custom, check the groups. */ + if($project->acl == 'custom') + { + if(isset($currentTeam[$this->app->user->account])) return true; + $userGroups = $this->app->user->groups; + $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 + * @param string $extra + * @access public + * @return void + */ + public function setMenu($projects, $projectID, $extra = '') + { + /* Check the privilege. */ + $project = $this->getById($projectID); + if($projects and !isset($projects[$projectID]) and !$this->checkPriv($project)) + { + echo(js::alert($this->lang->project->accessDenied)); + die(js::locate('back')); + } + + $moduleName = $this->app->getModuleName(); + $methodName = $this->app->getMethodName(); + + if($this->cookie->projectMode == 'noclosed' and $project->status == 'done') + { + setcookie('projectMode', 'all'); + $this->cookie->projectMode = 'all'; + } + + $selectHtml = $this->select($projects, $projectID, $moduleName, $methodName, $extra); + foreach($this->lang->project->menu as $key => $menu) + { + $replace = $key == 'list' ? $selectHtml : $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 + * @param string $extra + * @access public + * @return string + */ + public function select($projects, $projectID, $currentModule, $currentMethod, $extra = '') + { + $projectMode = $this->cookie->projectMode ? $this->cookie->projectMode : 'all'; + $products = $this->loadModel('product')->getPairs('nocode'); + $productGroup = $this->getProductGroupList(); + $selectGroup = array(); + foreach($productGroup as $projects) + { + foreach($projects as $project) + { + if($projectMode == 'noclosed' and ($project->status == 'done' or $project->status == 'suspended')) continue; + + if($project->product) + { + $product = isset($products[$project->product]) ? $products[$project->product] : ''; + $selectGroup[$product][$project->id] = $project->name; + } + else + { + $selectGroup[$this->lang->project->noProduct][$project->id] = $project->name; + } + } + } + + /* See product's model method:select. */ + $switchCode = "switchProject($('#projectID').val(), '$currentModule', '$currentMethod', '$extra');"; + $onchange = "onchange=\"$switchCode\""; + $onkeypress = "onkeypress=\"eventKeyCode=event.keyCode; if(eventKeyCode == 13) $switchCode\""; + $onclick = "onclick=\"eventKeyCode = 13; $switchCode\""; + $selectHtml = html::selectGroup('projectID', $selectGroup, $projectID, "tabindex=2 $onchange $onkeypress"); + return $selectHtml; + } + + /** + * Get project tree menu. + * + * @access public + * @return void + */ + public function tree() + { + $products = $this->loadModel('product')->getPairs('nocode'); + $productGroup = $this->getProductGroupList(); + $projectTree = "
            "; + foreach($productGroup as $productID => $projects) + { + if(!isset($products[$productID]) and $productID != '') continue; + $productName = isset($products[$productID]) ? $products[$productID] : $this->lang->project->noProduct; + $projectTree .= "
          • $productName
              "; + + foreach($projects as $project) + { + if($project->status != 'done') + { + $projectTree .= "
            • " . html::a(inlink('task', "projectID=$project->id"), $project->name, '', "id='project$project->id'") . "
            • "; + } + } + + + $hasDone = false; + foreach($projects as $project) + { + if($project->status == 'done') + { + $hasDone = true; + break; + } + } + if($hasDone) + { + $projectTree .= "
            • {$this->lang->project->selectGroup->done}
                "; + foreach($projects as $project) + { + if($project->status == 'done') + { + $projectTree .= "
              • " . html::a(inlink('task', "projectID=$project->id"), $project->name, '', "id='project$project->id'") . "
              • "; + } + } + $projectTree .= "
            • "; + } + + $projectTree .= "
          • "; + } + + $projectTree .= "
          "; + + return $projectTree; + } + + /** + * 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; + } + + /** + * Save order + * + * @access public + * @return void + */ + public function saveOrder() + { + foreach($_POST as $projectID => $order) + { + $this->dao->update(TABLE_PROJECT)->set('`order`')->eq($order)->where('id')->eq($projectID)->exec(); + } + } + + /** + * Create a project. + * + * @access public + * @return void + */ + public function create($copyProjectID = '') + { + $this->lang->project->team = $this->lang->project->teamname; + $project = fixer::input('post') + ->setDefault('status', 'wait') + ->stripTags('name, code, team') + ->setIF($this->post->acl != 'custom', 'whitelist', '') + ->join('whitelist', ',') + ->remove('products, workDays, delta') + ->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(); + $today = helper::today(); + $creatorExists = false; + + /* Copy team of project. */ + if($copyProjectID != '') + { + $members = $this->dao->select('*')->from(TABLE_TEAM)->where('project')->eq($copyProjectID)->fetchAll(); + foreach($members as $member) + { + $member->project = $projectID; + $member->join = $today; + $this->dao->insert(TABLE_TEAM)->data($member)->exec(); + if($member->account == $this->app->user->account) $creatorExists = true; + } + } + + /* Add the creator to team. */ + if($copyProjectID == '' or !$creatorExists) + { + $member->project = $projectID; + $member->account = $this->app->user->account; + $member->join = $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 == 'QD' or $fieldName == 'RD' ) + { + if(!empty($value) and !isset($team[$value])) + { + $member->project = (int)$projectID; + $member->account = $value; + $member->join = helper::today(); + $member->role = $this->lang->project->$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); + } + + /** + * Start project. + * + * @param int $projectID + * @access public + * @return void + */ + public function start($projectID) + { + $oldProject = $this->getById($projectID); + $now = helper::now(); + $project = fixer::input('post') + ->setDefault('status', 'doing') + ->remove('comment')->get(); + + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck() + ->where('id')->eq((int)$projectID) + ->exec(); + + if(!dao::isError()) return common::createChanges($oldProject, $project); + } + + /** + * Delay project. + * + * @param int $projectID + * @access public + * @return void + */ + public function delay($projectID) + { + $oldProject = $this->getById($projectID); + $now = helper::now(); + $project = fixer::input('post')->remove('comment')->get(); + + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck() + ->where('id')->eq((int)$projectID) + ->exec(); + + if(!dao::isError()) return common::createChanges($oldProject, $project); + } + + /** + * Suspend project. + * + * @param int $projectID + * @access public + * @return void + */ + public function suspend($projectID) + { + $oldProject = $this->getById($projectID); + $now = helper::now(); + $project = fixer::input('post') + ->setDefault('status', 'suspended') + ->remove('comment')->get(); + + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck() + ->where('id')->eq((int)$projectID) + ->exec(); + + if(!dao::isError()) return common::createChanges($oldProject, $project); + } + + /** + * Activate project. + * + * @param int $projectID + * @access public + * @return void + */ + public function activate($projectID) + { + $oldProject = $this->getById($projectID); + $now = helper::now(); + $project = fixer::input('post') + ->setDefault('status', 'doing') + ->remove('comment')->get(); + + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck() + ->where('id')->eq((int)$projectID) + ->exec(); + + if(!dao::isError()) return common::createChanges($oldProject, $project); + } + + /** + * Close project. + * + * @param int $projectID + * @access public + * @return void + */ + public function close($projectID) + { + $oldProject = $this->getById($projectID); + $now = helper::now(); + $project = fixer::input('post') + ->setDefault('status', 'done') + ->remove('comment')->get(); + + $this->dao->update(TABLE_PROJECT)->data($project) + ->autoCheck() + ->where('id')->eq((int)$projectID) + ->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 : 'isDone, `order`, status'; + $mode .= $this->cookie->projectMode; + /* Order by status's content whether or not done */ + $projects = $this->dao->select('*, IF(INSTR(" done", status) < 2, 0, 1) AS isDone')->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 + * @param int $productID + * @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('`order`, status') + ->beginIF($limit)->limit($limit)->fi() + ->fetchAll('id'); + } + else + { + return $this->dao->select('*, IF(INSTR(" done", status) < 2, 0, 1) AS isDone')->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($this->config->project->orderBy) + ->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,t1.status, t2.product')->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.project') + ->where('t1.deleted')->eq(0) + ->orderBy('t1.order') + ->fetchGroup('product'); + + $projects = $this->getList(); + + foreach($list as $id => $product) + { + foreach($product as $ID => $project) + { + if(!$this->checkPriv($projects[$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, $itemCounts = 30) + { + /* Init vars. */ + $projects = $this->getList($status, 0, $productID); + $projectKeys = array_keys($projects); + $stats = array(); + $hours = array(); + $emptyHour = array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'progress' => 0); + + /* Get all tasks and compute totalEstimate, totalConsumed, totalLeft, progress according to them. */ + $tasks = $this->dao->select('id, project, estimate, consumed, `left`, status, closedReason') + ->from(TABLE_TASK) + ->where('project')->in($projectKeys) + ->andWhere('deleted')->eq(0) + ->fetchGroup('project', 'id'); + + /* Compute totalEstimate, totalConsumed, totalLeft. */ + foreach($tasks as $projectID => $projectTasks) + { + $hour = (object)$emptyHour; + foreach($projectTasks as $task) + { + $hour->totalEstimate += $task->estimate; + $hour->totalConsumed += $task->consumed; + $hour->totalLeft += ($task->status != 'cancel' and $task->closedReason != 'cancel') ? $task->left : 0; + } + $hours[$projectID] = $hour; + } + + /* Compute totalReal and progress. */ + 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 burndown charts datas. */ + $burns = $this->dao->select('project, date AS name, `left` AS value') + ->from(TABLE_BURN) + ->where('project')->in($projectKeys) + ->orderBy('date desc') + ->fetchGroup('project', 'name'); + + foreach($burns as $projectID => $projectBurns) + { + /* If projectBurns > $itemCounts, split it, else call processBurnData() to pad burns. */ + $begin = $projects[$projectID]->begin; + $end = $projects[$projectID]->end; + if(count($projectBurns) >= $itemCounts) $projectBurns = array_slice($projectBurns, 0, $itemCounts); + if(count($projectBurns) < $itemCounts) $projectBurns = $this->processBurnData($projectBurns, $itemCounts, $begin, $end); + + /* Shorter names. */ + foreach($projectBurns as $projectBurn) + { + $projectBurn->name = substr($projectBurn->name, 5); + unset($projectBurn->project); + } + + ksort($projectBurns); + $burns[$projectID] = $projectBurns; + } + + /* Process projects. */ + foreach($projects as $key => $project) + { + if(!$this->checkPriv($project)) + { + unset($projects[$key]); + continue; + } + + // Process the end time. + $project->end = date(DT_DATE4, strtotime($project->end)); + + /* Process the burns. */ + $project->burns = array(); + $burnData = isset($burns[$project->id]) ? $burns[$project->id] : array(); + foreach($burnData as $data) $project->burns[] = $data->value; + + /* Process the hours. */ + $project->hours = isset($hours[$project->id]) ? $hours[$project->id] : (object)$emptyHour; + + $stats[] = $project; + } + + return $stats; + } + + /** + * Get project by id. + * + * @param int $projectID + * @param bool $setImgSize + * @access public + * @return void + */ + public function getById($projectID, $setImgSize = false) + { + $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); + + if($setImgSize) $project->desc = $this->loadModel('file')->setImgSize($project->desc); + if($setImgSize) $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,QD,RD')->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->QD = ''; + $managers->RD = ''; + 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(); + } + + /** + * Get projects to import + * + * @access public + * @return void + */ + public function getProjectsToImport() + { + $projects = $this->dao->select('distinct t1.*')->from(TABLE_PROJECT)->alias('t1') + ->leftJoin(TABLE_TASK)->alias('t2')->on('t1.id=t2.project') + ->where('t2.status')->notIN('done,closed') + ->orderBy('id desc') + ->fetchAll('id'); + + $pairs = array(); + $now = date('Y-m-d'); + foreach($projects as $id => $project) + { + if($this->checkPriv($project) and ($project->status == 'done' or $project->end < $now)) $pairs[$id] = ucfirst(substr($project->code, 0, 1)) . ':' . $project->name; + } + return $pairs; + } + + /** + * 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'); + // $products = $this->dao->select('product')->from(TABLE_PROJECTPRODUCT)->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($fromProject) + { + $this->loadModel('task'); + $tasks = array(); + $projectTasks = $this->task->getProjectTasks($fromProject, 'wait,doing,cancel'); + $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 = new stdclass(); + $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; + } + + /** + * Get teams which can be imported. + * + * @param string $account + * @param int $currentProject + * @access public + * @return array + */ + public function getTeams2Import($account, $currentProject) + { + return $this->dao->select('t1.project, t2.name as projectName') + ->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') + ->where('t1.account')->eq($account) + ->andWhere('t1.project')->ne($currentProject) + ->groupBy('t1.project') + ->orderBy('t1.project DESC') + ->fetchPairs(); + } + + /** + * Get members of a project who can be imported. + * + * @param int $project + * @param array $currentMembers + * @access public + * @return array + */ + public function getMembers2Import($project, $currentMembers) + { + return $this->dao->select('account, role, hours') + ->from(TABLE_TEAM) + ->where('project')->eq($project) + ->andWhere('account')->notIN($currentMembers) + ->fetchAll('account'); + } + + /** + * 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 = new stdclass(); + $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'") + ->andWhere('status')->notin('done,suspended') + ->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 + * @param string $mode noempty: skip the dates without burn down data. + * @access public + * @return array + */ + public function getBurnData($projectID = 0, $itemCounts = 30, $mode = 'noempty') + { + /* 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'); + $this->processBurnData($sets, $itemCounts, $project->begin, $project->end, $mode); + } + + foreach($sets as $set) $set->name = substr($set->name, 5); + return $sets; + } + + /** + * Get burn data for flot + * + * @param int $projectID + * @param int $itemCounts + * @access public + * @return void + */ + public function getBurnDataFlot($projectID = 0, $itemCounts = 30) + { + /* Get project and burn counts. */ + $project = $this->getById($projectID); + + /* If the burnCounts > $itemCounts, get the latest $itemCounts records. */ + $sets = $this->dao->select('date AS name, `left` AS value')->from(TABLE_BURN)->where('project')->eq((int)$projectID)->orderBy('date DESC')->fetchAll('name'); + + $count = 0; + $burnData = array(); + foreach($sets as $date => $set) + { + if($count > $itemCounts) break; + if($date > $project->end) continue; + + $set->name = $this->getMicTime($set->name); + $burnData[$date] = $set; + $count++; + } + $burnData = array_reverse($burnData); + + return $burnData; + } + + /** + * Get microsecond from date. + * + * @param string|int $date + * @access public + * @return void + */ + public function getMicTime($date) + { + if(is_numeric($date)) return (string)$date . '000'; + return (string)strtotime("$date UTC") . '000'; + } + + /** + * Process burndown datas when the sets is smaller than the itemCounts. + * + * @param array $sets + * @param int $itemCounts + * @param date $begin + * @param date $end + * @param string $mode + * @access public + * @return array + */ + public function processBurnData($sets, $itemCounts, $begin, $end, $mode = 'noempty') + { + $burnCounts = count($sets); + $current = helper::today(); + + if($end != '0000-00-00') + { + $period = helper::diffDate($end, $begin) + 1; + $counts = $period > $itemCounts ? $itemCounts : $period; + } + else + { + $counts = $itemCounts; + } + + for($i = 0; $i < $counts - $burnCounts; $i ++) + { + if(helper::diffDate($current, $end) > 0) break; + if(!isset($sets[$current]) and $mode != 'noempty') + { + $sets[$current]->name = $current; + $sets[$current]->value = ''; + } + $nextDay = date(DT_DATE1, strtotime('next day', strtotime($current))); + $current = $nextDay; + } + 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(); + $this->loadModel('task')->processTasks($tasks); + 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 the summary of project. + * + * @param array $tasks + * @access public + * @return string + */ + public function summary($tasks) + { + $taskSum = $statusWait = $statusDone = $statusDoing = $statusClosed = $statusCancel = 0; + $totalEstimate = $totalConsumed = $totalLeft = 0.0; + foreach($tasks as $task) + { + $totalEstimate += $task->estimate; + $totalConsumed += $task->consumed; + $totalLeft += (($task->status == 'cancel' or $task->closedReason == 'cancel') ? 0 : $task->left); + $statusVar = 'status' . ucfirst($task->status); + $$statusVar ++; + } + + return sprintf($this->lang->project->taskSummary, count($tasks), $statusWait, $statusDoing, $totalEstimate, $totalConsumed, $totalLeft); + } + + /** + * Judge an action is clickable or not. + * + * @param object $project + * @param string $action + * @access public + * @return bool + */ + public function isClickable($project, $action) + { + $action = strtolower($action); + + if($action == 'start') return $project->status == 'wait'; + if($action == 'close') return $project->status != 'done'; + if($action == 'suspend') return $project->status == 'wait' or $project->status == 'doing'; + if($action == 'delay') return $project->status == 'wait' or $project->status == 'doing'; + if($action == 'activate') return $project->status == 'suspended' or $project->status == 'done'; + + return true; + } +} diff --git a/module/project/view/activate.html.php b/module/project/view/activate.html.php index 43a3232d32..e47d106bbd 100644 --- a/module/project/view/activate.html.php +++ b/module/project/view/activate.html.php @@ -1,29 +1,29 @@ - - * @package project - * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package project + * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/project/view/browse.html.php b/module/project/view/browse.html.php index df0f029fbc..7be9a511ad 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 10a0129372..3a73b9f432 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");?>
          -
          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->severityList[$bug->severity]?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> - id"; - common::printIcon('bug', 'resolve', $params, $bug, 'list'); - common::printIcon('bug', 'close', $params, $bug, 'list'); - common::printIcon('bug', 'edit', $params, $bug, 'list'); - ?> -
          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");?>
          +
          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->severityList[$bug->severity]?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>assignedTo];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?> + id"; + common::printIcon('bug', 'resolve', $params, $bug, 'list'); + common::printIcon('bug', 'close', $params, $bug, 'list'); + common::printIcon('bug', 'edit', $params, $bug, 'list'); + ?> +
          show();?>
          + + diff --git a/module/project/view/build.html.php b/module/project/view/build.html.php index a5a50c20a2..d945991ca8 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");?>
          -
          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::printIcon('build', 'edit', "buildID=$build->id"); - common::printIcon('build', 'delete', "buildID=$build->id", '', 'list', '', 'hiddenwin'); - ?> -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          project->build;?>
          +
          id");?>
          +
          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::printIcon('build', 'edit', "buildID=$build->id"); + common::printIcon('build', 'delete', "buildID=$build->id", '', 'list', '', 'hiddenwin'); + ?> +
          + diff --git a/module/project/view/burn.html.php b/module/project/view/burn.html.php index 5fc3d8d512..730fb27f75 100644 --- a/module/project/view/burn.html.php +++ b/module/project/view/burn.html.php @@ -1,23 +1,23 @@ - - * @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/close.html.php b/module/project/view/close.html.php index 99ee9734b4..bdf8e2bf5b 100644 --- a/module/project/view/close.html.php +++ b/module/project/view/close.html.php @@ -1,27 +1,27 @@ - - * @package project - * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package project + * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/project/view/computeburn.html.php b/module/project/view/computeburn.html.php index 10b5c1811a..c25782582d 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 442e1b69ed..645eda6b71 100644 --- a/module/project/view/create.html.php +++ b/module/project/view/create.html.php @@ -1,100 +1,100 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - -project->placeholder, 'json');?> -
          - - - - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > - - - - - - -
          -
          project->create;?>
          -
          project->copy . '?', '', 'onclick=switchCopyProject(this);');?>
          -
          project->copy;?>
          project->name;?>
          project->code;?>
          project->begin;?>
          project->end;?> - - project->endList , '', "onclick='computeEndDate(this.value)'");?> -
          project->days;?>project->day;?>
          project->teamname;?>
          project->manageProducts;?>
          project->goal;?>
          project->desc;?>
          project->acl;?>project->aclList, $acl, "onclick='setWhite(this.value);'"));?>
          project->whitelist;?>
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + +project->placeholder, 'json');?> +
          + + + + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + > + + + + + + +
          +
          project->create;?>
          +
          project->copy . '?', '', 'onclick=switchCopyProject(this);');?>
          +
          project->copy;?>
          project->name;?>
          project->code;?>
          project->begin;?>
          project->end;?> + + project->endList , '', "onclick='computeEndDate(this.value)'");?> +
          project->days;?>project->day;?>
          project->teamname;?>
          project->manageProducts;?>
          project->goal;?>
          project->desc;?>
          project->acl;?>project->aclList, $acl, "onclick='setWhite(this.value);'"));?>
          project->whitelist;?>
          +
          + diff --git a/module/project/view/delay.html.php b/module/project/view/delay.html.php index 737689f9e7..a577313faa 100644 --- a/module/project/view/delay.html.php +++ b/module/project/view/delay.html.php @@ -1,41 +1,41 @@ - - * @package project - * @version $Id: delay.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - -
          name;?>
          project->begin;?>begin, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->days;?>days, "class='text-3'") . $lang->project->day;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package project + * @version $Id: delay.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + +
          name;?>
          project->begin;?>begin, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->days;?>days, "class='text-3'") . $lang->project->day;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/project/view/doc.html.php b/module/project/view/doc.html.php index 1608b03f4f..b89d2abbbf 100644 --- a/module/project/view/doc.html.php +++ b/module/project/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'); - ?> - - - - - - - - - - -
          -
          project->doc;?>
          -
          id&from=project");?>
          -
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module]);?>title);?>addedBy];?>addedDate;?> - id}"; - common::printIcon('doc', 'edit', $vars); - common::printIcon('doc', 'delete', $vars, '', 'list', '','hiddenwin'); - ?> -
          - + + * @package product + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + $doc):?> + createLink('doc', 'view', "docID=$doc->id"); + $canView = common::hasPriv('doc', 'view'); + ?> + + + + + + + + + + +
          +
          project->doc;?>
          +
          id&from=project");?>
          +
          idAB;?>doc->module;?>doc->title;?>doc->addedBy;?>doc->addedDate;?>actions;?>
          id)); else printf('%03d', $doc->id);?>module]);?>title);?>addedBy];?>addedDate;?> + id}"; + common::printIcon('doc', 'edit', $vars); + common::printIcon('doc', 'delete', $vars, '', 'list', '','hiddenwin'); + ?> +
          + diff --git a/module/project/view/dynamic.html.php b/module/project/view/dynamic.html.php index 7be0fc5b92..40e210719a 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-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();?>
          - - +dynamic view file of dashboard module of ZenTaoPMS. + * + * @copyright Copyright 2009-2013 青岛易软天创网络科技有限公司 (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 e023ac4c5e..646394186a 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -1,87 +1,87 @@ - - * @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='computeWorkDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->days;?>days, "class='text-3'") . $lang->project->day;?>
          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->QD;?>QD, 'class=text-3');?>
          project->RD;?>RD, '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='computeWorkDays()'");?>
          project->end;?>end, "class='text-3 date' onchange='computeWorkDays()'");?>
          project->days;?>days, "class='text-3'") . $lang->project->day;?>
          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->QD;?>QD, 'class=text-3');?>
          project->RD;?>RD, '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 2c5ddfdd65..c5bfd15272 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?>'>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?>'>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 ad1817ed77..7542a12ced 100755 --- a/module/project/view/importbug.html.php +++ b/module/project/view/importbug.html.php @@ -1,59 +1,59 @@ - - * @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->severityList[$bug->severity]?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]?>id", $bug->title, '', "class='preview'", true, true);?>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->severityList[$bug->severity]?>bug->priList[$bug->pri]?>'>bug->priList[$bug->pri]?>id", $bug->title, '', "class='preview'", true, true);?>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 ca2970f574..4453ca1cf3 100644 --- a/module/project/view/importtask.html.php +++ b/module/project/view/importtask.html.php @@ -1,72 +1,72 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - - - - - - - assignedTo == $app->user->account ? 'style=color:red' : '';?> - - - - - - - - - - - - - - -
          - $lang->project->fromproject) + $projects; - echo $lang->project->selectProject . ':'; - echo html::select('fromproject', $projects, $fromProject, "onchange='reload($projectID, this.value)'"); - ?> -
          project->name ?>idAB;?>priAB;?>task->name;?>task->assignedTo;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>task->story;?>import;?>
          project], 2);?>id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>pri?>'>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' : '';?> + + + + + + + + + + + + + + +
          + $lang->project->fromproject) + $projects; + echo $lang->project->selectProject . ':'; + echo html::select('fromproject', $projects, $fromProject, "onchange='reload($projectID, this.value)'"); + ?> +
          project->name ?>idAB;?>priAB;?>task->name;?>task->assignedTo;?>task->leftAB;?>task->deadlineAB;?>statusAB;?>task->story;?>import;?>
          project], 2);?>id", sprintf('%03d', $task->id))) printf('%03d', $task->id);?>pri?>'>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 109e2df278..e6af83f6f4 100644 --- a/module/project/view/index.html.php +++ b/module/project/view/index.html.php @@ -1,51 +1,51 @@ - - * @package ZenTaoPMS - * @version $Id$ - */ -?> - - - -

          - id"), $lang->project->all);?> - id"), $lang->project->statusList['wait']);?> - id"), $lang->project->statusList['doing']);?> - id"), $lang->project->statusList['suspended']);?> - id"), $lang->project->statusList['done']);?> -

          - - - - - - - - - - - - - - - - - - - - - - - - - -
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'view', 'project=' . $project->id), $project->name);?>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$ + */ +?> + + + +

          + id"), $lang->project->all);?> + id"), $lang->project->statusList['wait']);?> + id"), $lang->project->statusList['doing']);?> + id"), $lang->project->statusList['suspended']);?> + id"), $lang->project->statusList['done']);?> +

          + + + + + + + + + + + + + + + + + + + + + + + + + +
          project->name;?>project->code;?>project->end;?>project->status;?>project->totalEstimate;?>project->totalConsumed;?>project->totalLeft;?>project->progess;?>project->burn;?>
          createLink('project', 'view', 'project=' . $project->id), $project->name);?>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 5f27f4b612..0902cec5fc 100644 --- a/module/project/view/linkstory.html.php +++ b/module/project/view/linkstory.html.php @@ -1,63 +1,63 @@ - - * @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;?>
          - - - id);?> - story->priList[$story->pri]?>'>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;?>
          + + + id);?> + story->priList[$story->pri]?>'>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 7b7c4c0e14..c5a538de8b 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 b68945a70a..9b71ef4dca 100644 --- a/module/project/view/managemembers.html.php +++ b/module/project/view/managemembers.html.php @@ -1,82 +1,82 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -id);?> - -
          - - - - - - - - - - - account], 2);?> - account]);?> - - - - - - - - - - - - - - - - - - - - PROJECTMODEL::LINK_MEMBERS_ONE_TIME) $count = PROJECTMODEL::LINK_MEMBERS_ONE_TIME; - ?> - - - - - - - - - - - - - -
          -
          project->manageMembers;?>
          -
          -
          team->account;?>team->role;?>team->days;?>team->hours;?>
          - - - -
          account, "class='select-2' onchange='setRole(this.value, $i)'");?> - - -
          - - -
          - -
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +id);?> + +
          + + + + + + + + + + + account], 2);?> + account]);?> + + + + + + + + + + + + + + + + + + + + PROJECTMODEL::LINK_MEMBERS_ONE_TIME) $count = PROJECTMODEL::LINK_MEMBERS_ONE_TIME; + ?> + + + + + + + + + + + + + +
          +
          project->manageMembers;?>
          +
          +
          team->account;?>team->role;?>team->days;?>team->hours;?>
          + + + +
          account, "class='select-2' onchange='setRole(this.value, $i)'");?> + + +
          + + +
          + +
          +
          + diff --git a/module/project/view/manageproducts.html.php b/module/project/view/manageproducts.html.php index c0da830d90..5a662db064 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/order.html.php b/module/project/view/order.html.php index b30d8f6d84..7207f16df6 100644 --- a/module/project/view/order.html.php +++ b/module/project/view/order.html.php @@ -1,55 +1,55 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - - status == 'done') continue;?> - - - - - - - - -
          project->unDoneProjects?>
          project->id?>project->name?>project->status?>project->order?>
          id?>name?>project->statusList[$project->status]?>id, $project->order, "size='5'")?>
          -
          -
          - - - - - - - - - status != 'done') continue;?> - - - - - - - -
          project->doneProjects?>
          project->id?>project->name?>project->order?>
          id?>name?>id, $project->order, "size='5'")?>
          -
          - - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + + status == 'done') continue;?> + + + + + + + + +
          project->unDoneProjects?>
          project->id?>project->name?>project->status?>project->order?>
          id?>name?>project->statusList[$project->status]?>id, $project->order, "size='5'")?>
          +
          +
          + + + + + + + + + status != 'done') continue;?> + + + + + + + +
          project->doneProjects?>
          project->id?>project->name?>project->order?>
          id?>name?>id, $project->order, "size='5'")?>
          +
          + + diff --git a/module/project/view/sendmail.html.php b/module/project/view/sendmail.html.php index 042d73226c..f5de8e5237 100644 --- a/module/project/view/sendmail.html.php +++ b/module/project/view/sendmail.html.php @@ -1,39 +1,39 @@ - - * @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);?> -
          -
          - task->legendDesc;?> -
          - desc, 'src="data/upload')) - { - $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); - $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); - } - echo $task->desc; - ?> -
          -
          -
          + + * @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);?> +
          +
          + task->legendDesc;?> +
          + desc, 'src="data/upload')) + { + $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); + $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); + } + echo $task->desc; + ?> +
          +
          +
          diff --git a/module/project/view/start.html.php b/module/project/view/start.html.php index 08aa37f96b..15c827a55e 100644 --- a/module/project/view/start.html.php +++ b/module/project/view/start.html.php @@ -1,28 +1,28 @@ - - * @package project - * @version $Id: start.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package project + * @version $Id: start.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/project/view/story.html.php b/module/project/view/story.html.php index ee2474dfd4..8e4988d8f8 100644 --- a/module/project/view/story.html.php +++ b/module/project/view/story.html.php @@ -1,115 +1,115 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - id}&orderBy=%s"; ?> - - - - - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - $totalEstimate += $story->estimate; - ?> - - - - - - - - - - - - - - - - - - - -
          -
          project->story;?>
          -
          - lang->story->create = $this->lang->project->createStory; - if($productID) common::printIcon('story', 'create', "productID=$productID&moduleID=0&story=0&project=$project->id"); - - common::printIcon('project', 'linkStory', "project=$project->id"); - ?> -
          -
          idAB);?> priAB);?> story->title);?> openedByAB);?> assignedToAB);?> story->estimateAB);?> statusAB);?> story->stageAB);?> story->taskCount;?> actions;?>
          - - id));?> - story->priList[$story->pri]?>'>story->priList[$story->pri];?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> - id}&story={$story->id}"; - - $lang->task->batchCreate = $lang->project->batchWBS; - common::printIcon('task', 'batchCreate', $param . "&iframe=1", '', 'list', '', '', 'batchWBS', true); - - $lang->task->create = $lang->project->wbs; - common::printIcon('task', 'create', $param, '', 'list'); - - $lang->project->unlinkStory = $lang->unlink; - common::printIcon('project', 'unlinkStory', $param, '', 'list', '', 'hiddenwin'); - ?> -
          -
          - createLink('story', 'batchEdit', "from=projectStory&productID=0&projectID=$project->id&orderBy=$orderBy"); - echo html::commonButton($lang->story->batchEdit, "onclick=\"changeAction('projectStoryForm', 'batchEdit', '$actionLink')\""); - } - if(common::hasPriv('story', 'batchClose')) - { - $actionLink = $this->createLink('story', 'batchClose', "from=projectStory&productID=0&projectID=$project->id&orderBy=$orderBy"); - echo html::commonButton($lang->story->batchClose, "onclick=\"changeAction('projectStoryForm', 'batchClose', '$actionLink')\""); - } - } - printf($lang->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;?>
          +
          + lang->story->create = $this->lang->project->createStory; + if($productID) common::printIcon('story', 'create', "productID=$productID&moduleID=0&story=0&project=$project->id"); + + common::printIcon('project', 'linkStory', "project=$project->id"); + ?> +
          +
          idAB);?> priAB);?> story->title);?> openedByAB);?> assignedToAB);?> story->estimateAB);?> statusAB);?> story->stageAB);?> story->taskCount;?> actions;?>
          + + id));?> + story->priList[$story->pri]?>'>story->priList[$story->pri];?>title);?>openedBy];?>assignedTo];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?> + id}&story={$story->id}"; + + $lang->task->batchCreate = $lang->project->batchWBS; + common::printIcon('task', 'batchCreate', $param . "&iframe=1", '', 'list', '', '', 'batchWBS', true); + + $lang->task->create = $lang->project->wbs; + common::printIcon('task', 'create', $param, '', 'list'); + + $lang->project->unlinkStory = $lang->unlink; + common::printIcon('project', 'unlinkStory', $param, '', 'list', '', 'hiddenwin'); + ?> +
          +
          + createLink('story', 'batchEdit', "from=projectStory&productID=0&projectID=$project->id&orderBy=$orderBy"); + echo html::commonButton($lang->story->batchEdit, "onclick=\"changeAction('projectStoryForm', 'batchEdit', '$actionLink')\""); + } + if(common::hasPriv('story', 'batchClose')) + { + $actionLink = $this->createLink('story', 'batchClose', "from=projectStory&productID=0&projectID=$project->id&orderBy=$orderBy"); + echo html::commonButton($lang->story->batchClose, "onclick=\"changeAction('projectStoryForm', 'batchClose', '$actionLink')\""); + } + } + printf($lang->product->storySummary, count($stories), $totalEstimate); + ?> +
          +
          +
          + diff --git a/module/project/view/suspend.html.php b/module/project/view/suspend.html.php index 99ee9734b4..bdf8e2bf5b 100644 --- a/module/project/view/suspend.html.php +++ b/module/project/view/suspend.html.php @@ -1,27 +1,27 @@ - - * @package project - * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - -
          - - - - - - - - - -
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package project + * @version $Id: suspend.html.php 935 2013-01-16 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + +
          + + + + + + + + + +
          name;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/project/view/task.html.php b/module/project/view/task.html.php index b865915b75..26b8f1a32e 100644 --- a/module/project/view/task.html.php +++ b/module/project/view/task.html.php @@ -1,163 +1,163 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          '>
          - - - - - - - - - - - - -
          -
          project->projectTasks;?>
          -
          -
          -
          name;?>
          -
          - -
          - edit);?> - delete, 'hiddenwin');?> - tree->manage);?> - tree->fix, 'hiddenwin');?> -
          -
          -
          -
          id&from=projectTask&orderBy=$orderBy");?>'> - - 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' : ''; ?> - - - - - - - - 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]?>'>task->priList[$task->pri];?> - id", $task->name)) echo $task->name; - if($task->fromBug) echo html::a($this->createLink('bug', 'view', "id=$task->fromBug"), "[BUG#$task->fromBug]", '_blank', "class='bug'"); - ?> - 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);?> - - - >assignedTo == 'closed' ? 'Closed' : $task->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; - ?> - - id", $task, 'list'); - if($browseType == 'needconfirm') - { - $lang->task->confirmStoryChange = $lang->confirm; - common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin'); - } - common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task, 'list'); - common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list'); - common::printIcon('task', 'close', "taskID=$task->id", $task, 'list'); - common::printIcon('task', 'edit',"taskID=$task->id", '', 'list'); - ?> -
          -
          - task->batchEdit); - echo $summary; - ?> -
          - show();?> -
          -
          -
          - - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          '>
          + + + + + + + + + + + + +
          +
          project->projectTasks;?>
          +
          +
          +
          name;?>
          +
          + +
          + edit);?> + delete, 'hiddenwin');?> + tree->manage);?> + tree->fix, 'hiddenwin');?> +
          +
          +
          +
          id&from=projectTask&orderBy=$orderBy");?>'> + + 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' : ''; ?> + + + + + + + + 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]?>'>task->priList[$task->pri];?> + id", $task->name)) echo $task->name; + if($task->fromBug) echo html::a($this->createLink('bug', 'view', "id=$task->fromBug"), "[BUG#$task->fromBug]", '_blank', "class='bug'"); + ?> + 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);?> + + + >assignedTo == 'closed' ? 'Closed' : $task->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; + ?> + + id", $task, 'list'); + if($browseType == 'needconfirm') + { + $lang->task->confirmStoryChange = $lang->confirm; + common::printIcon('task', 'confirmStoryChange', "taskid=$task->id", '', 'list', '', 'hiddenwin'); + } + common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task, 'list'); + common::printIcon('task', 'finish', "taskID=$task->id", $task, 'list'); + common::printIcon('task', 'close', "taskID=$task->id", $task, 'list'); + common::printIcon('task', 'edit',"taskID=$task->id", '', 'list'); + ?> +
          +
          + task->batchEdit); + echo $summary; + ?> +
          + show();?> +
          +
          +
          + + diff --git a/module/project/view/team.html.php b/module/project/view/team.html.php index 06d8d95b8d..9645383d47 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 8fa2148fb3..c0e645bb4b 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;?>
          -
          -
          idAB;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>createLink('testtask', 'view', "taskID=$task->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", '', 'list'); - common::printIcon('testtask', 'linkCase', "taskID=$task->id", '', 'list'); - common::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); - common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', '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;?>
          +
          +
          idAB;?>testtask->name;?>testtask->build;?>testtask->owner;?>testtask->begin;?>testtask->end;?>statusAB;?>actions;?>
          createLink('testtask', 'view', "taskID=$task->id"), sprintf('%03d', $task->id));?>createLink('testtask', 'view', "taskID=$task->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", '', 'list'); + common::printIcon('testtask', 'linkCase', "taskID=$task->id", '', 'list'); + common::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); + common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', 'hiddenwin'); + ?> +
          + diff --git a/module/project/view/view.html.php b/module/project/view/view.html.php index b4c07b6dff..9e6389109e 100644 --- a/module/project/view/view.html.php +++ b/module/project/view/view.html.php @@ -1,134 +1,134 @@ - - * @package project - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          deleted) echo "class='deleted'";?>>PROJECT #id . ' ' . $project->name;?>
          -
          - id"; - $browseLink = $this->session->projectList ? $this->session->projectList : inlink('browse', "projectID=$project->id"); - if(!$project->deleted) - { - ob_start(); - common::printIcon('project', 'start', "projectID=$project->id", $project); - common::printIcon('project', 'activate', "projectID=$project->id", $project); - common::printIcon('project', 'delay', "projectID=$project->id", $project); - common::printIcon('project', 'suspend', "projectID=$project->id", $project); - common::printIcon('project', 'close', "projectID=$project->id", $project); - - common::printDivider(); - common::printIcon('project', 'edit', $params); - common::printIcon('project', 'delete', $params, '', 'button', '', 'hiddenwin'); - common::printRPN($browseLink); - - $actionLinks = ob_get_contents(); - ob_end_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
          -
          - - - - - - - -
          -
          - project->desc;?> -
          desc;?>
          -
          - - -
          -
          - project->basicInfo?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          project->name;?>name;?>
          project->code;?>code;?>
          project->beginAndEnd;?>begin . ' ~ ' . $project->end;?>
          project->days;?>days;?>
          project->goal;?>goal;?>
          project->status;?>show($lang->project->statusList, $project->status);?>
          project->PM;?>PM];?>
          project->PO;?>PO];?>
          project->QD;?>QD];?>
          project->RD;?>RD];?>
          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] . ' '; - ?> -
          -
          -
          - project->otherInfo?> - - - - - -
          project->lblStats;?>project->stats, $project->totalHours, $project->totalEstimate, $project->totalConsumed, $project->totalLeft, 10)?>
          -
          -
          - + + * @package project + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          +
          deleted) echo "class='deleted'";?>>PROJECT #id . ' ' . $project->name;?>
          +
          + id"; + $browseLink = $this->session->projectList ? $this->session->projectList : inlink('browse', "projectID=$project->id"); + if(!$project->deleted) + { + ob_start(); + common::printIcon('project', 'start', "projectID=$project->id", $project); + common::printIcon('project', 'activate', "projectID=$project->id", $project); + common::printIcon('project', 'delay', "projectID=$project->id", $project); + common::printIcon('project', 'suspend', "projectID=$project->id", $project); + common::printIcon('project', 'close', "projectID=$project->id", $project); + + common::printDivider(); + common::printIcon('project', 'edit', $params); + common::printIcon('project', 'delete', $params, '', 'button', '', 'hiddenwin'); + common::printRPN($browseLink); + + $actionLinks = ob_get_contents(); + ob_end_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
          +
          + + + + + + + +
          +
          + project->desc;?> +
          desc;?>
          +
          + + +
          +
          + project->basicInfo?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          project->name;?>name;?>
          project->code;?>code;?>
          project->beginAndEnd;?>begin . ' ~ ' . $project->end;?>
          project->days;?>days;?>
          project->goal;?>goal;?>
          project->status;?>show($lang->project->statusList, $project->status);?>
          project->PM;?>PM];?>
          project->PO;?>PO];?>
          project->QD;?>QD];?>
          project->RD;?>RD];?>
          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] . ' '; + ?> +
          +
          +
          + project->otherInfo?> + + + + + +
          project->lblStats;?>project->stats, $project->totalHours, $project->totalEstimate, $project->totalConsumed, $project->totalLeft, 10)?>
          +
          +
          + diff --git a/module/qa/control.php b/module/qa/control.php index 2ddac19bb0..302a9f7f4b 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 60f80c5baf..e7ff0fcfee 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 815a69ed63..c8baeb09ef 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 3f02d52da1..d8cc2ad0fc 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 2605 2012-02-21 07:22:58Z wwccss $ - * @link http://www.zentao.net - */ -$lang->qa->common = '測試視圖'; -$lang->qa->index = "測試首頁"; + + * @package company + * @version $Id: zh-tw.php 2605 2012-02-21 07:22:58Z wwccss $ + * @link http://www.zentao.net + */ +$lang->qa->common = '測試視圖'; +$lang->qa->index = "測試首頁"; diff --git a/module/qa/model.php b/module/qa/model.php index bdbbca25a5..f60cf5fedd 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 5040042bbc..4082ff5804 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 cae27724bb..0c46e5f6f5 100644 --- a/module/release/control.php +++ b/module/release/control.php @@ -1,260 +1,260 @@ - - * @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); - $products = $this->product->getPairs(); - $this->session->set('releaseList', $this->app->getURI(true)); - $this->view->header->title = $products[$productID] . $this->lang->colon . $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); - $releaseBuilds = $this->release->getReleaseBuilds($productID); - foreach($releaseBuilds as $build) unset($builds[$build]); - 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('build'); - - /* Get release and build. */ - $release = $this->release->getById((int)$releaseID); - $this->commonAction($release->product); - $build = $this->build->getById($release->build); - if($release->build !=0) - { - /* Get stories and bugs. */ - $orderBy = 'status_asc, stage_asc, id_desc'; - $stories = $this->story->getProjectStories($build->project, $orderBy); - $bugs = $this->bug->getProjectBugs($build->project); - } - else - { - $stories = array(); - $bugs = array(); - } - - $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, true); - if(!$release) die(js::error($this->lang->notFound) . js::locate('back')); - - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->fetchAll(); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->fetchAll(); - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); - - - $this->commonAction($release->product); - $products = $this->product->getPairs(); - $this->view->header->title = "RELEASE #$release->id $release->name/" . $products[$release->product]; - $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'); - $this->loadModel('story'); - $build = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch(); - if(!empty($build)) - { - $stories = $this->story->getProjectStories($build->project, $orderBy); - $bugs = $this->bug->getReleaseBugs($buildID, $productID); - } - $this->view->productID = $productID; - $this->view->stories = $stories; - $this->view->bugs = $bugs; - $this->view->orderBy = $orderBy; - die($this->display()); - } - - /** - * Export the stories of release to HTML. - * - * @param string $type story | bug - * @access public - * @return void - */ - public function export($type) - { - if(!empty($_POST)) - { - if($type == 'story') - { - $this->loadModel('story'); - - $stories = $this->dao->select('id, title')->from(TABLE_STORY)->where($this->session->storyQueryCondition) - ->beginIF($this->session->storyOrderBy != false)->orderBy($this->session->storyOrderBy)->fi() - ->fetchAll('id'); - - foreach($stories as $story) - { - $story->title = "id") . "' target='_blank'>$story->title"; - } - - $this->post->set('fields', array('id' => $this->lang->story->id, 'title' => $this->lang->story->title)); - $this->post->set('rows', $stories); - $this->fetch('file', 'export2HTML', $_POST); - } - else if($type == 'bug') - { - $this->loadModel('bug'); - - $bugs = $this->dao->select('id, title')->from(TABLE_BUG)->where($this->session->bugQueryCondition) - ->beginIF($this->session->bugOrderBy != false)->orderBy($this->session->bugOrderBy)->fi() - ->fetchAll('id'); - - foreach($bugs as $bug) - { - $bug->title = "id") . "' target='_blank'>$bug->title"; - } - - $this->post->set('fields', array('id' => $this->lang->bug->id, 'title' => $this->lang->bug->title)); - $this->post->set('rows', $bugs); - $this->fetch('file', 'export2HTML', $_POST); - } - } - - $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); + $products = $this->product->getPairs(); + $this->session->set('releaseList', $this->app->getURI(true)); + $this->view->header->title = $products[$productID] . $this->lang->colon . $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); + $releaseBuilds = $this->release->getReleaseBuilds($productID); + foreach($releaseBuilds as $build) unset($builds[$build]); + 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('build'); + + /* Get release and build. */ + $release = $this->release->getById((int)$releaseID); + $this->commonAction($release->product); + $build = $this->build->getById($release->build); + if($release->build !=0) + { + /* Get stories and bugs. */ + $orderBy = 'status_asc, stage_asc, id_desc'; + $stories = $this->story->getProjectStories($build->project, $orderBy); + $bugs = $this->bug->getProjectBugs($build->project); + } + else + { + $stories = array(); + $bugs = array(); + } + + $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, true); + if(!$release) die(js::error($this->lang->notFound) . js::locate('back')); + + $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->fetchAll(); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + + $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->fetchAll(); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'bug'); + + + $this->commonAction($release->product); + $products = $this->product->getPairs(); + $this->view->header->title = "RELEASE #$release->id $release->name/" . $products[$release->product]; + $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'); + $this->loadModel('story'); + $build = $this->dao->select('project')->from(TABLE_BUILD)->where('id')->eq($buildID)->fetch(); + if(!empty($build)) + { + $stories = $this->story->getProjectStories($build->project, $orderBy); + $bugs = $this->bug->getReleaseBugs($buildID, $productID); + } + $this->view->productID = $productID; + $this->view->stories = $stories; + $this->view->bugs = $bugs; + $this->view->orderBy = $orderBy; + die($this->display()); + } + + /** + * Export the stories of release to HTML. + * + * @param string $type story | bug + * @access public + * @return void + */ + public function export($type) + { + if(!empty($_POST)) + { + if($type == 'story') + { + $this->loadModel('story'); + + $stories = $this->dao->select('id, title')->from(TABLE_STORY)->where($this->session->storyQueryCondition) + ->beginIF($this->session->storyOrderBy != false)->orderBy($this->session->storyOrderBy)->fi() + ->fetchAll('id'); + + foreach($stories as $story) + { + $story->title = "id") . "' target='_blank'>$story->title"; + } + + $this->post->set('fields', array('id' => $this->lang->story->id, 'title' => $this->lang->story->title)); + $this->post->set('rows', $stories); + $this->fetch('file', 'export2HTML', $_POST); + } + else if($type == 'bug') + { + $this->loadModel('bug'); + + $bugs = $this->dao->select('id, title')->from(TABLE_BUG)->where($this->session->bugQueryCondition) + ->beginIF($this->session->bugOrderBy != false)->orderBy($this->session->bugOrderBy)->fi() + ->fetchAll('id'); + + foreach($bugs as $bug) + { + $bug->title = "id") . "' target='_blank'>$bug->title"; + } + + $this->post->set('fields', array('id' => $this->lang->bug->id, 'title' => $this->lang->bug->title)); + $this->post->set('rows', $bugs); + $this->fetch('file', 'export2HTML', $_POST); + } + } + + $this->display(); + } +} diff --git a/module/release/lang/en.php b/module/release/lang/en.php index 5679f4e824..fb46f024f4 100644 --- a/module/release/lang/en.php +++ b/module/release/lang/en.php @@ -1,37 +1,37 @@ - - * @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->basicInfo ='Basic Info'; - -$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'; -$lang->release->finishStories = 'The total demand for a complete %s'; -$lang->release->resolvedBugs = 'The total solution of bug%s'; -$lang->release->export = 'Export as HTML'; + + * @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->basicInfo ='Basic Info'; + +$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'; +$lang->release->finishStories = 'The total demand for a complete %s'; +$lang->release->resolvedBugs = 'The total solution of bug%s'; +$lang->release->export = 'Export as HTML'; diff --git a/module/release/lang/zh-cn.php b/module/release/lang/zh-cn.php index a284b17d29..ddbb2d0dfe 100644 --- a/module/release/lang/zh-cn.php +++ b/module/release/lang/zh-cn.php @@ -1,37 +1,37 @@ - - * @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->basicInfo ='基本信息'; - -$lang->release->id = 'ID'; -$lang->release->product = '产品'; -$lang->release->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'; -$lang->release->finishStories = '本次共完成需求%s个'; -$lang->release->resolvedBugs = '本次共解决Bug%s个'; -$lang->release->export = '导出HTML'; + + * @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->basicInfo ='基本信息'; + +$lang->release->id = 'ID'; +$lang->release->product = '产品'; +$lang->release->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'; +$lang->release->finishStories = '本次共完成需求%s个'; +$lang->release->resolvedBugs = '本次共解决Bug%s个'; +$lang->release->export = '导出HTML'; diff --git a/module/release/lang/zh-tw.php b/module/release/lang/zh-tw.php index 258b9cafa9..82b7415dc5 100644 --- a/module/release/lang/zh-tw.php +++ b/module/release/lang/zh-tw.php @@ -1,37 +1,37 @@ - - * @package release - * @version $Id: zh-tw.php 3301 2012-07-03 01:25:29Z chencongzhi520@gmail.com $ - * @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->basicInfo ='基本信息'; - -$lang->release->id = 'ID'; -$lang->release->product = '產品'; -$lang->release->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'; -$lang->release->finishStories = '本次共完成需求%s個'; -$lang->release->resolvedBugs = '本次共解決Bug%s個'; -$lang->release->export = '導出HTML'; + + * @package release + * @version $Id: zh-tw.php 3301 2012-07-03 01:25:29Z chencongzhi520@gmail.com $ + * @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->basicInfo ='基本信息'; + +$lang->release->id = 'ID'; +$lang->release->product = '產品'; +$lang->release->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'; +$lang->release->finishStories = '本次共完成需求%s個'; +$lang->release->resolvedBugs = '本次共解決Bug%s個'; +$lang->release->export = '導出HTML'; diff --git a/module/release/model.php b/module/release/model.php index 928324ca73..52e5c8cb27 100644 --- a/module/release/model.php +++ b/module/release/model.php @@ -1,131 +1,131 @@ - - * @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(); - if($setImgSize) $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(); - } - - /** - * Get release builds from product. - * - * @param int $productID - * @access public - * @return void - */ - public function getReleaseBuilds($productID) - { - $releases = $this->dao->select('build')->from(TABLE_RELEASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetchAll('build'); - return array_keys($releases); - } - - /** - * Create a release. - * - * @param int $productID - * @access public - * @return int - */ - public function create($productID) - { - if($this->post->build == false) - { - $build = fixer::input('post') - ->stripTags('name') - ->add('product', (int)$productID) - ->add('builder', $this->app->user->account) - ->remove('build') - ->get(); - $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->check('name','unique')->exec(); - $buildID = $this->dao->lastInsertID(); - } - - $release = fixer::input('post') - ->stripTags('name') - ->add('product', (int)$productID) - ->join('stories', ',') - ->join('bugs', ',') - ->remove('allchecker') - ->setIF($this->post->build ==false, 'build', $buildID) - ->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(); + if($setImgSize) $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(); + } + + /** + * Get release builds from product. + * + * @param int $productID + * @access public + * @return void + */ + public function getReleaseBuilds($productID) + { + $releases = $this->dao->select('build')->from(TABLE_RELEASE)->where('deleted')->eq(0)->andWhere('product')->eq($productID)->fetchAll('build'); + return array_keys($releases); + } + + /** + * Create a release. + * + * @param int $productID + * @access public + * @return int + */ + public function create($productID) + { + if($this->post->build == false) + { + $build = fixer::input('post') + ->stripTags('name') + ->add('product', (int)$productID) + ->add('builder', $this->app->user->account) + ->remove('build') + ->get(); + $this->dao->insert(TABLE_BUILD)->data($build)->autoCheck()->check('name','unique')->exec(); + $buildID = $this->dao->lastInsertID(); + } + + $release = fixer::input('post') + ->stripTags('name') + ->add('product', (int)$productID) + ->join('stories', ',') + ->join('bugs', ',') + ->remove('allchecker') + ->setIF($this->post->build ==false, 'build', $buildID) + ->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 c533771a5a..8be597bd97 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");?>
          -
          release->id;?>release->name;?>release->build;?>release->date;?>actions;?>
          id;?>id"), $release->name);?>buildName;?>date;?> - id", '', 'list'); - common::printIcon('release', 'delete', "release=$release->id", '', 'list', '', 'hiddenwin'); - ?> -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          release->browse;?>
          +
          id");?>
          +
          release->id;?>release->name;?>release->build;?>release->date;?>actions;?>
          id;?>id"), $release->name);?>buildName;?>date;?> + id", '', 'list'); + common::printIcon('release', 'delete', "release=$release->id", '', 'list', '', 'hiddenwin'); + ?> +
          + diff --git a/module/release/view/create.html.php b/module/release/view/create.html.php index 9a5ae73be6..a6e6d5ffa5 100644 --- a/module/release/view/create.html.php +++ b/module/release/view/create.html.php @@ -1,45 +1,45 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - -
          release->create;?>
          release->name;?>
          release->build;?> - build->notice; - ?> -
          release->date;?>
          release->desc;?>
          -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
          + + + + + + + + + + + + + + + + + + + + + +
          release->create;?>
          release->name;?>
          release->build;?> + build->notice; + ?> +
          release->date;?>
          release->desc;?>
          +
          + diff --git a/module/release/view/edit.html.php b/module/release/view/edit.html.php index 5daacd1e18..d24e9bf6f9 100644 --- a/module/release/view/edit.html.php +++ b/module/release/view/edit.html.php @@ -1,118 +1,118 @@ - - * @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;?> -
          - -
          - - - - - - - -
          - - - - - - - - -
          release->linkStories;?>
          idAB;?>story->title;?>statusAB;?>story->stageAB;?>
          -
          -
          - - $story):?> - createLink('story', 'view', "storyID=$story->id"); - ?> - - - - - - - -
          stories, $story->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          -
          -
          -
          - -
          - - - - - - - -
          - - - - - - - -
          release->linkBugs;?>
          idAB;?>bug->title;?>bug->status;?>
          -
          -
          - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - -
          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;?> +
          + +
          + + + + + + + +
          + + + + + + + + +
          release->linkStories;?>
          idAB;?>story->title;?>statusAB;?>story->stageAB;?>
          +
          +
          + + $story):?> + createLink('story', 'view', "storyID=$story->id"); + ?> + + + + + + + +
          stories, $story->id) !== false) echo 'checked';?>> id);?>title, '', "class='preview'");?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          +
          +
          +
          + +
          + + + + + + + +
          + + + + + + + +
          release->linkBugs;?>
          idAB;?>bug->title;?>bug->status;?>
          +
          +
          + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + +
          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/export.html.php b/module/release/view/export.html.php index 20c1cb2296..d6dee5b8bc 100755 --- a/module/release/view/export.html.php +++ b/module/release/view/export.html.php @@ -1,49 +1,49 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -

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

          +
          + + + + + +
          export;?>
          + setFileName;?> + + +
          +
          + diff --git a/module/release/view/view.html.php b/module/release/view/view.html.php index b13a344fef..4cf03baafe 100644 --- a/module/release/view/view.html.php +++ b/module/release/view/view.html.php @@ -1,117 +1,117 @@ - - * @package release - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
          '>RELEASE #id . ' ' . $release->name;?>
          -
          - release->desc;?> -
          desc;?>
          -
          - -
          - session->releaseList ? $this->session->releaseList : inlink('browse', "productID=$release->product"); - if(!$release->deleted) - { - common::printIcon('release', 'edit', "releaseID=$release->id"); - common::printIcon('release', 'delete', "releaseID=$release->id", '', 'button', '', 'hiddenwin'); - } - echo common::printRPN($browseLink, $lang->goback); - ?> -
          - - - - - - - - - - - - $story):?> - createLink('story', 'view', "storyID=$story->id");?> - - - - - - - - - - - -
          - release->stories;?> -
          -
          idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
          id);?>story->priList[$story->pri]?>'>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          release->finishStories, count($stories));?>
          - - - - - - - - - - - - - createLink('bug', 'view', "bugID=$bug->id");?> - - - - - - - - - - - -
          - release->bugs;?> -
          -
          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->resolvedBugs, count($bugs));?>
          -
          -
          - release->basicInfo?> - - - - - - - - - - - - - - - - - -
          release->product;?>productName;?>
          release->name;?>name;?>
          release->build;?>buildName;?>
          release->date;?>date;?>
          -
          -
          - + + * @package release + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
          '>RELEASE #id . ' ' . $release->name;?>
          +
          + release->desc;?> +
          desc;?>
          +
          + +
          + session->releaseList ? $this->session->releaseList : inlink('browse', "productID=$release->product"); + if(!$release->deleted) + { + common::printIcon('release', 'edit', "releaseID=$release->id"); + common::printIcon('release', 'delete', "releaseID=$release->id", '', 'button', '', 'hiddenwin'); + } + echo common::printRPN($browseLink, $lang->goback); + ?> +
          + + + + + + + + + + + + $story):?> + createLink('story', 'view', "storyID=$story->id");?> + + + + + + + + + + + +
          + release->stories;?> +
          +
          idAB;?>priAB;?>story->title;?>openedByAB;?>story->estimateAB;?>statusAB;?>story->stageAB;?>
          id);?>story->priList[$story->pri]?>'>story->priList[$story->pri];?>title, '', "class='preview'");?>openedBy];?>estimate;?>story->statusList[$story->status];?>story->stageList[$story->stage];?>
          release->finishStories, count($stories));?>
          + + + + + + + + + + + + + createLink('bug', 'view', "bugID=$bug->id");?> + + + + + + + + + + + +
          + release->bugs;?> +
          +
          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->resolvedBugs, count($bugs));?>
          +
          +
          + release->basicInfo?> + + + + + + + + + + + + + + + + + +
          release->product;?>productName;?>
          release->name;?>name;?>
          release->build;?>buildName;?>
          release->date;?>date;?>
          +
          +
          + diff --git a/module/report/control.php b/module/report/control.php index 7bd127c5c4..c044d1a04c 100644 --- a/module/report/control.php +++ b/module/report/control.php @@ -1,122 +1,122 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -class report extends control -{ - /** - * The index of report, goto project deviation. - * - * @access public - * @return void - */ - public function index() - { - $this->locate(inlink('productinfo')); - } - - /** - * Project deviation report. - * - * @access public - * @return void - */ - public function projectDeviation() - { - $this->view->header->title = $this->lang->report->projectDeviation; - $this->view->projects = $this->report->getProjects(); - $this->view->submenu = 'project'; - $this->display(); - } - - /** - * Product information report. - * - * @access public - * @return void - */ - public function productInfo() - { - $this->app->loadLang('product'); - $this->app->loadLang('productplan'); - $this->app->loadLang('story'); - $this->view->header->title = $this->lang->report->productInfo; - $this->view->products = $this->report->getProducts(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed'); - $this->view->submenu = 'product'; - $this->display(); - } - - /** - * Bug summary report. - * - * @param int $begin - * @param int $end - * @access public - * @return void - */ - public function bugSummary($begin = 0, $end = 0) - { - $this->app->loadLang('bug'); - if($begin == 0) - { - $begin = date('Y-m-d', strtotime('last month')); - } - else - { - $begin = date('Y-m-d', strtotime($begin)); - } - if($end == 0) - { - $end = date('Y-m-d', strtotime('now')); - } - else - { - $end = date('Y-m-d', strtotime($end)); - } - $this->view->header->title = $this->lang->report->bugSummary; - $this->view->begin = $begin; - $this->view->end = $end; - $this->view->bugs = $this->report->getBugs($begin, $end); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); - $this->view->submenu = 'test'; - $this->display(); - } - - /** - * Bug assign report. - * - * @access public - * @return void - */ - public function bugAssign() - { - $this->view->header->title = $this->lang->report->bugAssign; - $this->view->submenu = 'test'; - $this->view->assigns = $this->report->getBugAssign(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); - $this->display(); - } - - /** - * Workload report. - * - * @access public - * @return void - */ - public function workload() - { - $this->view->header->title = $this->lang->report->workload; - $this->view->workload = $this->report->getWorkload(); - $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); - $this->view->submenu = 'staff'; - $this->display(); - } -} + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +class report extends control +{ + /** + * The index of report, goto project deviation. + * + * @access public + * @return void + */ + public function index() + { + $this->locate(inlink('productinfo')); + } + + /** + * Project deviation report. + * + * @access public + * @return void + */ + public function projectDeviation() + { + $this->view->header->title = $this->lang->report->projectDeviation; + $this->view->projects = $this->report->getProjects(); + $this->view->submenu = 'project'; + $this->display(); + } + + /** + * Product information report. + * + * @access public + * @return void + */ + public function productInfo() + { + $this->app->loadLang('product'); + $this->app->loadLang('productplan'); + $this->app->loadLang('story'); + $this->view->header->title = $this->lang->report->productInfo; + $this->view->products = $this->report->getProducts(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed'); + $this->view->submenu = 'product'; + $this->display(); + } + + /** + * Bug summary report. + * + * @param int $begin + * @param int $end + * @access public + * @return void + */ + public function bugSummary($begin = 0, $end = 0) + { + $this->app->loadLang('bug'); + if($begin == 0) + { + $begin = date('Y-m-d', strtotime('last month')); + } + else + { + $begin = date('Y-m-d', strtotime($begin)); + } + if($end == 0) + { + $end = date('Y-m-d', strtotime('now')); + } + else + { + $end = date('Y-m-d', strtotime($end)); + } + $this->view->header->title = $this->lang->report->bugSummary; + $this->view->begin = $begin; + $this->view->end = $end; + $this->view->bugs = $this->report->getBugs($begin, $end); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); + $this->view->submenu = 'test'; + $this->display(); + } + + /** + * Bug assign report. + * + * @access public + * @return void + */ + public function bugAssign() + { + $this->view->header->title = $this->lang->report->bugAssign; + $this->view->submenu = 'test'; + $this->view->assigns = $this->report->getBugAssign(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); + $this->display(); + } + + /** + * Workload report. + * + * @access public + * @return void + */ + public function workload() + { + $this->view->header->title = $this->lang->report->workload; + $this->view->workload = $this->report->getWorkload(); + $this->view->users = $this->loadModel('user')->getPairs('noletter|noclosed|nodeleted'); + $this->view->submenu = 'staff'; + $this->display(); + } +} diff --git a/module/report/lang/en.php b/module/report/lang/en.php index 117b3107c1..38908709ba 100644 --- a/module/report/lang/en.php +++ b/module/report/lang/en.php @@ -1,72 +1,72 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->report->common = 'Report'; -$lang->report->index = 'Report index'; -$lang->report->list = 'Report list'; -$lang->report->item = 'Item'; -$lang->report->value = 'Value'; -$lang->report->percent = 'Percent'; -$lang->report->undefined = 'Undefined'; -$lang->report->time = 'Time'; - -$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'; - -$lang->report->projectDeviation = 'Project deviation'; -$lang->report->productInfo = 'Product information'; -$lang->report->bugSummary = 'Bug summary'; -$lang->report->bugAssign = 'Bug assign'; -$lang->report->workload = 'Workload'; - -$lang->reportList->project->lists[10] = 'Project deviation|report|projectdeviation'; -$lang->reportList->product->lists[10] = 'Product information|report|productinfo'; -$lang->reportList->test->lists[10] = 'Bug summary|report|bugsummary'; -$lang->reportList->test->lists[13] = 'Bug assign|report|bugassign'; -$lang->reportList->staff->lists[10] = 'Workload|report|workload'; - -$lang->report->id = 'ID'; -$lang->report->project = 'Project'; -$lang->report->product = 'Product'; -$lang->report->user = 'Username'; -$lang->report->bug = 'Bug'; -$lang->report->task = 'Tasks'; -$lang->report->estimate = 'Estimate'; -$lang->report->consumed = 'Consumed'; -$lang->report->remain = 'Remain'; -$lang->report->manhour = 'Manhour'; -$lang->report->deviation = 'Deviation'; -$lang->report->deviationRate = 'Deviation rate'; -$lang->report->stories = 'Stories'; -$lang->report->bugs = 'Bugs'; -$lang->report->devConsumed = 'Develop'; -$lang->report->testConsumed = 'Test'; -$lang->report->devTestRate = 'Dev/Test'; -$lang->report->details = 'Details'; -$lang->report->total = 'Total'; -$lang->report->to = 'to'; -$lang->report->taskTotal = "Task Total"; -$lang->report->manhourTotal = "Manhour Total"; -$lang->report->bugTotal = "%s Bugs"; - -$lang->report->proVersion = 'Try pro version for more!'; + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->report->common = 'Report'; +$lang->report->index = 'Report index'; +$lang->report->list = 'Report list'; +$lang->report->item = 'Item'; +$lang->report->value = 'Value'; +$lang->report->percent = 'Percent'; +$lang->report->undefined = 'Undefined'; +$lang->report->time = 'Time'; + +$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'; + +$lang->report->projectDeviation = 'Project deviation'; +$lang->report->productInfo = 'Product information'; +$lang->report->bugSummary = 'Bug summary'; +$lang->report->bugAssign = 'Bug assign'; +$lang->report->workload = 'Workload'; + +$lang->reportList->project->lists[10] = 'Project deviation|report|projectdeviation'; +$lang->reportList->product->lists[10] = 'Product information|report|productinfo'; +$lang->reportList->test->lists[10] = 'Bug summary|report|bugsummary'; +$lang->reportList->test->lists[13] = 'Bug assign|report|bugassign'; +$lang->reportList->staff->lists[10] = 'Workload|report|workload'; + +$lang->report->id = 'ID'; +$lang->report->project = 'Project'; +$lang->report->product = 'Product'; +$lang->report->user = 'Username'; +$lang->report->bug = 'Bug'; +$lang->report->task = 'Tasks'; +$lang->report->estimate = 'Estimate'; +$lang->report->consumed = 'Consumed'; +$lang->report->remain = 'Remain'; +$lang->report->manhour = 'Manhour'; +$lang->report->deviation = 'Deviation'; +$lang->report->deviationRate = 'Deviation rate'; +$lang->report->stories = 'Stories'; +$lang->report->bugs = 'Bugs'; +$lang->report->devConsumed = 'Develop'; +$lang->report->testConsumed = 'Test'; +$lang->report->devTestRate = 'Dev/Test'; +$lang->report->details = 'Details'; +$lang->report->total = 'Total'; +$lang->report->to = 'to'; +$lang->report->taskTotal = "Task Total"; +$lang->report->manhourTotal = "Manhour Total"; +$lang->report->bugTotal = "%s Bugs"; + +$lang->report->proVersion = 'Try pro version for more!'; diff --git a/module/report/lang/zh-cn.php b/module/report/lang/zh-cn.php index df199dfcde..014049a87a 100644 --- a/module/report/lang/zh-cn.php +++ b/module/report/lang/zh-cn.php @@ -1,72 +1,72 @@ - - * @package report - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->report->common = '统计视图'; -$lang->report->index = '统计首页'; -$lang->report->list = '统计报表'; -$lang->report->item = '条目'; -$lang->report->value = '值'; -$lang->report->percent = '百分比'; -$lang->report->undefined = '未设定'; -$lang->report->time = '时间'; - -$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'; - -$lang->report->projectDeviation = '项目偏差报表'; -$lang->report->productInfo = '产品信息统计表'; -$lang->report->bugSummary = 'Bug汇总表'; -$lang->report->bugAssign = 'Bug指派表'; -$lang->report->workload = '员工负载表'; - -$lang->reportList->project->lists[10] = '项目偏差报表|report|projectdeviation'; -$lang->reportList->product->lists[10] = '产品信息统计表|report|productinfo'; -$lang->reportList->test->lists[10] = 'Bug汇总表|report|bugsummary'; -$lang->reportList->test->lists[13] = 'Bug指派表|report|bugassign'; -$lang->reportList->staff->lists[10] = '员工负载表|report|workload'; - -$lang->report->id = '编号'; -$lang->report->project = '项目'; -$lang->report->product = '产品'; -$lang->report->user = '姓名'; -$lang->report->bug = 'Bug'; -$lang->report->task = '任务数'; -$lang->report->estimate = '总预计'; -$lang->report->consumed = '总消耗'; -$lang->report->remain = '剩余工时'; -$lang->report->manhour = '工时'; -$lang->report->deviation = '偏差'; -$lang->report->deviationRate = '偏差率'; -$lang->report->stories = '需求数'; -$lang->report->bugs = 'Bug数'; -$lang->report->devConsumed = '开发时间'; -$lang->report->testConsumed = '测试时间'; -$lang->report->devTestRate = '开发/测试'; -$lang->report->details = '详情'; -$lang->report->total = '总计'; -$lang->report->to = '至'; -$lang->report->taskTotal = "总任务数"; -$lang->report->manhourTotal = "总工时"; -$lang->report->bugTotal = "共%s个Bug"; - -$lang->report->proVersion = '更多精彩,尽在专业版!'; + + * @package report + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->report->common = '统计视图'; +$lang->report->index = '统计首页'; +$lang->report->list = '统计报表'; +$lang->report->item = '条目'; +$lang->report->value = '值'; +$lang->report->percent = '百分比'; +$lang->report->undefined = '未设定'; +$lang->report->time = '时间'; + +$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'; + +$lang->report->projectDeviation = '项目偏差报表'; +$lang->report->productInfo = '产品信息统计表'; +$lang->report->bugSummary = 'Bug汇总表'; +$lang->report->bugAssign = 'Bug指派表'; +$lang->report->workload = '员工负载表'; + +$lang->reportList->project->lists[10] = '项目偏差报表|report|projectdeviation'; +$lang->reportList->product->lists[10] = '产品信息统计表|report|productinfo'; +$lang->reportList->test->lists[10] = 'Bug汇总表|report|bugsummary'; +$lang->reportList->test->lists[13] = 'Bug指派表|report|bugassign'; +$lang->reportList->staff->lists[10] = '员工负载表|report|workload'; + +$lang->report->id = '编号'; +$lang->report->project = '项目'; +$lang->report->product = '产品'; +$lang->report->user = '姓名'; +$lang->report->bug = 'Bug'; +$lang->report->task = '任务数'; +$lang->report->estimate = '总预计'; +$lang->report->consumed = '总消耗'; +$lang->report->remain = '剩余工时'; +$lang->report->manhour = '工时'; +$lang->report->deviation = '偏差'; +$lang->report->deviationRate = '偏差率'; +$lang->report->stories = '需求数'; +$lang->report->bugs = 'Bug数'; +$lang->report->devConsumed = '开发时间'; +$lang->report->testConsumed = '测试时间'; +$lang->report->devTestRate = '开发/测试'; +$lang->report->details = '详情'; +$lang->report->total = '总计'; +$lang->report->to = '至'; +$lang->report->taskTotal = "总任务数"; +$lang->report->manhourTotal = "总工时"; +$lang->report->bugTotal = "共%s个Bug"; + +$lang->report->proVersion = '更多精彩,尽在专业版!'; diff --git a/module/report/lang/zh-tw.php b/module/report/lang/zh-tw.php index 5027ac1274..927708fbc4 100644 --- a/module/report/lang/zh-tw.php +++ b/module/report/lang/zh-tw.php @@ -1,72 +1,72 @@ - - * @package report - * @version $Id: zh-tw.php 3381 2012-08-09 09:25:12Z zhujinyonging@gmail.com $ - * @link http://www.zentao.net - */ -$lang->report->common = '統計視圖'; -$lang->report->index = '統計首頁'; -$lang->report->list = '統計報表'; -$lang->report->item = '條目'; -$lang->report->value = '值'; -$lang->report->percent = '百分比'; -$lang->report->undefined = '未設定'; -$lang->report->time = '時間'; - -$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'; - -$lang->report->projectDeviation = '項目偏差報表'; -$lang->report->productInfo = '產品信息統計表'; -$lang->report->bugSummary = 'Bug彙總表'; -$lang->report->bugAssign = 'Bug指派表'; -$lang->report->workload = '員工負載表'; - -$lang->reportList->project->lists[10] = '項目偏差報表|report|projectdeviation'; -$lang->reportList->product->lists[10] = '產品信息統計表|report|productinfo'; -$lang->reportList->test->lists[10] = 'Bug彙總表|report|bugsummary'; -$lang->reportList->test->lists[13] = 'Bug指派表|report|bugassign'; -$lang->reportList->staff->lists[10] = '員工負載表|report|workload'; - -$lang->report->id = '編號'; -$lang->report->project = '項目'; -$lang->report->product = '產品'; -$lang->report->user = '姓名'; -$lang->report->bug = 'Bug'; -$lang->report->task = '任務數'; -$lang->report->estimate = '總預計'; -$lang->report->consumed = '總消耗'; -$lang->report->remain = '剩餘工時'; -$lang->report->manhour = '工時'; -$lang->report->deviation = '偏差'; -$lang->report->deviationRate = '偏差率'; -$lang->report->stories = '需求數'; -$lang->report->bugs = 'Bug數'; -$lang->report->devConsumed = '開發時間'; -$lang->report->testConsumed = '測試時間'; -$lang->report->devTestRate = '開發/測試'; -$lang->report->details = '詳情'; -$lang->report->total = '總計'; -$lang->report->to = '至'; -$lang->report->taskTotal = "總任務數"; -$lang->report->manhourTotal = "總工時"; -$lang->report->bugTotal = "共%s個Bug"; - -$lang->report->proVersion = '更多精彩,盡在專業版!'; + + * @package report + * @version $Id: zh-tw.php 3381 2012-08-09 09:25:12Z zhujinyonging@gmail.com $ + * @link http://www.zentao.net + */ +$lang->report->common = '統計視圖'; +$lang->report->index = '統計首頁'; +$lang->report->list = '統計報表'; +$lang->report->item = '條目'; +$lang->report->value = '值'; +$lang->report->percent = '百分比'; +$lang->report->undefined = '未設定'; +$lang->report->time = '時間'; + +$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'; + +$lang->report->projectDeviation = '項目偏差報表'; +$lang->report->productInfo = '產品信息統計表'; +$lang->report->bugSummary = 'Bug彙總表'; +$lang->report->bugAssign = 'Bug指派表'; +$lang->report->workload = '員工負載表'; + +$lang->reportList->project->lists[10] = '項目偏差報表|report|projectdeviation'; +$lang->reportList->product->lists[10] = '產品信息統計表|report|productinfo'; +$lang->reportList->test->lists[10] = 'Bug彙總表|report|bugsummary'; +$lang->reportList->test->lists[13] = 'Bug指派表|report|bugassign'; +$lang->reportList->staff->lists[10] = '員工負載表|report|workload'; + +$lang->report->id = '編號'; +$lang->report->project = '項目'; +$lang->report->product = '產品'; +$lang->report->user = '姓名'; +$lang->report->bug = 'Bug'; +$lang->report->task = '任務數'; +$lang->report->estimate = '總預計'; +$lang->report->consumed = '總消耗'; +$lang->report->remain = '剩餘工時'; +$lang->report->manhour = '工時'; +$lang->report->deviation = '偏差'; +$lang->report->deviationRate = '偏差率'; +$lang->report->stories = '需求數'; +$lang->report->bugs = 'Bug數'; +$lang->report->devConsumed = '開發時間'; +$lang->report->testConsumed = '測試時間'; +$lang->report->devTestRate = '開發/測試'; +$lang->report->details = '詳情'; +$lang->report->total = '總計'; +$lang->report->to = '至'; +$lang->report->taskTotal = "總任務數"; +$lang->report->manhourTotal = "總工時"; +$lang->report->bugTotal = "共%s個Bug"; + +$lang->report->proVersion = '更多精彩,盡在專業版!'; diff --git a/module/report/model.php b/module/report/model.php index 11f7429b55..bf9397022c 100644 --- a/module/report/model.php +++ b/module/report/model.php @@ -1,461 +1,461 @@ - - * @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, $flotJSON, $count, $width = 'auto', $height = 500) - { - $this->app->loadLang('project'); - $this->app->loadConfig('project'); - $jsRoot = $this->app->getWebRoot() . 'js/'; - $width = $width . 'px'; - $height = $height . 'px'; - $maxDays = $this->config->project->maxBurnDay; - - $dataJSON = $flotJSON['data']; - $limitJSON = $flotJSON['limit']; - $reflineJSON = $flotJSON['refline']; -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; - } - - /** - * Get projects. - * - * @access public - * @return void - */ - public function getProjects() - { - $projects = array(); - - $tasks = $this->dao->select('t1.*') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.status')->ne('cancel') - ->andWhere('t1.deleted')->eq(0) - ->andWhere('t2.deleted')->eq(0) - ->fetchAll(); - foreach($tasks as $task) - { - if(!isset($projects[$task->project])) $projects[$task->project] = new stdclass(); - - $projects[$task->project]->estimate = isset($projects[$task->project]->estimate) ? $projects[$task->project]->estimate + $task->estimate : $task->estimate; - $projects[$task->project]->consumed = isset($projects[$task->project]->consumed) ? $projects[$task->project]->consumed + $task->consumed : $task->consumed; - $projects[$task->project]->tasks = isset($projects[$task->project]->tasks) ? $projects[$task->project]->tasks + 1 : 1; - if($task->type == 'devel') $projects[$task->project]->devConsumed = isset($projects[$task->project]->devConsumed) ? $projects[$task->project]->devConsumed + $task->consumed : $task->consumed; - if($task->type == 'test') $projects[$task->project]->testConsumed = isset($projects[$task->project]->testConsumed) ? $projects[$task->project]->testConsumed + $task->consumed : $task->consumed; - } - - $bugs = $this->dao->select('t1.project') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.deleted')->eq(0) - ->andWhere('t2.deleted')->eq(0) - ->fetchAll(); - foreach($bugs as $bug) - { - if($bug->project) - { - $projects[$bug->project]->bugs = isset($projects[$bug->project]->bugs) ? $projects[$bug->project]->bugs + 1 : 1; - } - } - - $stories = $this->dao->select('t1.project') - ->from(TABLE_PROJECTSTORY)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->leftJoin(TABLE_STORY)->alias('t3') - ->on('t1.story = t3.id') - ->where('t2.deleted')->eq(0) - ->andWhere('t3.deleted')->eq(0) - ->fetchAll(); - foreach($stories as $story) - { - if(!isset($projects[$story->project])) $projects[$story->project] = new stdclass(); - - $projects[$story->project]->stories = isset($projects[$story->project]->stories) ? $projects[$story->project]->stories + 1 : 1; - } - - $projectList = $this->dao->select('id, name, status')->from(TABLE_PROJECT)->fetchAll(); - $projectPairs = array(); - foreach($projectList as $project) - { - $projectPairs[$project->id] = $project->name; - if($project->status != 'done') unset($projects[$project->id]); - } - foreach($projects as $id => $project) - { - if(!isset($projectPairs[$id])) - { - unset($projects[$id]); - continue; - } - if(!isset($project->stories)) $projects[$id]->stories = 0; - if(!isset($project->bugs)) $projects[$id]->bugs = 0; - if(!isset($project->devConsumed)) $projects[$id]->devConsumed = 0; - if(!isset($project->testConsumed)) $projects[$id]->testConsumed = 0; - if(!isset($project->consumed)) $projects[$id]->consumed = 0; - if(!isset($project->estimate)) $projects[$id]->estimate = 0; - $projects[$id]->name = $projectPairs[$id]; - } - return $projects; - } - - /** - * Get products. - * - * @access public - * @return array - */ - public function getProducts() - { - $products = $this->dao->select('id, code, name, PO')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchAll('id'); - $plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('deleted')->eq(0)->andWhere('product')->in(array_keys($products))->fetchAll('id'); - if(!$plans) return array(); - foreach($plans as $plan) $products[$plan->product]->plans[$plan->id] = $plan; - - $planStories = $this->dao->select('plan, id, status')->from(TABLE_STORY)->where('deleted')->eq(0)->andWhere('plan')->in(array_keys($plans))->fetchGroup('plan', 'id'); - foreach($planStories as $planID => $stories) - { - foreach($stories as $story) - { - $plan = $plans[$story->plan]; - $products[$plan->product]->plans[$story->plan]->status[$story->status] = isset($products[$plan->product]->plans[$story->plan]->status[$story->status]) ? $products[$plan->product]->plans[$story->plan]->status[$story->status] + 1 : 1; - } - } - return $products; - } - - /** - * Get bugs - * - * @param int $begin - * @param int $end - * @access public - * @return array - */ - public function getBugs($begin, $end) - { - $end = date('Ymd', strtotime("$end +1 day")); - $bugs = $this->dao->select('id, resolution, openedBy')->from(TABLE_BUG) - ->where('deleted')->eq(0) - ->andWhere('openedDate')->ge($begin) - ->andWhere('openedDate')->le($end) - ->fetchAll(); - $bugSummary = array(); - foreach($bugs as $bug) - { - $bugSummary[$bug->openedBy][$bug->resolution] = empty($bugSummary[$bug->openedBy][$bug->resolution]) ? 1 : $bugSummary[$bug->openedBy][$bug->resolution] + 1; - $bugSummary[$bug->openedBy]['all'] = empty($bugSummary[$bug->openedBy]['all']) ? 1 : $bugSummary[$bug->openedBy]['all'] + 1; - } - return $bugSummary; - } - - /** - * Get workload. - * - * @access public - * @return array - */ - public function getWorkload() - { - $tasks = $this->dao->select('t1.*, t2.name as projectName') - ->from(TABLE_TASK)->alias('t1') - ->leftJoin(TABLE_PROJECT)->alias('t2') - ->on('t1.project = t2.id') - ->where('t1.deleted')->eq(0) - ->andWhere('t1.status')->notin('cancel, closed, done') - ->andWhere('t2.deleted')->eq(0) - ->fetchGroup('assignedTo'); - $workload = array(); - foreach($tasks as $user => $userTasks) - { - if($user) - { - foreach($userTasks as $task) - { - $workload[$user]['task'][$task->projectName]['count'] = isset($workload[$user]['task'][$task->projectName]['count']) ? $workload[$user]['task'][$task->projectName]['count'] + 1 : 1; - $workload[$user]['task'][$task->projectName]['manhour'] = isset($workload[$user]['task'][$task->projectName]['manhour']) ? $workload[$user]['task'][$task->projectName]['manhour'] + $task->left : $task->left; - $workload[$user]['total']['count'] = isset($workload[$user]['total']['count']) ? $workload[$user]['total']['count'] + 1 : 1; - $workload[$user]['total']['manhour'] = isset($workload[$user]['total']['manhour']) ? $workload[$user]['total']['manhour'] + $task->left : $task->left; - } - } - } - unset($workload['closed']); - return $workload; - } - - /** - * Get bug assign. - * - * @access public - * @return array - */ - public function getBugAssign() - { - $bugs = $this->dao->select('t1.*, t2.name as productName') - ->from(TABLE_BUG)->alias('t1') - ->leftJoin(TABLE_PRODUCT)->alias('t2') - ->on('t1.product = t2.id') - ->where('t1.deleted')->eq(0) - ->andWhere('t1.status')->eq('active') - ->andWhere('t2.deleted')->eq(0) - ->fetchGroup('assignedTo'); - $assign = array(); - foreach($bugs as $user => $userBugs) - { - if($user) - { - foreach($userBugs as $bug) - { - $assign[$user]['bug'][$bug->productName]['count'] = isset($assign[$user]['bug'][$bug->productName]['count']) ? $assign[$user]['bug'][$bug->productName]['count'] + 1 : 1; - $assign[$user]['total']['count'] = isset($assign[$user]['total']['count']) ? $assign[$user]['total']['count'] + 1 : 1; - } - } - } - unset($assign['closed']); - return $assign; - } -} + + * @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, $flotJSON, $count, $width = 'auto', $height = 500) + { + $this->app->loadLang('project'); + $this->app->loadConfig('project'); + $jsRoot = $this->app->getWebRoot() . 'js/'; + $width = $width . 'px'; + $height = $height . 'px'; + $maxDays = $this->config->project->maxBurnDay; + + $dataJSON = $flotJSON['data']; + $limitJSON = $flotJSON['limit']; + $reflineJSON = $flotJSON['refline']; +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; + } + + /** + * Get projects. + * + * @access public + * @return void + */ + public function getProjects() + { + $projects = array(); + + $tasks = $this->dao->select('t1.*') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.status')->ne('cancel') + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->fetchAll(); + foreach($tasks as $task) + { + if(!isset($projects[$task->project])) $projects[$task->project] = new stdclass(); + + $projects[$task->project]->estimate = isset($projects[$task->project]->estimate) ? $projects[$task->project]->estimate + $task->estimate : $task->estimate; + $projects[$task->project]->consumed = isset($projects[$task->project]->consumed) ? $projects[$task->project]->consumed + $task->consumed : $task->consumed; + $projects[$task->project]->tasks = isset($projects[$task->project]->tasks) ? $projects[$task->project]->tasks + 1 : 1; + if($task->type == 'devel') $projects[$task->project]->devConsumed = isset($projects[$task->project]->devConsumed) ? $projects[$task->project]->devConsumed + $task->consumed : $task->consumed; + if($task->type == 'test') $projects[$task->project]->testConsumed = isset($projects[$task->project]->testConsumed) ? $projects[$task->project]->testConsumed + $task->consumed : $task->consumed; + } + + $bugs = $this->dao->select('t1.project') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->fetchAll(); + foreach($bugs as $bug) + { + if($bug->project) + { + $projects[$bug->project]->bugs = isset($projects[$bug->project]->bugs) ? $projects[$bug->project]->bugs + 1 : 1; + } + } + + $stories = $this->dao->select('t1.project') + ->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->leftJoin(TABLE_STORY)->alias('t3') + ->on('t1.story = t3.id') + ->where('t2.deleted')->eq(0) + ->andWhere('t3.deleted')->eq(0) + ->fetchAll(); + foreach($stories as $story) + { + if(!isset($projects[$story->project])) $projects[$story->project] = new stdclass(); + + $projects[$story->project]->stories = isset($projects[$story->project]->stories) ? $projects[$story->project]->stories + 1 : 1; + } + + $projectList = $this->dao->select('id, name, status')->from(TABLE_PROJECT)->fetchAll(); + $projectPairs = array(); + foreach($projectList as $project) + { + $projectPairs[$project->id] = $project->name; + if($project->status != 'done') unset($projects[$project->id]); + } + foreach($projects as $id => $project) + { + if(!isset($projectPairs[$id])) + { + unset($projects[$id]); + continue; + } + if(!isset($project->stories)) $projects[$id]->stories = 0; + if(!isset($project->bugs)) $projects[$id]->bugs = 0; + if(!isset($project->devConsumed)) $projects[$id]->devConsumed = 0; + if(!isset($project->testConsumed)) $projects[$id]->testConsumed = 0; + if(!isset($project->consumed)) $projects[$id]->consumed = 0; + if(!isset($project->estimate)) $projects[$id]->estimate = 0; + $projects[$id]->name = $projectPairs[$id]; + } + return $projects; + } + + /** + * Get products. + * + * @access public + * @return array + */ + public function getProducts() + { + $products = $this->dao->select('id, code, name, PO')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->fetchAll('id'); + $plans = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('deleted')->eq(0)->andWhere('product')->in(array_keys($products))->fetchAll('id'); + if(!$plans) return array(); + foreach($plans as $plan) $products[$plan->product]->plans[$plan->id] = $plan; + + $planStories = $this->dao->select('plan, id, status')->from(TABLE_STORY)->where('deleted')->eq(0)->andWhere('plan')->in(array_keys($plans))->fetchGroup('plan', 'id'); + foreach($planStories as $planID => $stories) + { + foreach($stories as $story) + { + $plan = $plans[$story->plan]; + $products[$plan->product]->plans[$story->plan]->status[$story->status] = isset($products[$plan->product]->plans[$story->plan]->status[$story->status]) ? $products[$plan->product]->plans[$story->plan]->status[$story->status] + 1 : 1; + } + } + return $products; + } + + /** + * Get bugs + * + * @param int $begin + * @param int $end + * @access public + * @return array + */ + public function getBugs($begin, $end) + { + $end = date('Ymd', strtotime("$end +1 day")); + $bugs = $this->dao->select('id, resolution, openedBy')->from(TABLE_BUG) + ->where('deleted')->eq(0) + ->andWhere('openedDate')->ge($begin) + ->andWhere('openedDate')->le($end) + ->fetchAll(); + $bugSummary = array(); + foreach($bugs as $bug) + { + $bugSummary[$bug->openedBy][$bug->resolution] = empty($bugSummary[$bug->openedBy][$bug->resolution]) ? 1 : $bugSummary[$bug->openedBy][$bug->resolution] + 1; + $bugSummary[$bug->openedBy]['all'] = empty($bugSummary[$bug->openedBy]['all']) ? 1 : $bugSummary[$bug->openedBy]['all'] + 1; + } + return $bugSummary; + } + + /** + * Get workload. + * + * @access public + * @return array + */ + public function getWorkload() + { + $tasks = $this->dao->select('t1.*, t2.name as projectName') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_PROJECT)->alias('t2') + ->on('t1.project = t2.id') + ->where('t1.deleted')->eq(0) + ->andWhere('t1.status')->notin('cancel, closed, done') + ->andWhere('t2.deleted')->eq(0) + ->fetchGroup('assignedTo'); + $workload = array(); + foreach($tasks as $user => $userTasks) + { + if($user) + { + foreach($userTasks as $task) + { + $workload[$user]['task'][$task->projectName]['count'] = isset($workload[$user]['task'][$task->projectName]['count']) ? $workload[$user]['task'][$task->projectName]['count'] + 1 : 1; + $workload[$user]['task'][$task->projectName]['manhour'] = isset($workload[$user]['task'][$task->projectName]['manhour']) ? $workload[$user]['task'][$task->projectName]['manhour'] + $task->left : $task->left; + $workload[$user]['total']['count'] = isset($workload[$user]['total']['count']) ? $workload[$user]['total']['count'] + 1 : 1; + $workload[$user]['total']['manhour'] = isset($workload[$user]['total']['manhour']) ? $workload[$user]['total']['manhour'] + $task->left : $task->left; + } + } + } + unset($workload['closed']); + return $workload; + } + + /** + * Get bug assign. + * + * @access public + * @return array + */ + public function getBugAssign() + { + $bugs = $this->dao->select('t1.*, t2.name as productName') + ->from(TABLE_BUG)->alias('t1') + ->leftJoin(TABLE_PRODUCT)->alias('t2') + ->on('t1.product = t2.id') + ->where('t1.deleted')->eq(0) + ->andWhere('t1.status')->eq('active') + ->andWhere('t2.deleted')->eq(0) + ->fetchGroup('assignedTo'); + $assign = array(); + foreach($bugs as $user => $userBugs) + { + if($user) + { + foreach($userBugs as $bug) + { + $assign[$user]['bug'][$bug->productName]['count'] = isset($assign[$user]['bug'][$bug->productName]['count']) ? $assign[$user]['bug'][$bug->productName]['count'] + 1 : 1; + $assign[$user]['total']['count'] = isset($assign[$user]['total']['count']) ? $assign[$user]['total']['count'] + 1 : 1; + } + } + } + unset($assign['closed']); + return $assign; + } +} diff --git a/module/search/control.php b/module/search/control.php index 2e20fb5e32..02c5177b07 100644 --- a/module/search/control.php +++ b/module/search/control.php @@ -1,81 +1,81 @@ - - * @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) - { - $queryID = (empty($module) and empty($queryID)) ? $this->session->searchParams['queryID'] : $queryID; - $module = empty($module) ? $this->session->searchParams['module'] : $module; - $searchFields = empty($searchFields) ? json_decode($this->session->searchParams['searchFields'], true) : $searchFields; - $fieldParams = empty($fieldParams) ? json_decode($this->session->searchParams['fieldParams'], true) : $fieldParams; - $actionURL = empty($actionURL) ? $this->session->searchParams['actionURL'] : $actionURL; - $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')); - } -} + + * @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) + { + $queryID = (empty($module) and empty($queryID)) ? $this->session->searchParams['queryID'] : $queryID; + $module = empty($module) ? $this->session->searchParams['module'] : $module; + $searchFields = empty($searchFields) ? json_decode($this->session->searchParams['searchFields'], true) : $searchFields; + $fieldParams = empty($fieldParams) ? json_decode($this->session->searchParams['fieldParams'], true) : $fieldParams; + $actionURL = empty($actionURL) ? $this->session->searchParams['actionURL'] : $actionURL; + $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')); + } +} diff --git a/module/search/lang/en.php b/module/search/lang/en.php index fa72f4b200..7b924dbf9d 100644 --- a/module/search/lang/en.php +++ b/module/search/lang/en.php @@ -1,51 +1,51 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->search = new stdclass(); -$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->me = 'Me'; - -$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['between'] = 'between'; -$lang->search->operators['notinclude'] = 'not include'; -$lang->search->operators['belong'] = 'belongs to'; - -$lang->search->andor['and'] = 'And'; -$lang->search->andor['or'] = 'Or'; - -$lang->search->null = 'Null'; - -$lang->userquery = new stdclass(); -$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 = new stdclass(); +$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->me = 'Me'; + +$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['between'] = 'between'; +$lang->search->operators['notinclude'] = 'not include'; +$lang->search->operators['belong'] = 'belongs to'; + +$lang->search->andor['and'] = 'And'; +$lang->search->andor['or'] = 'Or'; + +$lang->search->null = 'Null'; + +$lang->userquery = new stdclass(); +$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 f4f9a47534..623381d70d 100644 --- a/module/search/lang/zh-cn.php +++ b/module/search/lang/zh-cn.php @@ -1,51 +1,51 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->search = new stdclass(); -$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->me = '自己'; - -$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['between'] = '介于'; -$lang->search->operators['notinclude'] = '不包含'; -$lang->search->operators['belong'] = '从属于'; - -$lang->search->andor['and'] = '并且'; -$lang->search->andor['or'] = '或者'; - -$lang->search->null = '空'; - -$lang->userquery = new stdclass(); -$lang->userquery->title = '查询标题'; -$lang->userquery->myQueries = '我的查询'; -$lang->userquery->execut = '执行'; -$lang->userquery->delete = '删除'; + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->search = new stdclass(); +$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->me = '自己'; + +$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['between'] = '介于'; +$lang->search->operators['notinclude'] = '不包含'; +$lang->search->operators['belong'] = '从属于'; + +$lang->search->andor['and'] = '并且'; +$lang->search->andor['or'] = '或者'; + +$lang->search->null = '空'; + +$lang->userquery = new stdclass(); +$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 26823e497d..53c49d92d2 100644 --- a/module/search/lang/zh-tw.php +++ b/module/search/lang/zh-tw.php @@ -1,51 +1,51 @@ - - * @package search - * @version $Id: zh-tw.php 3838 2012-12-18 07:41:23Z zhujinyonging@gmail.com $ - * @link http://www.zentao.net - */ -$lang->search = new stdclass(); -$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->me = '自己'; - -$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['between'] = '介於'; -$lang->search->operators['notinclude'] = '不包含'; -$lang->search->operators['belong'] = '從屬於'; - -$lang->search->andor['and'] = '並且'; -$lang->search->andor['or'] = '或者'; - -$lang->search->null = '空'; - -$lang->userquery = new stdclass(); -$lang->userquery->title = '查詢標題'; -$lang->userquery->myQueries = '我的查詢'; -$lang->userquery->execut = '執行'; -$lang->userquery->delete = '刪除'; + + * @package search + * @version $Id: zh-tw.php 3838 2012-12-18 07:41:23Z zhujinyonging@gmail.com $ + * @link http://www.zentao.net + */ +$lang->search = new stdclass(); +$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->me = '自己'; + +$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['between'] = '介於'; +$lang->search->operators['notinclude'] = '不包含'; +$lang->search->operators['belong'] = '從屬於'; + +$lang->search->andor['and'] = '並且'; +$lang->search->andor['or'] = '或者'; + +$lang->search->null = '空'; + +$lang->userquery = new stdclass(); +$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 84395962a2..77153829b0 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -1,351 +1,351 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -?> -session->set('searchParams', $searchParams); - } - - /** - * Build the query to execute. - * - * @access public - * @return void - */ - public function buildQuery() - { - /* Init vars. */ - $where = ''; - $groupItems = $this->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 values. */ - 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%"); - } - elseif($operator == 'belong') - { - if($this->post->$fieldName == 'module') - { - $allModules = $this->loadModel('tree')->getAllChildId($value); - $where .= helper::dbIN($allModules); - } - elseif($this->post->$fieldName == 'dept') - { - $allDepts = $this->loadModel('dept')->getAllChildId($value); - $where .= helper::dbIN($allDepts); - } - else - { - $where .= ' = ' . $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) - { - $hasProduct = false; - $hasProject = false; - $hasUser = false; - - $fields = array_keys($fields); - foreach($fields as $fieldName) - { - if(empty($params[$fieldName])) continue; - if($params[$fieldName]['values'] == 'products') $hasProduct = true; - if($params[$fieldName]['values'] == 'users') $hasUser = true; - if($params[$fieldName]['values'] == 'projects') $hasProject = true; - } - - if($hasUser) - { - $users = $this->loadModel('user')->getPairs(); - $users['$@me'] = $this->lang->search->me; - } - if($hasProduct) $products = array('' => '') + $this->loadModel('product')->getPairs(); - if($hasProject) $projects = array('' => '') + $this->loadModel('project')->getPairs(); - - 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); - $query->sql = $this->replaceDynamic($query->sql); - 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 public - * @return array - */ - public 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; - } - - /** - Replace dynamic account and date. - * - * @param string $query - * @access public - * @return string - */ - public function replaceDynamic($query) - { - $this->app->loadClass('date'); - $lastWeek = date::getLastWeek(); - $thisWeek = date::getThisWeek(); - $lastMonth = date::getLastMonth(); - $thisMonth = date::getThisMonth(); - $yesterday = date::yesterday(); - $today = date::today(); - if(strpos($query, '$') !== false) - { - $query = str_replace('$@me', $this->app->user->account, $query); - $query = str_replace("'\$lastMonth'", "'" . $lastMonth['begin'] . "' and '" . $lastMonth['end'] . "'", $query); - $query = str_replace("'\$thisMonth'", "'" . $thisMonth['begin'] . "' and '" . $thisMonth['end'] . "'", $query); - $query = str_replace("'\$lastWeek'", "'" . $lastWeek['begin'] . "' and '" . $lastWeek['end'] . "'", $query); - $query = str_replace("'\$thisWeek'", "'" . $thisWeek['begin'] . "' and '" . $thisWeek['end'] . "'", $query); - $query = str_replace("'\$yesterday'", "'" . $yesterday . "' and '" . $yesterday . "'", $query); - $query = str_replace("'\$today'", "'" . $today . "' and '" . $today . "'", $query); - } - return $query; - } -} + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +?> +session->set('searchParams', $searchParams); + } + + /** + * Build the query to execute. + * + * @access public + * @return void + */ + public function buildQuery() + { + /* Init vars. */ + $where = ''; + $groupItems = $this->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 values. */ + 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%"); + } + elseif($operator == 'belong') + { + if($this->post->$fieldName == 'module') + { + $allModules = $this->loadModel('tree')->getAllChildId($value); + $where .= helper::dbIN($allModules); + } + elseif($this->post->$fieldName == 'dept') + { + $allDepts = $this->loadModel('dept')->getAllChildId($value); + $where .= helper::dbIN($allDepts); + } + else + { + $where .= ' = ' . $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) + { + $hasProduct = false; + $hasProject = false; + $hasUser = false; + + $fields = array_keys($fields); + foreach($fields as $fieldName) + { + if(empty($params[$fieldName])) continue; + if($params[$fieldName]['values'] == 'products') $hasProduct = true; + if($params[$fieldName]['values'] == 'users') $hasUser = true; + if($params[$fieldName]['values'] == 'projects') $hasProject = true; + } + + if($hasUser) + { + $users = $this->loadModel('user')->getPairs(); + $users['$@me'] = $this->lang->search->me; + } + if($hasProduct) $products = array('' => '') + $this->loadModel('product')->getPairs(); + if($hasProject) $projects = array('' => '') + $this->loadModel('project')->getPairs(); + + 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); + $query->sql = $this->replaceDynamic($query->sql); + 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 public + * @return array + */ + public 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; + } + + /** + Replace dynamic account and date. + * + * @param string $query + * @access public + * @return string + */ + public function replaceDynamic($query) + { + $this->app->loadClass('date'); + $lastWeek = date::getLastWeek(); + $thisWeek = date::getThisWeek(); + $lastMonth = date::getLastMonth(); + $thisMonth = date::getThisMonth(); + $yesterday = date::yesterday(); + $today = date::today(); + if(strpos($query, '$') !== false) + { + $query = str_replace('$@me', $this->app->user->account, $query); + $query = str_replace("'\$lastMonth'", "'" . $lastMonth['begin'] . "' and '" . $lastMonth['end'] . "'", $query); + $query = str_replace("'\$thisMonth'", "'" . $thisMonth['begin'] . "' and '" . $thisMonth['end'] . "'", $query); + $query = str_replace("'\$lastWeek'", "'" . $lastWeek['begin'] . "' and '" . $lastWeek['end'] . "'", $query); + $query = str_replace("'\$thisWeek'", "'" . $thisWeek['begin'] . "' and '" . $thisWeek['end'] . "'", $query); + $query = str_replace("'\$yesterday'", "'" . $yesterday . "' and '" . $yesterday . "'", $query); + $query = str_replace("'\$today'", "'" . $today . "' and '" . $today . "'", $query); + } + return $query; + } +} diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php index 88969f8a11..d7bc0ce8be 100644 --- a/module/search/view/buildform.html.php +++ b/module/search/view/buildform.html.php @@ -1,312 +1,312 @@ - - * @package search - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
          ' target='hiddenwin' id='searchform'> - - - - - - - - - - -
            - - 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 searchSelect'"); - if($param['control'] == 'input') - { - $fieldName = $formSession["field$fieldNO"]; - $extraClass = isset($param['class']) ? $param['class'] : ''; - echo html::input("value$fieldNO", $formSession["value$fieldNO"], "class='text-2 $extraClass searchInput'"); - } - 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 searchSelect'"); - - if($param['control'] == 'input') - { - $fieldName = $formSession["field$fieldNO"]; - $extraClass = isset($param['class']) ? $param['class'] : ''; - echo html::input("value$fieldNO", $formSession["value$fieldNO"], "class='text-2 $extraClass searchInput'"); - } - echo ''; - - $fieldNO ++; - echo ''; - } - ?> -
          -
          - - search->common); - echo html::commonButton($lang->search->reset, 'onclick=resetForm();'); - echo html::commonButton($lang->save, 'onclick=saveQuery()'); - ?> - - - - -   - - -
          -
          - + + * @package search + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
          ' target='hiddenwin' id='searchform'> + + + + + + + + + + +
            + + 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 searchSelect'"); + if($param['control'] == 'input') + { + $fieldName = $formSession["field$fieldNO"]; + $extraClass = isset($param['class']) ? $param['class'] : ''; + echo html::input("value$fieldNO", $formSession["value$fieldNO"], "class='text-2 $extraClass searchInput'"); + } + 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 searchSelect'"); + + if($param['control'] == 'input') + { + $fieldName = $formSession["field$fieldNO"]; + $extraClass = isset($param['class']) ? $param['class'] : ''; + echo html::input("value$fieldNO", $formSession["value$fieldNO"], "class='text-2 $extraClass searchInput'"); + } + echo ''; + + $fieldNO ++; + echo ''; + } + ?> +
          +
          + + search->common); + echo html::commonButton($lang->search->reset, 'onclick=resetForm();'); + echo html::commonButton($lang->save, 'onclick=saveQuery()'); + ?> + + + + +   + + +
          +
          + diff --git a/module/setting/model.php b/module/setting/model.php index 3a73e3cfe0..c7f3552295 100644 --- a/module/setting/model.php +++ b/module/setting/model.php @@ -1,261 +1,261 @@ - - * @package setting - * @version $Id$ - * @link http://www.zentao.net - */ -?> -createDAO($this->parseItemParam($paramString), 'select')->fetch('value', $autoCompany = false); - } - - /** - * Get some items. - * - * @param string $paramString see parseItemParam(); - * @access public - * @return array - */ - public function getItems($paramString) - { - return $this->createDAO($this->parseItemParam($paramString), 'select')->fetchAll('id', $autoCompany = false); - } - - /** - * Set value of an item. - * - * @param string $path system.common.global.sn or system.common.sn - * @param string $value - * @param string|int $company - * @access public - * @return void - */ - public function setItem($path, $value = '', $company = 'current') - { - $level = substr_count($path, '.'); - $section = ''; - - if($level <= 1) return false; - if($level == 2) list($owner, $module, $key) = explode('.', $path); - if($level == 3) list($owner, $module, $section, $key) = explode('.', $path); - - $item = new stdclass(); - $item->company = $company === 'current' ? $this->app->company->id : $company; - $item->owner = $owner; - $item->module = $module; - $item->section = $section; - $item->key = $key; - $item->value = $value; - - $this->dao->replace(TABLE_CONFIG)->data($item)->exec($autoCompany = false); - } - - /** - * Batch set items, the example: - * - * $path = 'system.mail'; - * $items->turnon = true; - * $items->smtp->host = 'localhost'; - * - * @param string $path like system.mail - * @param array|object $items the items array or object, can be mixed by one level or two levels. - * @access public - * @return bool - */ - public function setItems($path, $items, $company = 'current') - { - foreach($items as $key => $item) - { - if(is_array($item) or is_object($item)) - { - $section = $key; - foreach($item as $subKey => $subItem) - { - $this->setItem($path . '.' . $section . '.' . $subKey, $subItem); - } - } - else - { - $this->setItem($path . '.' . $key, $item); - } - } - - if(!dao::isError()) return true; - return false; - } - - /** - * Delete items. - * - * @param string $paramString see parseItemParam(); - * @access public - * @return void - */ - public function deleteItems($paramString) - { - $this->createDAO($this->parseItemParam($paramString), 'delete')->exec(); - } - - /** - * Parse the param string for select or delete items. - * - * @param string $paramString owner=xxx&company=1,2&key=sn and so on. - * @access public - * @return array - */ - public function parseItemParam($paramString) - { - /* Parse the param string into array. */ - parse_str($paramString, $params); - - /* Init fields not set in the param string. */ - $fields = 'company,owner,module,section,key'; - $fields = explode(',', $fields); - foreach($fields as $field) if(!isset($params[$field])) $params[$field] = ''; - - /* If not set company, set as current company. */ - if($params['company'] == '') $params['company'] = $this->app->company->id; - - return $params; - } - - /** - * Create a DAO object to select or delete one or more records. - * - * @param array $params the params parsed by parseItemParam() method. - * @param string $method select|delete. - * @access public - * @return object - */ - public function createDAO($params, $method = 'select') - { - return $this->dao->$method('*')->from(TABLE_CONFIG)->where('1 = 1') - ->beginIF($params['company'])->andWhere('company')->in($params['company'])->fi() - ->beginIF($params['owner'])->andWhere('owner')->in($params['owner'])->fi() - ->beginIF($params['module'])->andWhere('module')->in($params['module'])->fi() - ->beginIF($params['section'])->andWhere('section')->in($params['section'])->fi() - ->beginIF($params['key'])->andWhere('`key`')->in($params['key'])->fi(); - } - - /** - * Get config of system and one user. - * - * @param string $account - * @access public - * @return array - */ - public function getSysAndPersonalConfig($account = '') - { - $company = $this->app->company->id . ',' . '0'; // Get settings of current company, and also settings for all company. - $owner = 'system,' . ($account ? $account : ''); - $records = $this->dao->select('*')->from(TABLE_CONFIG) - ->where('owner')->in($owner) - ->andWhere('company')->in($company) - ->orderBy('id') - ->fetchAll('id', false); - if(!$records) return array(); - - /* Group records by owner and module. */ - $config = array(); - foreach($records as $record) - { - if(!isset($record->module)) return array(); // If no module field, return directly. Since 3.2 version, there's the module field. - - if($record->section) $config[$record->owner]->{$record->module}[] = $record; - if(!$record->section) $config[$record->owner]->{$record->module}[] = $record; - } - return $config; - } - - //-------------------------------- methods for version and sn. ----------------------------// - - /** - * Get the version of current zentaopms. - * - * Since the version field not saved in db. So if empty, return 0.3 beta. - * - * @access public - * @return void - */ - public function getVersion() - { - $version = isset($this->config->global->version) ? $this->config->global->version : '0.3.beta'; // No version, set as 0.3.beta. - if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0. - return $version; - } - - /** - * Update version - * - * @param string $version - * @access public - * @return void - */ - public function updateVersion($version) - { - return $this->setItem('system.common.global.version', $version, 0); - } - - /** - * Set the sn of current zentaopms. - * - * @access public - * @return void - */ - public function setSN() - { - $sn = $this->getItem('owner=system&module=common§ion=global&key=sn'); - if($this->snNeededUpdate($sn)) $this->setItem('system.common.global.sn', $this->computeSN()); - } - - /** - * 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; - } - - /** - * Judge a sn needed update or not. - * - * @param string $sn - * @access public - * @return bool - */ - public function snNeededUpdate($sn) - { - if($sn == '') return true; - if($sn == '281602d8ff5ee7533eeafd26eda4e776') return true; - if($sn == '9bed3108092c94a0db2b934a46268b4a') return true; - if($sn == '8522dd4d76762a49d02261ddbe4ad432') return true; - if($sn == '13593e340ee2bdffed640d0c4eed8bec') return true; - - return false; - } -} + + * @package setting + * @version $Id$ + * @link http://www.zentao.net + */ +?> +createDAO($this->parseItemParam($paramString), 'select')->fetch('value', $autoCompany = false); + } + + /** + * Get some items. + * + * @param string $paramString see parseItemParam(); + * @access public + * @return array + */ + public function getItems($paramString) + { + return $this->createDAO($this->parseItemParam($paramString), 'select')->fetchAll('id', $autoCompany = false); + } + + /** + * Set value of an item. + * + * @param string $path system.common.global.sn or system.common.sn + * @param string $value + * @param string|int $company + * @access public + * @return void + */ + public function setItem($path, $value = '', $company = 'current') + { + $level = substr_count($path, '.'); + $section = ''; + + if($level <= 1) return false; + if($level == 2) list($owner, $module, $key) = explode('.', $path); + if($level == 3) list($owner, $module, $section, $key) = explode('.', $path); + + $item = new stdclass(); + $item->company = $company === 'current' ? $this->app->company->id : $company; + $item->owner = $owner; + $item->module = $module; + $item->section = $section; + $item->key = $key; + $item->value = $value; + + $this->dao->replace(TABLE_CONFIG)->data($item)->exec($autoCompany = false); + } + + /** + * Batch set items, the example: + * + * $path = 'system.mail'; + * $items->turnon = true; + * $items->smtp->host = 'localhost'; + * + * @param string $path like system.mail + * @param array|object $items the items array or object, can be mixed by one level or two levels. + * @access public + * @return bool + */ + public function setItems($path, $items, $company = 'current') + { + foreach($items as $key => $item) + { + if(is_array($item) or is_object($item)) + { + $section = $key; + foreach($item as $subKey => $subItem) + { + $this->setItem($path . '.' . $section . '.' . $subKey, $subItem); + } + } + else + { + $this->setItem($path . '.' . $key, $item); + } + } + + if(!dao::isError()) return true; + return false; + } + + /** + * Delete items. + * + * @param string $paramString see parseItemParam(); + * @access public + * @return void + */ + public function deleteItems($paramString) + { + $this->createDAO($this->parseItemParam($paramString), 'delete')->exec(); + } + + /** + * Parse the param string for select or delete items. + * + * @param string $paramString owner=xxx&company=1,2&key=sn and so on. + * @access public + * @return array + */ + public function parseItemParam($paramString) + { + /* Parse the param string into array. */ + parse_str($paramString, $params); + + /* Init fields not set in the param string. */ + $fields = 'company,owner,module,section,key'; + $fields = explode(',', $fields); + foreach($fields as $field) if(!isset($params[$field])) $params[$field] = ''; + + /* If not set company, set as current company. */ + if($params['company'] == '') $params['company'] = $this->app->company->id; + + return $params; + } + + /** + * Create a DAO object to select or delete one or more records. + * + * @param array $params the params parsed by parseItemParam() method. + * @param string $method select|delete. + * @access public + * @return object + */ + public function createDAO($params, $method = 'select') + { + return $this->dao->$method('*')->from(TABLE_CONFIG)->where('1 = 1') + ->beginIF($params['company'])->andWhere('company')->in($params['company'])->fi() + ->beginIF($params['owner'])->andWhere('owner')->in($params['owner'])->fi() + ->beginIF($params['module'])->andWhere('module')->in($params['module'])->fi() + ->beginIF($params['section'])->andWhere('section')->in($params['section'])->fi() + ->beginIF($params['key'])->andWhere('`key`')->in($params['key'])->fi(); + } + + /** + * Get config of system and one user. + * + * @param string $account + * @access public + * @return array + */ + public function getSysAndPersonalConfig($account = '') + { + $company = $this->app->company->id . ',' . '0'; // Get settings of current company, and also settings for all company. + $owner = 'system,' . ($account ? $account : ''); + $records = $this->dao->select('*')->from(TABLE_CONFIG) + ->where('owner')->in($owner) + ->andWhere('company')->in($company) + ->orderBy('id') + ->fetchAll('id', false); + if(!$records) return array(); + + /* Group records by owner and module. */ + $config = array(); + foreach($records as $record) + { + if(!isset($record->module)) return array(); // If no module field, return directly. Since 3.2 version, there's the module field. + + if($record->section) $config[$record->owner]->{$record->module}[] = $record; + if(!$record->section) $config[$record->owner]->{$record->module}[] = $record; + } + return $config; + } + + //-------------------------------- methods for version and sn. ----------------------------// + + /** + * Get the version of current zentaopms. + * + * Since the version field not saved in db. So if empty, return 0.3 beta. + * + * @access public + * @return void + */ + public function getVersion() + { + $version = isset($this->config->global->version) ? $this->config->global->version : '0.3.beta'; // No version, set as 0.3.beta. + if($version == '3.0.stable') $version = '3.0'; // convert 3.0.stable to 3.0. + return $version; + } + + /** + * Update version + * + * @param string $version + * @access public + * @return void + */ + public function updateVersion($version) + { + return $this->setItem('system.common.global.version', $version, 0); + } + + /** + * Set the sn of current zentaopms. + * + * @access public + * @return void + */ + public function setSN() + { + $sn = $this->getItem('owner=system&module=common§ion=global&key=sn'); + if($this->snNeededUpdate($sn)) $this->setItem('system.common.global.sn', $this->computeSN()); + } + + /** + * 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; + } + + /** + * Judge a sn needed update or not. + * + * @param string $sn + * @access public + * @return bool + */ + public function snNeededUpdate($sn) + { + if($sn == '') return true; + if($sn == '281602d8ff5ee7533eeafd26eda4e776') return true; + if($sn == '9bed3108092c94a0db2b934a46268b4a') return true; + if($sn == '8522dd4d76762a49d02261ddbe4ad432') return true; + if($sn == '13593e340ee2bdffed640d0c4eed8bec') return true; + + return false; + } +} diff --git a/module/story/control.php b/module/story/control.php index 3ffe853e2c..3b7c6ec07a 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -1,1030 +1,1030 @@ - - * @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('project'); - $this->loadModel('tree'); - $this->loadModel('user'); - $this->loadModel('action'); - } - - /** - * 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())); - if($bugID == 0) - { - $actionID = $this->action->create('story', $storyID, 'Opened', ''); - } - else - { - $actionID = $this->action->create('story', $storyID, 'Frombug', '', $bugID); - } - $this->sendMail($storyID, $actionID); - if($this->post->newStory) - { - echo js::alert($this->lang->story->successSaved . $this->lang->story->newStory); - die(js::locate($this->createLink('story', 'create', "productID=$productID&moduleID=$moduleID&story=0&projectID=$projectID&bugID=$bugID"), 'parent')); - } - 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|pdfirst'); - $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; - if(strpos($oldBug->mailto, $oldBug->openedBy) === false) - { - $mailto = $oldBug->mailto . $oldBug->openedBy . ','; - } - else - { - $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->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); - $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 public - * @return void - */ - public 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|pdfirst'); - $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) - { - 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|pofirst'), $this->view->story->assignedTo); - $this->view->story = $this->story->getById($storyID, 0, true); - $this->display(); - } - - /** - * Batch edit story. - * - * @param string $from productBrowse|projectStory|storyBatchEdit. - * @param int $productID - * @param int $projectID - * @param string $orderBy - * @access public - * @return void - */ - public function batchEdit($from = '', $productID = 0, $projectID = 0, $orderBy = '') - { - /* Get post data for product-Browse or project-Story. */ - if($from == 'productBrowse' or $from == 'projectStory') - { - /* Init vars. */ - $editedStories = array(); - $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); - $columns = 9; - $showSuhosinInfo = false; - - /* Get all stories. */ - if(!$projectID) - { - /* Set menu. */ - $this->product->setMenu($this->product->getPairs('nodeleted'), $productID); - $allStories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition)->orderBy($orderBy)->fetchAll('id'); - } - else - { - $this->lang->story->menu = $this->lang->project->menu; - $this->project->setMenu($this->project->getPairs('nodeleted'), $projectID); - $this->lang->set('menugroup.story', 'project'); - $allStories = $this->story->getProjectStories($projectID, $orderBy); - } - if(!$allStories) $allStories = array(); - - /* Initialize the stories whose need to edited. */ - $moduleOptionMenus = array(); - $productPlans = array(); - $this->loadModel('productplan'); - foreach($allStories as $story) - { - if(in_array($story->id, $storyIDList)) - { - $editedStories[$story->id] = $story; - if(!isset($moduleOptionMenus[$story->product])) - { - $moduleOptionMenus[$story->product] = $this->tree->getOptionMenu($story->product, $viewType = 'story'); - $productPlans[$story->product] = $this->productplan->getPairs($story->product); - } - } - } - - /* Judge whether the editedStories is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedStories), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - if(!$projectID) - { - $product = $this->product->getByID($productID); - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->batchEdit; - } - else - { - $project = $this->project->getByID($projectID); - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->story->batchEdit; - } - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->position[] = $this->lang->story->common; - $this->view->position[] = $this->lang->story->batchEdit; - $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); - $this->view->moduleOptionMenus = $moduleOptionMenus; - $this->view->productPlans = $productPlans; - $this->view->productID = $productID; - $this->view->editedStories = $editedStories; - - $this->display(); - } - /* Get post data for story-batchEdit. */ - elseif($from == 'storyBatchEdit') - { - if(!empty($_POST)) - { - - $allChanges = $this->story->batchUpdate(); - - if($allChanges) - { - foreach($allChanges as $storyID => $changes) - { - $actionID = $this->action->create('story', $storyID, 'Edited'); - $this->action->logHistory($actionID, $changes); - $this->sendMail($storyID, $actionID); - } - } - } - die(js::locate($this->session->storyList, 'parent')); - } - } - - /** - * Change a story. - * - * @param int $storyID - * @access public - * @return void - */ - public function change($storyID) - { - 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) - { - 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) - { - $storyID = (int)$storyID; - $story = $this->story->getById($storyID, $version, true); - 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)->andWhere('deleted')->eq(0)->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)->andWhere('deleted')->eq(0)->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'] = "STORY #$story->id $story->title - $product->name"; - $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('story', $storyID); - $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) - { - 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) - { - if(!empty($_POST)) - { - $changes = $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, $changes); - $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(); - } - - /** - * Batch close story. - * - * @param string $from productBrowse|projectStory|storyBatchClose - * @param int $productID - * @param int $projectID - * @param string $orderBy - * @access public - * @return void - */ - public function batchClose($from = '', $productID = 0, $projectID = 0, $orderBy = '') - { - /* Get post data for product-Browse or project-Story. */ - if($from == 'productBrowse' or $from == 'projectStory') - { - /* Init vars. */ - $editedStories = array(); - $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); - $columns = 4; - $showSuhosinInfo = false; - - /* Get all stories. */ - if(!$projectID) - { - /* Set menu. */ - $this->product->setMenu($this->product->getPairs('nodeleted'), $productID); - $allStories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition)->orderBy($orderBy)->fetchAll('id'); - } - else - { - $this->lang->story->menu = $this->lang->project->menu; - $this->lang->story->menuOrder = $this->lang->project->menuOrder; - $this->project->setMenu($this->project->getPairs('nodeleted'), $projectID); - $this->lang->set('menugroup.story', 'project'); - $allStories = $this->story->getProjectStories($projectID, $orderBy); - } - if(!$allStories) $allStories = array(); - - /* Initialize the stories whose need to edited. */ - foreach($allStories as $story) if(in_array($story->id, $storyIDList)) $editedStories[$story->id] = $story; - - /* Judge whether the editedStories is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedStories), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - if(!$projectID) - { - $product = $this->product->getByID($productID); - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->batchClose; - } - else - { - $project = $this->project->getByID($projectID); - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->story->batchClose; - } - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->position[] = $this->lang->story->common; - $this->view->position[] = $this->lang->story->batchClose; - $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); - $this->view->plans = $this->loadModel('productplan')->getPairs($productID); - $this->view->productID = $productID; - $this->view->editedStories = $editedStories; - - $this->display(); - } - /* Get post data for story-batchClose. */ - elseif($from == 'storyBatchClose') - { - if(!empty($_POST)) - { - - $allChanges = $this->story->batchClose(); - - if($allChanges) - { - foreach($allChanges as $storyID => $changes) - { - $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comments[$storyID], ucfirst($this->post->closedReasons[$storyID])); - $this->action->logHistory($actionID); - $this->sendMail($storyID, $actionID); - } - } - } - die(js::locate($this->session->storyList, 'parent')); - } - } - - /** - * 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 public - * @return void - */ - public function sendmail($storyID, $actionID) - { - $story = $this->story->getById($storyID); - $productName = $this->product->getById($story->product)->name; - - /* Get actions. */ - $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 = $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. */ - if($action->action == 'opened') $action->comment = ''; - $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 = array(); - if($this->session->storyOnlyCondition) - { - $stories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition) - ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() - ->orderBy($orderBy)->fetchAll('id', false); - } - else - { - $stmt = $this->dbh->query($this->session->storyQueryCondition . ($this->post->exportType == 'selected' ? " AND id IN({$this->cookie->checkedItem})" : '') . " ORDER BY " . strtr($orderBy, '_', ' ')); - while($row = $stmt->fetch()) $stories[$row->id] = $row; - } - - /* 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->post->set('kind', 'story'); - $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('project'); + $this->loadModel('tree'); + $this->loadModel('user'); + $this->loadModel('action'); + } + + /** + * 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())); + if($bugID == 0) + { + $actionID = $this->action->create('story', $storyID, 'Opened', ''); + } + else + { + $actionID = $this->action->create('story', $storyID, 'Frombug', '', $bugID); + } + $this->sendMail($storyID, $actionID); + if($this->post->newStory) + { + echo js::alert($this->lang->story->successSaved . $this->lang->story->newStory); + die(js::locate($this->createLink('story', 'create', "productID=$productID&moduleID=$moduleID&story=0&projectID=$projectID&bugID=$bugID"), 'parent')); + } + 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|pdfirst'); + $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; + if(strpos($oldBug->mailto, $oldBug->openedBy) === false) + { + $mailto = $oldBug->mailto . $oldBug->openedBy . ','; + } + else + { + $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->contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); + $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 public + * @return void + */ + public 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|pdfirst'); + $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) + { + 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|pofirst'), $this->view->story->assignedTo); + $this->view->story = $this->story->getById($storyID, 0, true); + $this->display(); + } + + /** + * Batch edit story. + * + * @param string $from productBrowse|projectStory|storyBatchEdit. + * @param int $productID + * @param int $projectID + * @param string $orderBy + * @access public + * @return void + */ + public function batchEdit($from = '', $productID = 0, $projectID = 0, $orderBy = '') + { + /* Get post data for product-Browse or project-Story. */ + if($from == 'productBrowse' or $from == 'projectStory') + { + /* Init vars. */ + $editedStories = array(); + $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); + $columns = 9; + $showSuhosinInfo = false; + + /* Get all stories. */ + if(!$projectID) + { + /* Set menu. */ + $this->product->setMenu($this->product->getPairs('nodeleted'), $productID); + $allStories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition)->orderBy($orderBy)->fetchAll('id'); + } + else + { + $this->lang->story->menu = $this->lang->project->menu; + $this->project->setMenu($this->project->getPairs('nodeleted'), $projectID); + $this->lang->set('menugroup.story', 'project'); + $allStories = $this->story->getProjectStories($projectID, $orderBy); + } + if(!$allStories) $allStories = array(); + + /* Initialize the stories whose need to edited. */ + $moduleOptionMenus = array(); + $productPlans = array(); + $this->loadModel('productplan'); + foreach($allStories as $story) + { + if(in_array($story->id, $storyIDList)) + { + $editedStories[$story->id] = $story; + if(!isset($moduleOptionMenus[$story->product])) + { + $moduleOptionMenus[$story->product] = $this->tree->getOptionMenu($story->product, $viewType = 'story'); + $productPlans[$story->product] = $this->productplan->getPairs($story->product); + } + } + } + + /* Judge whether the editedStories is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedStories), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + if(!$projectID) + { + $product = $this->product->getByID($productID); + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->batchEdit; + } + else + { + $project = $this->project->getByID($projectID); + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->story->batchEdit; + } + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->position[] = $this->lang->story->common; + $this->view->position[] = $this->lang->story->batchEdit; + $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); + $this->view->moduleOptionMenus = $moduleOptionMenus; + $this->view->productPlans = $productPlans; + $this->view->productID = $productID; + $this->view->editedStories = $editedStories; + + $this->display(); + } + /* Get post data for story-batchEdit. */ + elseif($from == 'storyBatchEdit') + { + if(!empty($_POST)) + { + + $allChanges = $this->story->batchUpdate(); + + if($allChanges) + { + foreach($allChanges as $storyID => $changes) + { + $actionID = $this->action->create('story', $storyID, 'Edited'); + $this->action->logHistory($actionID, $changes); + $this->sendMail($storyID, $actionID); + } + } + } + die(js::locate($this->session->storyList, 'parent')); + } + } + + /** + * Change a story. + * + * @param int $storyID + * @access public + * @return void + */ + public function change($storyID) + { + 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) + { + 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) + { + $storyID = (int)$storyID; + $story = $this->story->getById($storyID, $version, true); + 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)->andWhere('deleted')->eq(0)->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)->andWhere('deleted')->eq(0)->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'] = "STORY #$story->id $story->title - $product->name"; + $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('story', $storyID); + $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) + { + 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) + { + if(!empty($_POST)) + { + $changes = $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, $changes); + $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(); + } + + /** + * Batch close story. + * + * @param string $from productBrowse|projectStory|storyBatchClose + * @param int $productID + * @param int $projectID + * @param string $orderBy + * @access public + * @return void + */ + public function batchClose($from = '', $productID = 0, $projectID = 0, $orderBy = '') + { + /* Get post data for product-Browse or project-Story. */ + if($from == 'productBrowse' or $from == 'projectStory') + { + /* Init vars. */ + $editedStories = array(); + $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); + $columns = 4; + $showSuhosinInfo = false; + + /* Get all stories. */ + if(!$projectID) + { + /* Set menu. */ + $this->product->setMenu($this->product->getPairs('nodeleted'), $productID); + $allStories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition)->orderBy($orderBy)->fetchAll('id'); + } + else + { + $this->lang->story->menu = $this->lang->project->menu; + $this->lang->story->menuOrder = $this->lang->project->menuOrder; + $this->project->setMenu($this->project->getPairs('nodeleted'), $projectID); + $this->lang->set('menugroup.story', 'project'); + $allStories = $this->story->getProjectStories($projectID, $orderBy); + } + if(!$allStories) $allStories = array(); + + /* Initialize the stories whose need to edited. */ + foreach($allStories as $story) if(in_array($story->id, $storyIDList)) $editedStories[$story->id] = $story; + + /* Judge whether the editedStories is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedStories), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + if(!$projectID) + { + $product = $this->product->getByID($productID); + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->story->batchClose; + } + else + { + $project = $this->project->getByID($projectID); + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->story->batchClose; + } + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->position[] = $this->lang->story->common; + $this->view->position[] = $this->lang->story->batchClose; + $this->view->users = $this->loadModel('user')->getPairs('nodeleted'); + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'story'); + $this->view->plans = $this->loadModel('productplan')->getPairs($productID); + $this->view->productID = $productID; + $this->view->editedStories = $editedStories; + + $this->display(); + } + /* Get post data for story-batchClose. */ + elseif($from == 'storyBatchClose') + { + if(!empty($_POST)) + { + + $allChanges = $this->story->batchClose(); + + if($allChanges) + { + foreach($allChanges as $storyID => $changes) + { + $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comments[$storyID], ucfirst($this->post->closedReasons[$storyID])); + $this->action->logHistory($actionID); + $this->sendMail($storyID, $actionID); + } + } + } + die(js::locate($this->session->storyList, 'parent')); + } + } + + /** + * 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 public + * @return void + */ + public function sendmail($storyID, $actionID) + { + $story = $this->story->getById($storyID); + $productName = $this->product->getById($story->product)->name; + + /* Get actions. */ + $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 = $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. */ + if($action->action == 'opened') $action->comment = ''; + $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 = array(); + if($this->session->storyOnlyCondition) + { + $stories = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition) + ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() + ->orderBy($orderBy)->fetchAll('id', false); + } + else + { + $stmt = $this->dbh->query($this->session->storyQueryCondition . ($this->post->exportType == 'selected' ? " AND id IN({$this->cookie->checkedItem})" : '') . " ORDER BY " . strtr($orderBy, '_', ' ')); + while($row = $stmt->fetch()) $stories[$row->id] = $row; + } + + /* 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->post->set('kind', 'story'); + $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 1db50cc2a0..ee15c159bc 100644 --- a/module/story/lang/en.php +++ b/module/story/lang/en.php @@ -1,269 +1,269 @@ - - * @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"; -$lang->story->change = "Change"; -$lang->story->changed = 'Changed'; -$lang->story->review = 'Review'; -$lang->story->edit = "Edit"; -$lang->story->batchEdit = "Batch edit"; -$lang->story->close = 'Close'; -$lang->story->batchClose = 'Batch 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->fromBug = 'From bug'; -$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->hour = 'Hour'; -$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->newStory = 'Continue to add story.'; - -$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['customer'] = 'Customer'; -$lang->story->sourceList['user'] = 'User'; -$lang->story->sourceList['po'] = 'Product Owner'; -$lang->story->sourceList['market'] = 'Market'; -$lang->story->sourceList['service'] = 'Customer 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->afterSubmit = "After created"; -$lang->story->successSaved = "Successfully saved"; -$lang->story->confirmDelete = "Are you sure to delete this story?"; -$lang->story->confirmBatchClose = "Are you sure to close those stories?"; -$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->form = new stdclass(); -$lang->story->form->titleNote = 'A word to briefly express story content'; -$lang->story->form->area = 'The story of their respective range'; -$lang->story->form->desc = 'Description and standards, what stories? How to acceptance?'; -$lang->story->form->resource = 'Allocation of resources, who completed? How long does it take?'; -$lang->story->form->file = 'Attachments, if the demand for related documents, please click here to upload.'; - -$lang->story->action = new stdclass(); -$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 = new stdclass(); -$lang->story->report->common = 'Report'; -$lang->story->report->select = 'Select'; -$lang->story->report->create = 'Create'; - -$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 = new stdclass(); -$lang->story->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->story->report->storysPerModule = new stdclass(); -$lang->story->report->storysPerSource = new stdclass(); -$lang->story->report->storysPerPlan = new stdclass(); -$lang->story->report->storysPerStatus = new stdclass(); -$lang->story->report->storysPerStage = new stdclass(); -$lang->story->report->storysPerPri = new stdclass(); -$lang->story->report->storysPerOpenedBy = new stdclass(); -$lang->story->report->storysPerAssignedTo = new stdclass(); -$lang->story->report->storysPerClosedReason = new stdclass(); -$lang->story->report->storysPerEstimate = new stdclass(); -$lang->story->report->storysPerChange = new stdclass(); - -$lang->story->report->storysPerProduct->graph = new stdclass(); -$lang->story->report->storysPerModule->graph = new stdclass(); -$lang->story->report->storysPerSource->graph = new stdclass(); -$lang->story->report->storysPerPlan->graph = new stdclass(); -$lang->story->report->storysPerStatus->graph = new stdclass(); -$lang->story->report->storysPerStage->graph = new stdclass(); -$lang->story->report->storysPerPri->graph = new stdclass(); -$lang->story->report->storysPerOpenedBy->graph = new stdclass(); -$lang->story->report->storysPerAssignedTo->graph = new stdclass(); -$lang->story->report->storysPerClosedReason->graph = new stdclass(); -$lang->story->report->storysPerEstimate->graph = new stdclass(); -$lang->story->report->storysPerChange->graph = new stdclass(); - -$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'; - -$lang->story->placeholder = new stdclass(); -$lang->story->placeholder->estimate = 'Estimate the story point.'; -$lang->story->placeholder->mailto = 'Mail to'; + + * @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"; +$lang->story->change = "Change"; +$lang->story->changed = 'Changed'; +$lang->story->review = 'Review'; +$lang->story->edit = "Edit"; +$lang->story->batchEdit = "Batch edit"; +$lang->story->close = 'Close'; +$lang->story->batchClose = 'Batch 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->fromBug = 'From bug'; +$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->hour = 'Hour'; +$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->newStory = 'Continue to add story.'; + +$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['customer'] = 'Customer'; +$lang->story->sourceList['user'] = 'User'; +$lang->story->sourceList['po'] = 'Product Owner'; +$lang->story->sourceList['market'] = 'Market'; +$lang->story->sourceList['service'] = 'Customer 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->afterSubmit = "After created"; +$lang->story->successSaved = "Successfully saved"; +$lang->story->confirmDelete = "Are you sure to delete this story?"; +$lang->story->confirmBatchClose = "Are you sure to close those stories?"; +$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->form = new stdclass(); +$lang->story->form->titleNote = 'A word to briefly express story content'; +$lang->story->form->area = 'The story of their respective range'; +$lang->story->form->desc = 'Description and standards, what stories? How to acceptance?'; +$lang->story->form->resource = 'Allocation of resources, who completed? How long does it take?'; +$lang->story->form->file = 'Attachments, if the demand for related documents, please click here to upload.'; + +$lang->story->action = new stdclass(); +$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 = new stdclass(); +$lang->story->report->common = 'Report'; +$lang->story->report->select = 'Select'; +$lang->story->report->create = 'Create'; + +$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 = new stdclass(); +$lang->story->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->story->report->storysPerModule = new stdclass(); +$lang->story->report->storysPerSource = new stdclass(); +$lang->story->report->storysPerPlan = new stdclass(); +$lang->story->report->storysPerStatus = new stdclass(); +$lang->story->report->storysPerStage = new stdclass(); +$lang->story->report->storysPerPri = new stdclass(); +$lang->story->report->storysPerOpenedBy = new stdclass(); +$lang->story->report->storysPerAssignedTo = new stdclass(); +$lang->story->report->storysPerClosedReason = new stdclass(); +$lang->story->report->storysPerEstimate = new stdclass(); +$lang->story->report->storysPerChange = new stdclass(); + +$lang->story->report->storysPerProduct->graph = new stdclass(); +$lang->story->report->storysPerModule->graph = new stdclass(); +$lang->story->report->storysPerSource->graph = new stdclass(); +$lang->story->report->storysPerPlan->graph = new stdclass(); +$lang->story->report->storysPerStatus->graph = new stdclass(); +$lang->story->report->storysPerStage->graph = new stdclass(); +$lang->story->report->storysPerPri->graph = new stdclass(); +$lang->story->report->storysPerOpenedBy->graph = new stdclass(); +$lang->story->report->storysPerAssignedTo->graph = new stdclass(); +$lang->story->report->storysPerClosedReason->graph = new stdclass(); +$lang->story->report->storysPerEstimate->graph = new stdclass(); +$lang->story->report->storysPerChange->graph = new stdclass(); + +$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'; + +$lang->story->placeholder = new stdclass(); +$lang->story->placeholder->estimate = 'Estimate the story point.'; +$lang->story->placeholder->mailto = 'Mail to'; diff --git a/module/story/lang/zh-cn.php b/module/story/lang/zh-cn.php index e89a8c154a..b72f53bb56 100644 --- a/module/story/lang/zh-cn.php +++ b/module/story/lang/zh-cn.php @@ -1,269 +1,269 @@ - - * @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->batchEdit = "批量编辑"; -$lang->story->close = '关闭'; -$lang->story->batchClose = '批量关闭'; -$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->fromBug = '来源Bug'; -$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->hour = '小时'; -$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->newStory = '继续添加需求'; - -$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['customer'] = '客户'; -$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->afterSubmit = "添加之后"; -$lang->story->successSaved = "需求成功添加,"; -$lang->story->confirmDelete = "您确认删除该需求吗?"; -$lang->story->confirmBatchClose = "您确认关闭这些需求吗?"; -$lang->story->errorFormat = '需求数据有误'; -$lang->story->errorEmptyTitle = '标题不能为空'; -$lang->story->mustChooseResult = '必须选择评审结果'; -$lang->story->mustChoosePreVersion = '必须选择回溯的版本'; -$lang->story->ajaxGetProjectStories = '接口:获取项目需求列表'; -$lang->story->ajaxGetProductStories = '接口:获取产品需求列表'; - -$lang->story->form = new stdclass(); -$lang->story->form->titleNote = '一句话简要表达需求内容'; -$lang->story->form->area = '该需求所属范围'; -$lang->story->form->desc = '描述及标准,什么需求?如何验收?'; -$lang->story->form->resource = '资源分配,有谁完成?需要多少时间?'; -$lang->story->form->file = '附件,如果该需求有相关文件,请点此上传。'; - -$lang->story->action = new stdclass(); -$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 = new stdclass(); -$lang->story->report->common = '报表'; -$lang->story->report->select = '请选择报表类型'; -$lang->story->report->create = '生成报表'; - -$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 = new stdclass(); -$lang->story->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->story->report->storysPerModule = new stdclass(); -$lang->story->report->storysPerSource = new stdclass(); -$lang->story->report->storysPerPlan = new stdclass(); -$lang->story->report->storysPerStatus = new stdclass(); -$lang->story->report->storysPerStage = new stdclass(); -$lang->story->report->storysPerPri = new stdclass(); -$lang->story->report->storysPerOpenedBy = new stdclass(); -$lang->story->report->storysPerAssignedTo = new stdclass(); -$lang->story->report->storysPerClosedReason = new stdclass(); -$lang->story->report->storysPerEstimate = new stdclass(); -$lang->story->report->storysPerChange = new stdclass(); - -$lang->story->report->storysPerProduct->graph = new stdclass(); -$lang->story->report->storysPerModule->graph = new stdclass(); -$lang->story->report->storysPerSource->graph = new stdclass(); -$lang->story->report->storysPerPlan->graph = new stdclass(); -$lang->story->report->storysPerStatus->graph = new stdclass(); -$lang->story->report->storysPerStage->graph = new stdclass(); -$lang->story->report->storysPerPri->graph = new stdclass(); -$lang->story->report->storysPerOpenedBy->graph = new stdclass(); -$lang->story->report->storysPerAssignedTo->graph = new stdclass(); -$lang->story->report->storysPerClosedReason->graph = new stdclass(); -$lang->story->report->storysPerEstimate->graph = new stdclass(); -$lang->story->report->storysPerChange->graph = new stdclass(); - -$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 = '变更次数'; - -$lang->story->placeholder = new stdclass(); -$lang->story->placeholder->estimate = "完成该需求的工作量"; -$lang->story->placeholder->mailto = '输入用户名自动完成'; + + * @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->batchEdit = "批量编辑"; +$lang->story->close = '关闭'; +$lang->story->batchClose = '批量关闭'; +$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->fromBug = '来源Bug'; +$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->hour = '小时'; +$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->newStory = '继续添加需求'; + +$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['customer'] = '客户'; +$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->afterSubmit = "添加之后"; +$lang->story->successSaved = "需求成功添加,"; +$lang->story->confirmDelete = "您确认删除该需求吗?"; +$lang->story->confirmBatchClose = "您确认关闭这些需求吗?"; +$lang->story->errorFormat = '需求数据有误'; +$lang->story->errorEmptyTitle = '标题不能为空'; +$lang->story->mustChooseResult = '必须选择评审结果'; +$lang->story->mustChoosePreVersion = '必须选择回溯的版本'; +$lang->story->ajaxGetProjectStories = '接口:获取项目需求列表'; +$lang->story->ajaxGetProductStories = '接口:获取产品需求列表'; + +$lang->story->form = new stdclass(); +$lang->story->form->titleNote = '一句话简要表达需求内容'; +$lang->story->form->area = '该需求所属范围'; +$lang->story->form->desc = '描述及标准,什么需求?如何验收?'; +$lang->story->form->resource = '资源分配,有谁完成?需要多少时间?'; +$lang->story->form->file = '附件,如果该需求有相关文件,请点此上传。'; + +$lang->story->action = new stdclass(); +$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 = new stdclass(); +$lang->story->report->common = '报表'; +$lang->story->report->select = '请选择报表类型'; +$lang->story->report->create = '生成报表'; + +$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 = new stdclass(); +$lang->story->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->story->report->storysPerModule = new stdclass(); +$lang->story->report->storysPerSource = new stdclass(); +$lang->story->report->storysPerPlan = new stdclass(); +$lang->story->report->storysPerStatus = new stdclass(); +$lang->story->report->storysPerStage = new stdclass(); +$lang->story->report->storysPerPri = new stdclass(); +$lang->story->report->storysPerOpenedBy = new stdclass(); +$lang->story->report->storysPerAssignedTo = new stdclass(); +$lang->story->report->storysPerClosedReason = new stdclass(); +$lang->story->report->storysPerEstimate = new stdclass(); +$lang->story->report->storysPerChange = new stdclass(); + +$lang->story->report->storysPerProduct->graph = new stdclass(); +$lang->story->report->storysPerModule->graph = new stdclass(); +$lang->story->report->storysPerSource->graph = new stdclass(); +$lang->story->report->storysPerPlan->graph = new stdclass(); +$lang->story->report->storysPerStatus->graph = new stdclass(); +$lang->story->report->storysPerStage->graph = new stdclass(); +$lang->story->report->storysPerPri->graph = new stdclass(); +$lang->story->report->storysPerOpenedBy->graph = new stdclass(); +$lang->story->report->storysPerAssignedTo->graph = new stdclass(); +$lang->story->report->storysPerClosedReason->graph = new stdclass(); +$lang->story->report->storysPerEstimate->graph = new stdclass(); +$lang->story->report->storysPerChange->graph = new stdclass(); + +$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 = '变更次数'; + +$lang->story->placeholder = new stdclass(); +$lang->story->placeholder->estimate = "完成该需求的工作量"; +$lang->story->placeholder->mailto = '输入用户名自动完成'; diff --git a/module/story/lang/zh-tw.php b/module/story/lang/zh-tw.php index bdfba44844..381f83ba0b 100644 --- a/module/story/lang/zh-tw.php +++ b/module/story/lang/zh-tw.php @@ -1,269 +1,269 @@ - - * @package story - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @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->batchEdit = "批量編輯"; -$lang->story->close = '關閉'; -$lang->story->batchClose = '批量關閉'; -$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->fromBug = '來源Bug'; -$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->hour = '小時'; -$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->newStory = '繼續添加需求'; - -$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['customer'] = '客戶'; -$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->afterSubmit = "添加之後"; -$lang->story->successSaved = "需求成功添加,"; -$lang->story->confirmDelete = "您確認刪除該需求嗎?"; -$lang->story->confirmBatchClose = "您確認關閉這些需求嗎?"; -$lang->story->errorFormat = '需求數據有誤'; -$lang->story->errorEmptyTitle = '標題不能為空'; -$lang->story->mustChooseResult = '必須選擇評審結果'; -$lang->story->mustChoosePreVersion = '必須選擇回溯的版本'; -$lang->story->ajaxGetProjectStories = '介面:獲取項目需求列表'; -$lang->story->ajaxGetProductStories = '介面:獲取產品需求列表'; - -$lang->story->form = new stdclass(); -$lang->story->form->titleNote = '一句話簡要表達需求內容'; -$lang->story->form->area = '該需求所屬範圍'; -$lang->story->form->desc = '描述及標準,什麼需求?如何驗收?'; -$lang->story->form->resource = '資源分配,有誰完成?需要多少時間?'; -$lang->story->form->file = '附件,如果該需求有相關檔案,請點此上傳。'; - -$lang->story->action = new stdclass(); -$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 = new stdclass(); -$lang->story->report->common = '報表'; -$lang->story->report->select = '請選擇報表類型'; -$lang->story->report->create = '生成報表'; - -$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 = new stdclass(); -$lang->story->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->story->report->storysPerModule = new stdclass(); -$lang->story->report->storysPerSource = new stdclass(); -$lang->story->report->storysPerPlan = new stdclass(); -$lang->story->report->storysPerStatus = new stdclass(); -$lang->story->report->storysPerStage = new stdclass(); -$lang->story->report->storysPerPri = new stdclass(); -$lang->story->report->storysPerOpenedBy = new stdclass(); -$lang->story->report->storysPerAssignedTo = new stdclass(); -$lang->story->report->storysPerClosedReason = new stdclass(); -$lang->story->report->storysPerEstimate = new stdclass(); -$lang->story->report->storysPerChange = new stdclass(); - -$lang->story->report->storysPerProduct->graph = new stdclass(); -$lang->story->report->storysPerModule->graph = new stdclass(); -$lang->story->report->storysPerSource->graph = new stdclass(); -$lang->story->report->storysPerPlan->graph = new stdclass(); -$lang->story->report->storysPerStatus->graph = new stdclass(); -$lang->story->report->storysPerStage->graph = new stdclass(); -$lang->story->report->storysPerPri->graph = new stdclass(); -$lang->story->report->storysPerOpenedBy->graph = new stdclass(); -$lang->story->report->storysPerAssignedTo->graph = new stdclass(); -$lang->story->report->storysPerClosedReason->graph = new stdclass(); -$lang->story->report->storysPerEstimate->graph = new stdclass(); -$lang->story->report->storysPerChange->graph = new stdclass(); - -$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 = '變更次數'; - -$lang->story->placeholder = new stdclass(); -$lang->story->placeholder->estimate = "完成該需求的工作量"; -$lang->story->placeholder->mailto = '輸入用戶名自動完成'; + + * @package story + * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ + * @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->batchEdit = "批量編輯"; +$lang->story->close = '關閉'; +$lang->story->batchClose = '批量關閉'; +$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->fromBug = '來源Bug'; +$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->hour = '小時'; +$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->newStory = '繼續添加需求'; + +$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['customer'] = '客戶'; +$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->afterSubmit = "添加之後"; +$lang->story->successSaved = "需求成功添加,"; +$lang->story->confirmDelete = "您確認刪除該需求嗎?"; +$lang->story->confirmBatchClose = "您確認關閉這些需求嗎?"; +$lang->story->errorFormat = '需求數據有誤'; +$lang->story->errorEmptyTitle = '標題不能為空'; +$lang->story->mustChooseResult = '必須選擇評審結果'; +$lang->story->mustChoosePreVersion = '必須選擇回溯的版本'; +$lang->story->ajaxGetProjectStories = '介面:獲取項目需求列表'; +$lang->story->ajaxGetProductStories = '介面:獲取產品需求列表'; + +$lang->story->form = new stdclass(); +$lang->story->form->titleNote = '一句話簡要表達需求內容'; +$lang->story->form->area = '該需求所屬範圍'; +$lang->story->form->desc = '描述及標準,什麼需求?如何驗收?'; +$lang->story->form->resource = '資源分配,有誰完成?需要多少時間?'; +$lang->story->form->file = '附件,如果該需求有相關檔案,請點此上傳。'; + +$lang->story->action = new stdclass(); +$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 = new stdclass(); +$lang->story->report->common = '報表'; +$lang->story->report->select = '請選擇報表類型'; +$lang->story->report->create = '生成報表'; + +$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 = new stdclass(); +$lang->story->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->story->report->storysPerModule = new stdclass(); +$lang->story->report->storysPerSource = new stdclass(); +$lang->story->report->storysPerPlan = new stdclass(); +$lang->story->report->storysPerStatus = new stdclass(); +$lang->story->report->storysPerStage = new stdclass(); +$lang->story->report->storysPerPri = new stdclass(); +$lang->story->report->storysPerOpenedBy = new stdclass(); +$lang->story->report->storysPerAssignedTo = new stdclass(); +$lang->story->report->storysPerClosedReason = new stdclass(); +$lang->story->report->storysPerEstimate = new stdclass(); +$lang->story->report->storysPerChange = new stdclass(); + +$lang->story->report->storysPerProduct->graph = new stdclass(); +$lang->story->report->storysPerModule->graph = new stdclass(); +$lang->story->report->storysPerSource->graph = new stdclass(); +$lang->story->report->storysPerPlan->graph = new stdclass(); +$lang->story->report->storysPerStatus->graph = new stdclass(); +$lang->story->report->storysPerStage->graph = new stdclass(); +$lang->story->report->storysPerPri->graph = new stdclass(); +$lang->story->report->storysPerOpenedBy->graph = new stdclass(); +$lang->story->report->storysPerAssignedTo->graph = new stdclass(); +$lang->story->report->storysPerClosedReason->graph = new stdclass(); +$lang->story->report->storysPerEstimate->graph = new stdclass(); +$lang->story->report->storysPerChange->graph = new stdclass(); + +$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 = '變更次數'; + +$lang->story->placeholder = new stdclass(); +$lang->story->placeholder->estimate = "完成該需求的工作量"; +$lang->story->placeholder->mailto = '輸入用戶名自動完成'; diff --git a/module/story/model.php b/module/story/model.php index 04e122c199..10b7a95dfa 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -1,1397 +1,1397 @@ - - * @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) ? $spec->spec : ''; - $story->verify = isset($spec->verify) ? $spec->verify : ''; - - if($setImgSize) $story->spec = $this->loadModel('file')->setImgSize($story->spec); - if($setImgSize) $story->verify = $this->file->setImgSize($story->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 == 'done') 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,newStory') - ->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] = new stdclass(); - $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(); - $this->setStage($storyID); - - $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) - { - $specChanged = false; - $oldStory = $this->getById($storyID); - $newTitle = stripslashes($this->post->title); - $newSpec = stripslashes($this->post->spec); - $newVerify = stripslashes($this->post->verify); - if($newSpec != $oldStory->spec or $newVerify != $oldStory->verify or $newTitle != $oldStory->title or $this->loadModel('file')->getCount()) $specChanged = true; - - $now = helper::now(); - $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('status', $oldStory->status) - ->setIF($this->post->plan !== false and $this->post->plan == '', 'plan', 0) - ->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(); - - if(!dao::isError()) - { - $this->setStage($storyID); - return common::createChanges($oldStory, $story); - } - } - - /** - * Batch update stories. - * - * @access public - * @return array. - */ - public function batchUpdate() - { - /* Init vars. */ - $stories = array(); - $allChanges = array(); - $now = helper::now(); - $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $taskIDList. */ - if($this->session->showSuhosinInfo) array_pop($storyIDList); - - /* Init $stories. */ - if(!empty($storyIDList)) - { - foreach($storyIDList as $storyID) - { - $oldStory = $this->getById($storyID); - - $story->lastEditedBy = $this->app->user->account; - $story->lastEditedDate = $now; - $story->status = $oldStory->status; - $story->title = htmlspecialchars($this->post->titles[$storyID]); - $story->estimate = $this->post->estimates[$storyID]; - $story->pri = $this->post->pris[$storyID]; - $story->module = $this->post->modules[$storyID]; - $story->plan = $this->post->plans[$storyID]; - $story->source = $this->post->sources[$storyID]; - $story->stage = isset($this->post->stages[$storyID]) ? $this->post->stages[$storyID] : $oldStory->stage; - $story->closedBy = isset($this->post->closedBys[$storyID]) ? $this->post->closedBys[$storyID] : $oldStory->closedBy; - $story->closedReason = isset($this->post->closedReasons[$storyID]) ? $this->post->closedReasons[$storyID] : $oldStory->closedReason; - $story->duplicateStory = isset($this->post->duplicateStories[$storyID]) ? $this->post->duplicateStories[$storyID] : $oldStory->duplicateStory; - $story->childStories = isset($this->post->childStoriesIDList[$storyID]) ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; - - if($story->title != $oldStory->title) $story->status = 'changed'; - if($story->plan !== false and $story->plan == '') $story->plan = 0; - if($story->closedBy != false and $oldStory->closedDate == '') $story->closedDate = $now; - if($story->closedReason != false and $oldStory->closedDate == '') $story->closedDate = $now; - if($story->closedBy != false or $story->closedReason != false) $story->status = 'closed'; - if($story->closedReason != false and $story->closedBy == false) $story->closedBy = $this->app->user->account; - - $stories[$storyID] = $story; - unset($story); - } - - foreach($stories as $storyID => $story) - { - $oldStory = $this->getById($storyID); - - $this->dao->update(TABLE_STORY)->data($story) - ->autoCheck() - ->batchCheck($this->config->story->edit->requiredFields, 'notempty') - ->checkIF($story->closedBy, 'closedReason', 'notempty') - ->checkIF($story->closedReason == 'done', 'stage', 'notempty') - ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq((int)$storyID) - ->exec(); - - if(!dao::isError()) - { - $allChanges[$storyID] = common::createChanges($oldStory, $story); - } - else - { - die(js::error('story#' . $storyID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - /** - * 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 common::createChanges($oldStory, $story); - } - - /** - * Batch close story. - * - * @access public - * @return void - */ - public function batchClose() - { - /* Init vars. */ - $stories = array(); - $allChanges = array(); - $now = helper::now(); - $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $storyIDList. */ - if($this->session->showSuhosinInfo) array_pop($storyIDList); - if(!empty($storyIDList)) - { - foreach($storyIDList as $storyID) - { - $oldStory = $this->getById($storyID); - - $story->lastEditedBy = $this->app->user->account; - $story->lastEditedDate = $now; - $story->closedBy = $this->app->user->account; - $story->closedDate = $now; - $story->assignedTo = 'closed'; - $story->assignedDate = $now; - $story->status = 'closed'; - - $story->closedReason = $this->post->closedReasons[$storyID]; - $story->duplicateStory = $this->post->duplicateStoryIDList[$storyID] ? $this->post->duplicateStoryIDList[$storyID] : $oldStory->duplicateStory; - $story->childStories = $this->post->childStoriesIDList[$storyID] ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; - - if($story->closedReason == 'done') $story->stage = 'released'; - if($story->closedReason != 'done') $story->plan = 0; - - $stories[$storyID] = $story; - unset($story); - } - - foreach($stories as $storyID => $story) - { - if(!$story->closedReason) continue; - - $oldStory = $this->getById($storyID); - - $this->dao->update(TABLE_STORY)->data($story) - ->autoCheck() - ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq($storyID)->exec(); - - if(!dao::isError()) - { - $allChanges[$storyID] = common::createChanges($oldStory, $story); - } - else - { - die(js::error('story#' . $storyID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - /** - * 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('wait')->where('id')->eq((int)$storyID)->andWhere('plan')->eq(0)->andWhere('status')->eq('active')->exec(); - $this->dao->update(TABLE_STORY)->set('stage')->eq('planned')->where('id')->eq((int)$storyID)->andWhere('plan')->gt(0)->exec(); - return true; - } - - /* Search related tasks. */ - $tasks = $this->dao->select('type,status')->from(TABLE_TASK) - ->where('project')->in($projects) - ->andWhere('story')->eq($storyID) - ->andWhere('type')->in('devel,test') - ->andWhere('status')->ne('cancel') - ->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; - } - - /* Get current stage and set as default value. */ - $currentStage = $this->dao->findById($storyID)->from(TABLE_STORY)->fields('stage')->fetch('stage'); - $stage = $currentStage; - - /* Cycle all tasks, get counts of every type and every status. */ - $statusList['devel'] = array('wait' => 0, 'doing' => 0, 'done' => 0); - $statusList['test'] = array('wait' => 0, 'doing' => 0, 'done' => 0); - foreach($tasks as $type => $typeTasks) - { - foreach($typeTasks as $task) - { - $status = $task->status ? $task->status : 'wait'; - $status = $status == 'closed' ? 'done' : $status; - - $statusList[$task->type][$status] ++; - } - } - - /* Get counts of every type tasks. */ - $develTasks = isset($tasks['devel']) ? count($tasks['devel']) : 0; - $testTasks = isset($tasks['test']) ? count($tasks['test']) : 0; - - /** - * Judge stage according to the devel and test tasks' status. - * - * 1. one doing devel task, all test tasks waiting, set stage as developing. - * 2. all devel tasks done, all test tasks waiting, set stage as developed. - * 3. one test task doing, set stage as testing. - * 4. all test tasks done, still some devel tasks not done(wait, doing), set stage as testing. - * 5. all test tasks done, all devel tasks done, set stage as tested. - */ - if($statusList['devel']['doing'] > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developing'; - if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developed'; - if($statusList['test']['doing'] > 0) $stage = 'testing'; - if(($statusList['devel']['wait'] > 0 or $statusList['devel']['doing'] > 0) and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'testing'; - if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'tested'; - - $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) - { - return $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(); - } - - /** - * 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('t1.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') - { - return $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(); - } - - /** - * 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, $projectID = '') - { - if($projectID != '') - { - $products = $this->loadModel('project')->getProducts($projectID); - } - else - { - $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)); - $storyQuery = $this->loadModel('search')->replaceDynamic($storyQuery); - - 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) - { - $productIDs = array_keys($this->loadModel('product')->getPrivProducts()); - - /* Get plans. */ - $plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) - ->beginIF($productID != 'all' and $productID != '')->where('product')->eq((int)$productID)->fi() - ->beginIF($productID == 'all')->where('product')->in($productIDs)->fi() - ->fetchPairs(); - - $tmpStories = $this->dao->select('*')->from(TABLE_STORY)->where($sql) - ->beginIF($productID != 'all' and $productID != '')->andWhere('product')->eq((int)$productID)->fi() - ->beginIF($productID == 'all')->andWhere('product')->in($productIDs)->fi() - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('id'); - - if(!$tmpStories) return array(); - - /* Process plans. */ - $stories = array(); - foreach($tmpStories as $story) - { - $story->planTitle = isset($plans[$story->plan]) ? $plans[$story->plan] : ''; - $stories[] = $story; - } - return $stories; - } - - /** - * 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') - { - $stories = $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'); - return $stories; - } - - /** - * 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) - { - $stories = $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'); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - - return $stories; - } - - /** - * 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); - $stories = $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(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - - return $stories; - } - - /** - * Get story pairs of a user. - * - * @param string $account - * @param string $limit - * @access public - * @return array - */ - public function getUserStoryPairs($account, $limit = 10) - { - return $this->dao->select('id, title') - ->from(TABLE_STORY) - ->where('deleted')->eq(0) - ->andWhere('assignedTo')->eq($account) - ->orderBy('id_desc') - ->limit($limit) - ->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 public - * @return void - */ - public 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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->fi() - ->groupBy('version')->orderBy('value')->fetchAll(); - } - - /** - * Adjust the action clickable. - * - * @param object $story - * @param string $action - * @access public - * @return void - */ - public function isClickable($story, $action) - { - $action = strtolower($action); - - if($action == 'change') return $story->status != 'closed'; - if($action == 'review') return $story->status == 'draft' or $story->status == 'changed'; - if($action == 'close') return $story->status != 'closed'; - if($action == 'activate') return $story->status == 'closed'; - - return true; - } -} + + * @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) ? $spec->spec : ''; + $story->verify = isset($spec->verify) ? $spec->verify : ''; + + if($setImgSize) $story->spec = $this->loadModel('file')->setImgSize($story->spec); + if($setImgSize) $story->verify = $this->file->setImgSize($story->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 == 'done') 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,newStory') + ->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] = new stdclass(); + $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(); + $this->setStage($storyID); + + $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) + { + $specChanged = false; + $oldStory = $this->getById($storyID); + $newTitle = stripslashes($this->post->title); + $newSpec = stripslashes($this->post->spec); + $newVerify = stripslashes($this->post->verify); + if($newSpec != $oldStory->spec or $newVerify != $oldStory->verify or $newTitle != $oldStory->title or $this->loadModel('file')->getCount()) $specChanged = true; + + $now = helper::now(); + $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('status', $oldStory->status) + ->setIF($this->post->plan !== false and $this->post->plan == '', 'plan', 0) + ->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(); + + if(!dao::isError()) + { + $this->setStage($storyID); + return common::createChanges($oldStory, $story); + } + } + + /** + * Batch update stories. + * + * @access public + * @return array. + */ + public function batchUpdate() + { + /* Init vars. */ + $stories = array(); + $allChanges = array(); + $now = helper::now(); + $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $taskIDList. */ + if($this->session->showSuhosinInfo) array_pop($storyIDList); + + /* Init $stories. */ + if(!empty($storyIDList)) + { + foreach($storyIDList as $storyID) + { + $oldStory = $this->getById($storyID); + + $story->lastEditedBy = $this->app->user->account; + $story->lastEditedDate = $now; + $story->status = $oldStory->status; + $story->title = htmlspecialchars($this->post->titles[$storyID]); + $story->estimate = $this->post->estimates[$storyID]; + $story->pri = $this->post->pris[$storyID]; + $story->module = $this->post->modules[$storyID]; + $story->plan = $this->post->plans[$storyID]; + $story->source = $this->post->sources[$storyID]; + $story->stage = isset($this->post->stages[$storyID]) ? $this->post->stages[$storyID] : $oldStory->stage; + $story->closedBy = isset($this->post->closedBys[$storyID]) ? $this->post->closedBys[$storyID] : $oldStory->closedBy; + $story->closedReason = isset($this->post->closedReasons[$storyID]) ? $this->post->closedReasons[$storyID] : $oldStory->closedReason; + $story->duplicateStory = isset($this->post->duplicateStories[$storyID]) ? $this->post->duplicateStories[$storyID] : $oldStory->duplicateStory; + $story->childStories = isset($this->post->childStoriesIDList[$storyID]) ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; + + if($story->title != $oldStory->title) $story->status = 'changed'; + if($story->plan !== false and $story->plan == '') $story->plan = 0; + if($story->closedBy != false and $oldStory->closedDate == '') $story->closedDate = $now; + if($story->closedReason != false and $oldStory->closedDate == '') $story->closedDate = $now; + if($story->closedBy != false or $story->closedReason != false) $story->status = 'closed'; + if($story->closedReason != false and $story->closedBy == false) $story->closedBy = $this->app->user->account; + + $stories[$storyID] = $story; + unset($story); + } + + foreach($stories as $storyID => $story) + { + $oldStory = $this->getById($storyID); + + $this->dao->update(TABLE_STORY)->data($story) + ->autoCheck() + ->batchCheck($this->config->story->edit->requiredFields, 'notempty') + ->checkIF($story->closedBy, 'closedReason', 'notempty') + ->checkIF($story->closedReason == 'done', 'stage', 'notempty') + ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq((int)$storyID) + ->exec(); + + if(!dao::isError()) + { + $allChanges[$storyID] = common::createChanges($oldStory, $story); + } + else + { + die(js::error('story#' . $storyID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + /** + * 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 common::createChanges($oldStory, $story); + } + + /** + * Batch close story. + * + * @access public + * @return void + */ + public function batchClose() + { + /* Init vars. */ + $stories = array(); + $allChanges = array(); + $now = helper::now(); + $storyIDList = $this->post->storyIDList ? $this->post->storyIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $storyIDList. */ + if($this->session->showSuhosinInfo) array_pop($storyIDList); + if(!empty($storyIDList)) + { + foreach($storyIDList as $storyID) + { + $oldStory = $this->getById($storyID); + + $story->lastEditedBy = $this->app->user->account; + $story->lastEditedDate = $now; + $story->closedBy = $this->app->user->account; + $story->closedDate = $now; + $story->assignedTo = 'closed'; + $story->assignedDate = $now; + $story->status = 'closed'; + + $story->closedReason = $this->post->closedReasons[$storyID]; + $story->duplicateStory = $this->post->duplicateStoryIDList[$storyID] ? $this->post->duplicateStoryIDList[$storyID] : $oldStory->duplicateStory; + $story->childStories = $this->post->childStoriesIDList[$storyID] ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; + + if($story->closedReason == 'done') $story->stage = 'released'; + if($story->closedReason != 'done') $story->plan = 0; + + $stories[$storyID] = $story; + unset($story); + } + + foreach($stories as $storyID => $story) + { + if(!$story->closedReason) continue; + + $oldStory = $this->getById($storyID); + + $this->dao->update(TABLE_STORY)->data($story) + ->autoCheck() + ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq($storyID)->exec(); + + if(!dao::isError()) + { + $allChanges[$storyID] = common::createChanges($oldStory, $story); + } + else + { + die(js::error('story#' . $storyID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + /** + * 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('wait')->where('id')->eq((int)$storyID)->andWhere('plan')->eq(0)->andWhere('status')->eq('active')->exec(); + $this->dao->update(TABLE_STORY)->set('stage')->eq('planned')->where('id')->eq((int)$storyID)->andWhere('plan')->gt(0)->exec(); + return true; + } + + /* Search related tasks. */ + $tasks = $this->dao->select('type,status')->from(TABLE_TASK) + ->where('project')->in($projects) + ->andWhere('story')->eq($storyID) + ->andWhere('type')->in('devel,test') + ->andWhere('status')->ne('cancel') + ->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; + } + + /* Get current stage and set as default value. */ + $currentStage = $this->dao->findById($storyID)->from(TABLE_STORY)->fields('stage')->fetch('stage'); + $stage = $currentStage; + + /* Cycle all tasks, get counts of every type and every status. */ + $statusList['devel'] = array('wait' => 0, 'doing' => 0, 'done' => 0); + $statusList['test'] = array('wait' => 0, 'doing' => 0, 'done' => 0); + foreach($tasks as $type => $typeTasks) + { + foreach($typeTasks as $task) + { + $status = $task->status ? $task->status : 'wait'; + $status = $status == 'closed' ? 'done' : $status; + + $statusList[$task->type][$status] ++; + } + } + + /* Get counts of every type tasks. */ + $develTasks = isset($tasks['devel']) ? count($tasks['devel']) : 0; + $testTasks = isset($tasks['test']) ? count($tasks['test']) : 0; + + /** + * Judge stage according to the devel and test tasks' status. + * + * 1. one doing devel task, all test tasks waiting, set stage as developing. + * 2. all devel tasks done, all test tasks waiting, set stage as developed. + * 3. one test task doing, set stage as testing. + * 4. all test tasks done, still some devel tasks not done(wait, doing), set stage as testing. + * 5. all test tasks done, all devel tasks done, set stage as tested. + */ + if($statusList['devel']['doing'] > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developing'; + if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['wait'] == $testTasks) $stage = 'developed'; + if($statusList['test']['doing'] > 0) $stage = 'testing'; + if(($statusList['devel']['wait'] > 0 or $statusList['devel']['doing'] > 0) and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'testing'; + if($statusList['devel']['done'] == $develTasks and $develTasks > 0 and $statusList['test']['done'] == $testTasks and $testTasks > 0) $stage = 'tested'; + + $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) + { + return $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(); + } + + /** + * 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('t1.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') + { + return $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(); + } + + /** + * 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, $projectID = '') + { + if($projectID != '') + { + $products = $this->loadModel('project')->getProducts($projectID); + } + else + { + $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)); + $storyQuery = $this->loadModel('search')->replaceDynamic($storyQuery); + + 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) + { + $productIDs = array_keys($this->loadModel('product')->getPrivProducts()); + + /* Get plans. */ + $plans = $this->dao->select('id,title')->from(TABLE_PRODUCTPLAN) + ->beginIF($productID != 'all' and $productID != '')->where('product')->eq((int)$productID)->fi() + ->beginIF($productID == 'all')->where('product')->in($productIDs)->fi() + ->fetchPairs(); + + $tmpStories = $this->dao->select('*')->from(TABLE_STORY)->where($sql) + ->beginIF($productID != 'all' and $productID != '')->andWhere('product')->eq((int)$productID)->fi() + ->beginIF($productID == 'all')->andWhere('product')->in($productIDs)->fi() + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('id'); + + if(!$tmpStories) return array(); + + /* Process plans. */ + $stories = array(); + foreach($tmpStories as $story) + { + $story->planTitle = isset($plans[$story->plan]) ? $plans[$story->plan] : ''; + $stories[] = $story; + } + return $stories; + } + + /** + * 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') + { + $stories = $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'); + return $stories; + } + + /** + * 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) + { + $stories = $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'); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + + return $stories; + } + + /** + * 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); + $stories = $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(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); + + return $stories; + } + + /** + * Get story pairs of a user. + * + * @param string $account + * @param string $limit + * @access public + * @return array + */ + public function getUserStoryPairs($account, $limit = 10) + { + return $this->dao->select('id, title') + ->from(TABLE_STORY) + ->where('deleted')->eq(0) + ->andWhere('assignedTo')->eq($account) + ->orderBy('id_desc') + ->limit($limit) + ->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 public + * @return void + */ + public 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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->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->storyQueryCondition != false)->where($this->session->storyQueryCondition)->fi() + ->groupBy('version')->orderBy('value')->fetchAll(); + } + + /** + * Adjust the action clickable. + * + * @param object $story + * @param string $action + * @access public + * @return void + */ + public function isClickable($story, $action) + { + $action = strtolower($action); + + if($action == 'change') return $story->status != 'closed'; + if($action == 'review') return $story->status == 'draft' or $story->status == 'changed'; + if($action == 'close') return $story->status != 'closed'; + if($action == 'activate') return $story->status == 'closed'; + + return true; + } +} diff --git a/module/story/view/activate.html.php b/module/story/view/activate.html.php index ff0367d40b..ef8f70ab16 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/batchclose.html.php b/module/story/view/batchclose.html.php index 85416807aa..58898d95ec 100755 --- a/module/story/view/batchclose.html.php +++ b/module/story/view/batchclose.html.php @@ -1,64 +1,64 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          "> - - - - - - - - - - - - - - - - status != 'closed'):?> - - - - - - - - - - - - -
          story->common . $lang->colon . $lang->story->batchClose;?>
          idAB;?> story->title;?> story->status;?>story->closedReason;?> story->comment;?>
          id . html::hidden("storyIDList[$story->id]", $story->id);?>title;?>story->statusList[$story->status];?> -
          - status == 'draft') unset($this->lang->story->reasonList['cancel']); - echo html::select("closedReasons[$story->id]", $lang->story->reasonList, 'done', "class=w-70px onchange=setDuplicateAndChild(this.value,$story->id)"); - ?> -
          -
          id;?>' closedReason != 'duplicate') echo "style='display:none'";?>> - id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> -
          - -
          id;?>' closedReason != 'subdivided') echo "style='display:none'";?>> - id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> -
          -
          -
          - id]", $lang->story->reasonList, $story->closedReason, 'class="w-70px" disabled="disabled"');?> -
          -
          id]", '', "rows='1' class='area-1'");?>
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          "> + + + + + + + + + + + + + + + + status != 'closed'):?> + + + + + + + + + + + + +
          story->common . $lang->colon . $lang->story->batchClose;?>
          idAB;?> story->title;?> story->status;?>story->closedReason;?> story->comment;?>
          id . html::hidden("storyIDList[$story->id]", $story->id);?>title;?>story->statusList[$story->status];?> +
          + status == 'draft') unset($this->lang->story->reasonList['cancel']); + echo html::select("closedReasons[$story->id]", $lang->story->reasonList, 'done', "class=w-70px onchange=setDuplicateAndChild(this.value,$story->id)"); + ?> +
          +
          id;?>' closedReason != 'duplicate') echo "style='display:none'";?>> + id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> +
          + +
          id;?>' closedReason != 'subdivided') echo "style='display:none'";?>> + id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> +
          +
          +
          + id]", $lang->story->reasonList, $story->closedReason, 'class="w-70px" disabled="disabled"');?> +
          +
          id]", '', "rows='1' class='area-1'");?>
          +
          + diff --git a/module/story/view/batchcreate.html.php b/module/story/view/batchcreate.html.php index dae9e6d012..abd0228d01 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/batchedit.html.php b/module/story/view/batchedit.html.php index c557ed383b..fff798e7c9 100644 --- a/module/story/view/batchedit.html.php +++ b/module/story/view/batchedit.html.php @@ -1,76 +1,76 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          "> - - - - - - - - - - - - - - - - - - - - - - - - - - - status != 'draft'):?> - - - - - - status == 'closed'):?> - - - - - - status == 'closed'):?> - - - - - - - - - - -
          story->common . $lang->colon . $lang->story->batchEdit;?>
          idAB;?> story->title;?> story->estimateAB;?> priAB;?>story->module;?>story->planAB;?> story->source;?> story->status;?> story->stageAB;?>story->closedBy;?>story->closedReason;?>
          id . html::hidden("storyIDList[$story->id]", $story->id);?>id]", $story->title, 'class=text-1'); echo "*";?>id]", $story->estimate, 'class=text-1'); echo "*";?>id]", (array)$lang->story->priList, $story->pri, 'class=select-1');?>id]", $moduleOptionMenus[$story->product], $story->module, 'class=select-1');?>id]", $productPlans[$story->product], $story->plan, 'class=select-1');?>id]", $lang->story->sourceList, $story->source, 'class=select-1');?>story->statusList[$story->status];?>id]", $lang->story->stageList, $story->stage, 'class=select-1');?>id]", $lang->story->stageList, $story->stage, 'class="select-1" disabled="disabled"');?>id]", $users, $story->closedBy, 'class="select-1"');?>id]", $users, $story->closedBy, 'class="select-1" disabled="disabled"');?> -
          id]", $lang->story->reasonList, $story->closedReason, "class=w-60px onchange=setDuplicateAndChild(this.value,$story->id)");?>
          - -
          id;?>' closedReason != 'duplicate') echo "style='display:none'";?>> - id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> -
          - -
          id;?>' closedReason != 'subdivided') echo "style='display:none'";?>> - id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> -
          -
          id]", $lang->story->reasonList, $story->closedReason, 'class="w-60px" disabled="disabled"');?>
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          "> + + + + + + + + + + + + + + + + + + + + + + + + + + + status != 'draft'):?> + + + + + + status == 'closed'):?> + + + + + + status == 'closed'):?> + + + + + + + + + + +
          story->common . $lang->colon . $lang->story->batchEdit;?>
          idAB;?> story->title;?> story->estimateAB;?> priAB;?>story->module;?>story->planAB;?> story->source;?> story->status;?> story->stageAB;?>story->closedBy;?>story->closedReason;?>
          id . html::hidden("storyIDList[$story->id]", $story->id);?>id]", $story->title, 'class=text-1'); echo "*";?>id]", $story->estimate, 'class=text-1'); echo "*";?>id]", (array)$lang->story->priList, $story->pri, 'class=select-1');?>id]", $moduleOptionMenus[$story->product], $story->module, 'class=select-1');?>id]", $productPlans[$story->product], $story->plan, 'class=select-1');?>id]", $lang->story->sourceList, $story->source, 'class=select-1');?>story->statusList[$story->status];?>id]", $lang->story->stageList, $story->stage, 'class=select-1');?>id]", $lang->story->stageList, $story->stage, 'class="select-1" disabled="disabled"');?>id]", $users, $story->closedBy, 'class="select-1"');?>id]", $users, $story->closedBy, 'class="select-1" disabled="disabled"');?> +
          id]", $lang->story->reasonList, $story->closedReason, "class=w-60px onchange=setDuplicateAndChild(this.value,$story->id)");?>
          + +
          id;?>' closedReason != 'duplicate') echo "style='display:none'";?>> + id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> +
          + +
          id;?>' closedReason != 'subdivided') echo "style='display:none'";?>> + id]", '', "class=w-30px placeholder='{$lang->idAB}'");?> +
          +
          id]", $lang->story->reasonList, $story->closedReason, 'class="w-60px" disabled="disabled"');?>
          +
          + diff --git a/module/story/view/change.html.php b/module/story/view/change.html.php index 8c88de5ead..c55ed634a7 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 c101eef0f2..7afc8d4071 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 eeb7e5bfa9..5cae8aa0f3 100644 --- a/module/story/view/create.html.php +++ b/module/story/view/create.html.php @@ -1,79 +1,79 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -story->placeholder, 'json'); ?> -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          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->hour;?>
          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->placeholder, 'json'); ?> +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          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->hour;?>
          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 23f1b02a9b..ec372d324f 100644 --- a/module/story/view/edit.html.php +++ b/module/story/view/edit.html.php @@ -1,143 +1,143 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          -
          STORY #id . $lang->colon . $story->title;?>
          -
          -
          - - - - - - - -
          -
          - story->legendSpec;?> -
          spec;?>
          -
          -
          - story->verify;?> -
          verify);?>
          -
          -
          - 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):?> - - - - - - status == 'closed'):?> - - - - - - - - - -
          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->verify;?> +
          verify);?>
          +
          +
          + 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):?> + + + + + + status == 'closed'):?> + + + + + + + + + +
          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 c6680aa28f..ab1fac2f8a 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 602d5ca51d..24c0c87317 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;?>
          -
          createLink('product', 'browse', "productID=$productID&browseType=$browseType&moduleID=$moduleID")); ?>
          -
          - - - - - - - -
          -
          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;?>
          +
          createLink('product', 'browse', "productID=$productID&browseType=$browseType&moduleID=$moduleID")); ?>
          +
          + + + + + + + +
          +
          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 554d6eaef3..6816b227fd 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 12f224f1d1..2c93d939bb 100644 --- a/module/story/view/sendmail.html.php +++ b/module/story/view/sendmail.html.php @@ -1,39 +1,39 @@ - - * @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);?> -
          -
          - story->legendSpec;?> -
          - spec, 'src="data/upload')) - { - $story->spec = str_replace('server->http_host . $this->config->webRoot, $story->spec); - $story->spec = str_replace('server->http_host . $this->config->webRoot, $story->spec); - } - echo $story->spec; - ?> -
          -
          -
          + + * @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);?> +
          +
          + story->legendSpec;?> +
          + spec, 'src="data/upload')) + { + $story->spec = str_replace('server->http_host . $this->config->webRoot, $story->spec); + $story->spec = str_replace('server->http_host . $this->config->webRoot, $story->spec); + } + echo $story->spec; + ?> +
          +
          +
          diff --git a/module/story/view/view.html.php b/module/story/view/view.html.php index 6c0b7751be..0e1c8702b0 100644 --- a/module/story/view/view.html.php +++ b/module/story/view/view.html.php @@ -1,274 +1,274 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          -
          deleted) echo "class='deleted'";?>>STORY #id . ' ' . $story->title;?>
          -
          - session->storyList != false ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product&moduleID=$story->module"); - $actionLinks = ''; - if(!$story->deleted) - { - ob_start(); - - common::printIcon('story', 'change', "storyID=$story->id", $story); - common::printIcon('story', 'review', "storyID=$story->id", $story); - common::printIcon('story', 'close', "storyID=$story->id", $story); - common::printIcon('story', 'activate', "storyID=$story->id", $story); - common::printIcon('story', 'createCase', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", '', 'button', 'createCase'); - - common::printDivider(); - common::printIcon('story', 'edit', "storyID=$story->id"); - common::printCommentIcon('story'); - common::printIcon('story', 'create', "productID=$story->product&moduleID=$story->module&storyID=$story->id", '', 'button', 'copy'); - common::printIcon('story', 'delete', "storyID=$story->id", '', 'button', '', 'hiddenwin'); - - common::printDivider(); - common::printRPN($browseLink, $preAndNext); - - $actionLinks = ob_get_contents(); - ob_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
          -
          - - - - - - -
          -
          - story->legendSpec;?> -
          spec;?>
          -
          -
          - story->legendVerify;?> -
          verify;?>
          -
          - fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true'));?> - - - -
          - -
          - 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;?> - - - - -
          - id $bug->title'>" . html::a($this->createLink('bug', 'view', "bugID=$bug->id"), "#$bug->id $bug->title") . '
          '; - } - ?> -
          -
          - -
          - story->legendCases;?> - - - - -
          - id $case->title'>" . 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;?> -
          - id $fromBug->title'>" . 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 . ' ' . $story->title;?>
          +
          + session->storyList != false ? $app->session->storyList : $this->createLink('product', 'browse', "productID=$story->product&moduleID=$story->module"); + $actionLinks = ''; + if(!$story->deleted) + { + ob_start(); + + common::printIcon('story', 'change', "storyID=$story->id", $story); + common::printIcon('story', 'review', "storyID=$story->id", $story); + common::printIcon('story', 'close', "storyID=$story->id", $story); + common::printIcon('story', 'activate', "storyID=$story->id", $story); + common::printIcon('story', 'createCase', "productID=$story->product&moduleID=0&from=¶m=0&storyID=$story->id", '', 'button', 'createCase'); + + common::printDivider(); + common::printIcon('story', 'edit', "storyID=$story->id"); + common::printCommentIcon('story'); + common::printIcon('story', 'create', "productID=$story->product&moduleID=$story->module&storyID=$story->id", '', 'button', 'copy'); + common::printIcon('story', 'delete', "storyID=$story->id", '', 'button', '', 'hiddenwin'); + + common::printDivider(); + common::printRPN($browseLink, $preAndNext); + + $actionLinks = ob_get_contents(); + ob_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
          +
          + + + + + + +
          +
          + story->legendSpec;?> +
          spec;?>
          +
          +
          + story->legendVerify;?> +
          verify;?>
          +
          + fetch('file', 'printFiles', array('files' => $story->files, 'fieldset' => 'true'));?> + + + +
          + +
          + 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;?> + + + + +
          + id $bug->title'>" . html::a($this->createLink('bug', 'view', "bugID=$bug->id"), "#$bug->id $bug->title") . '
          '; + } + ?> +
          +
          + +
          + story->legendCases;?> + + + + +
          + id $case->title'>" . 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;?> +
          + id $fromBug->title'>" . 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 b5fa68504b..fe589f1273 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 ff31b6a2fa..843b632802 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 09f1573c15..29e4914066 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 d7f922aff3..0282c42e15 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 30f3e35b64..409603d645 100644 --- a/module/svn/model.php +++ b/module/svn/model.php @@ -1,653 +1,653 @@ - - * @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(stripos($repo->path, 'https') === 0 or stripos($repo->path, 'svn') === 0) - { - $cmd = $this->config->svn->client . ' --version --quiet'; - $version = `$cmd`; - if(version_compare($version, '1.6.0', '>')) - { - $this->client .= ' --trust-server-cert'; - } - } - 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); - putenv('LC_CTYPE=en_US.UTF-8'); - - $oldRevision = $revision - 1; - - $url = str_replace('%2F', '/', urlencode($url)); - $url = str_replace('%3A', ':', $url); - - $cmd = $this->client . " diff -r $oldRevision:$revision $url"; - $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); - - putenv('LC_CTYPE=en_US.UTF-8'); - - $url = str_replace('%2F', '/', urlencode($url)); - $url = str_replace('%3A', ':', $url); - - $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(stripos($repo->path, 'https') === 0 or stripos($repo->path, 'svn') === 0) + { + $cmd = $this->config->svn->client . ' --version --quiet'; + $version = `$cmd`; + if(version_compare($version, '1.6.0', '>')) + { + $this->client .= ' --trust-server-cert'; + } + } + 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); + putenv('LC_CTYPE=en_US.UTF-8'); + + $oldRevision = $revision - 1; + + $url = str_replace('%2F', '/', urlencode($url)); + $url = str_replace('%3A', ':', $url); + + $cmd = $this->client . " diff -r $oldRevision:$revision $url"; + $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); + + putenv('LC_CTYPE=en_US.UTF-8'); + + $url = str_replace('%2F', '/', urlencode($url)); + $url = str_replace('%3A', ':', $url); + + $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 4285162c3b..6de0cf95d7 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 e3e158227c..61133071e2 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 6fc5ab0d9e..f4c89c571d 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 68c7639eba..012fa76e92 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -1,873 +1,873 @@ - - * @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'); - $this->loadModel('tree'); - } - - /** - * Create a task. - * - * @param int $projectID - * @param int $storyID - * @access public - * @return void - */ - public function create($projectID = 0, $storyID = 0, $moduleID = 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 == 'toTaskList') - { - 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'); - $contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); - $moduleOptionMenu = $this->tree->getOptionMenu($projectID, $viewType = 'task'); - - $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->view->contactLists = $contactLists; - $this->view->moduleID = $moduleID; - $this->view->moduleOptionMenu = $moduleOptionMenu; - $this->display(); - } - - /** - * Batch create task. - * - * @param int $projectID - * @param int $storyID - * @access public - * @return void - */ - public function batchCreate($projectID = 0, $storyID = 0, $iframe = 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. */ - if($iframe) die(js::reload('parent.parent')); - die(js::locate($taskLink, 'parent')); - } - - $stories = $this->story->getProjectStoryPairs($projectID); - $stories['ditto'] = $this->lang->task->ditto; - $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')); - } - - $noclosedProjects = $this->project->getPairs('noclosed,nocode'); - unset($noclosedProjects[$this->view->project->id]); - $this->view->projects = array($this->view->project->id => $this->view->project->name) + $noclosedProjects; - - $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->view->modules = $this->tree->getOptionMenu($this->view->task->project, $viewType = 'task'); - $this->display(); - } - - /** - * Batch edit task. - * - * @param int $projectID - * @param string $from example:projectTask, taskBatchEdit - * @param string $orderBy - * @access public - * @return void - */ - public function batchEdit($projectID = 0, $from = '', $orderBy = '') - { - /* Get form data for project-task. */ - if($from == 'projectTask') - { - /* Initialize vars. */ - if(!$orderBy) $orderBy = $this->cookie->projectTaskOrder ? $this->cookie->projectTaskOrder : 'status,id_desc'; - $project = $this->project->getById($projectID); - $taskIDList = $this->post->taskIDList ? $this->post->taskIDList : array(); - $editedTasks = array(); - $columns = 13; - $showSuhosinInfo = false; - - /* Set project menu. */ - $this->project->setMenu($this->project->getPairs(), $project->id); - - /* Get all tasks. */ - $allTasks = $this->dao->select('*')->from(TABLE_TASK)->alias('t1')->where($this->session->taskQueryCondition)->orderBy($orderBy)->fetchAll('id'); - if(!$allTasks) $allTasks = array(); - - /* Initialize the tasks whose need to edited. */ - foreach($allTasks as $task) if(in_array($task->id, $taskIDList)) $editedTasks[$task->id] = $task; - - /* Judge whether the editedTasks is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedTasks), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - $this->view->header->title = $project->name . $this->lang->colon . $this->lang->task->batchEdit; - $this->view->position[] = $this->lang->task->common; - $this->view->position[] = $this->lang->task->batchEdit; - - $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); - $members = $members + array('closed' => 'Closed'); - - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->projectID = $project->id; - $this->view->modules = $this->tree->getOptionMenu($projectID, $viewType = 'task'); - $this->view->editedTasks = $editedTasks; - $this->view->members = $members; - - $this->display(); - } - /* Get form data for task-batchEdit. */ - elseif($from == 'taskBatchEdit') - { - $allChanges = $this->task->batchUpdate(); - - if(!empty($allChanges)) - { - foreach($allChanges as $taskID => $changes) - { - if(!empty($changes)) - { - $actionID = $this->loadModel('action')->create('task', $taskID, 'Edited'); - $this->action->logHistory($actionID, $changes); - $this->sendmail($taskID, $actionID); - - $task = $this->task->getById($taskID); - 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->session->taskList, 'parent')); - } - } - - /** - * 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'); - $changes = $this->task->assign($taskID); - if(dao::isError()) die(js::error(dao::getError())); - $actionID = $this->action->create('task', $taskID, 'Assigned', $this->post->comment, $this->post->assignedTo); - $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->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, true); - if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); - - /* Update action. */ - if($task->assignedTo == $this->app->user->account) $this->loadModel('action')->read('task', $taskID); - - /* Set menu. */ - $project = $this->project->getById($task->project); - $this->project->setMenu($this->project->getPairs(), $project->id); - - $header['title'] = "TASK#$task->id $task->name / $project->name"; - $position[] = html::a($this->createLink('project', 'browse', "projectID=$task->project"), $project->name); - $position[] = $task->name; - - $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('task', $taskID); - $this->view->modulePath = $this->tree->getParents($task->module); - $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(); - } - - /** - * Record consumed and estimate. - * - * @param int $taskID - * @access public - * @return void - */ - public function record($taskID, $confirm = 'no') - { - $this->commonAction($taskID); - - if(!empty($_POST)) - { - $changes = $this->task->record($taskID); - $actionID = $this->action->create('task', $taskID, 'Recorded', $this->post->comment, (float)$this->post->consumed); - $this->action->logHistory($actionID, $changes); - die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); - } - - $header['title'] = $this->lang->task->record; - - $this->view->header = $header; - $this->view->beforeConsumed = $this->task->getBeforeConsumed($taskID); - $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->view->date = strftime("%Y-%m-%d %X", strtotime('now')); - - $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 public - * @return void - */ - public function sendmail($taskID, $actionID) - { - /* Set toList and ccList. */ - $task = $this->task->getById($taskID); - $projectName = $this->project->getById($task->project)->name; - $users = $this->loadModel('user')->getPairs('noletter'); - $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->view->users = $users; - $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 $id - * @param string $status - * @access public - * @return string - */ - public function ajaxGetUserTasks($account = '', $id = '', $status = 'wait,doing') - { - if($account == '') $account = $this->app->user->account; - $tasks = $this->task->getUserTaskPairs($account, $status); - - if($id) die(html::select("tasks[$id]", $tasks, '', 'class="select-1 f-left"')); - 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->taskQueryCondition) - ->beginIF($this->post->exportType == 'selected')->andWhere('t1.id')->in($this->cookie->checkedItem)->fi() - ->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->post->set('kind', 'task'); - $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'); + $this->loadModel('tree'); + } + + /** + * Create a task. + * + * @param int $projectID + * @param int $storyID + * @access public + * @return void + */ + public function create($projectID = 0, $storyID = 0, $moduleID = 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 == 'toTaskList') + { + 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'); + $contactLists = $this->user->getContactLists($this->app->user->account, 'withnote'); + $moduleOptionMenu = $this->tree->getOptionMenu($projectID, $viewType = 'task'); + + $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->view->contactLists = $contactLists; + $this->view->moduleID = $moduleID; + $this->view->moduleOptionMenu = $moduleOptionMenu; + $this->display(); + } + + /** + * Batch create task. + * + * @param int $projectID + * @param int $storyID + * @access public + * @return void + */ + public function batchCreate($projectID = 0, $storyID = 0, $iframe = 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. */ + if($iframe) die(js::reload('parent.parent')); + die(js::locate($taskLink, 'parent')); + } + + $stories = $this->story->getProjectStoryPairs($projectID); + $stories['ditto'] = $this->lang->task->ditto; + $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')); + } + + $noclosedProjects = $this->project->getPairs('noclosed,nocode'); + unset($noclosedProjects[$this->view->project->id]); + $this->view->projects = array($this->view->project->id => $this->view->project->name) + $noclosedProjects; + + $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->view->modules = $this->tree->getOptionMenu($this->view->task->project, $viewType = 'task'); + $this->display(); + } + + /** + * Batch edit task. + * + * @param int $projectID + * @param string $from example:projectTask, taskBatchEdit + * @param string $orderBy + * @access public + * @return void + */ + public function batchEdit($projectID = 0, $from = '', $orderBy = '') + { + /* Get form data for project-task. */ + if($from == 'projectTask') + { + /* Initialize vars. */ + if(!$orderBy) $orderBy = $this->cookie->projectTaskOrder ? $this->cookie->projectTaskOrder : 'status,id_desc'; + $project = $this->project->getById($projectID); + $taskIDList = $this->post->taskIDList ? $this->post->taskIDList : array(); + $editedTasks = array(); + $columns = 13; + $showSuhosinInfo = false; + + /* Set project menu. */ + $this->project->setMenu($this->project->getPairs(), $project->id); + + /* Get all tasks. */ + $allTasks = $this->dao->select('*')->from(TABLE_TASK)->alias('t1')->where($this->session->taskQueryCondition)->orderBy($orderBy)->fetchAll('id'); + if(!$allTasks) $allTasks = array(); + + /* Initialize the tasks whose need to edited. */ + foreach($allTasks as $task) if(in_array($task->id, $taskIDList)) $editedTasks[$task->id] = $task; + + /* Judge whether the editedTasks is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedTasks), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + $this->view->header->title = $project->name . $this->lang->colon . $this->lang->task->batchEdit; + $this->view->position[] = $this->lang->task->common; + $this->view->position[] = $this->lang->task->batchEdit; + + $members = $this->project->getTeamMemberPairs($projectID, 'nodeleted'); + $members = $members + array('closed' => 'Closed'); + + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->projectID = $project->id; + $this->view->modules = $this->tree->getOptionMenu($projectID, $viewType = 'task'); + $this->view->editedTasks = $editedTasks; + $this->view->members = $members; + + $this->display(); + } + /* Get form data for task-batchEdit. */ + elseif($from == 'taskBatchEdit') + { + $allChanges = $this->task->batchUpdate(); + + if(!empty($allChanges)) + { + foreach($allChanges as $taskID => $changes) + { + if(!empty($changes)) + { + $actionID = $this->loadModel('action')->create('task', $taskID, 'Edited'); + $this->action->logHistory($actionID, $changes); + $this->sendmail($taskID, $actionID); + + $task = $this->task->getById($taskID); + 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->session->taskList, 'parent')); + } + } + + /** + * 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'); + $changes = $this->task->assign($taskID); + if(dao::isError()) die(js::error(dao::getError())); + $actionID = $this->action->create('task', $taskID, 'Assigned', $this->post->comment, $this->post->assignedTo); + $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->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, true); + if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); + + /* Update action. */ + if($task->assignedTo == $this->app->user->account) $this->loadModel('action')->read('task', $taskID); + + /* Set menu. */ + $project = $this->project->getById($task->project); + $this->project->setMenu($this->project->getPairs(), $project->id); + + $header['title'] = "TASK#$task->id $task->name / $project->name"; + $position[] = html::a($this->createLink('project', 'browse', "projectID=$task->project"), $project->name); + $position[] = $task->name; + + $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('task', $taskID); + $this->view->modulePath = $this->tree->getParents($task->module); + $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(); + } + + /** + * Record consumed and estimate. + * + * @param int $taskID + * @access public + * @return void + */ + public function record($taskID, $confirm = 'no') + { + $this->commonAction($taskID); + + if(!empty($_POST)) + { + $changes = $this->task->record($taskID); + $actionID = $this->action->create('task', $taskID, 'Recorded', $this->post->comment, (float)$this->post->consumed); + $this->action->logHistory($actionID, $changes); + die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent')); + } + + $header['title'] = $this->lang->task->record; + + $this->view->header = $header; + $this->view->beforeConsumed = $this->task->getBeforeConsumed($taskID); + $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->view->date = strftime("%Y-%m-%d %X", strtotime('now')); + + $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 public + * @return void + */ + public function sendmail($taskID, $actionID) + { + /* Set toList and ccList. */ + $task = $this->task->getById($taskID); + $projectName = $this->project->getById($task->project)->name; + $users = $this->loadModel('user')->getPairs('noletter'); + $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->view->users = $users; + $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 $id + * @param string $status + * @access public + * @return string + */ + public function ajaxGetUserTasks($account = '', $id = '', $status = 'wait,doing') + { + if($account == '') $account = $this->app->user->account; + $tasks = $this->task->getUserTaskPairs($account, $status); + + if($id) die(html::select("tasks[$id]", $tasks, '', 'class="select-1 f-left"')); + 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->taskQueryCondition) + ->beginIF($this->post->exportType == 'selected')->andWhere('t1.id')->in($this->cookie->checkedItem)->fi() + ->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->post->set('kind', 'task'); + $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 adc0ed36c6..88b549756a 100644 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -1,228 +1,228 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->task->index = "Index"; -$lang->task->create = "Create"; -$lang->task->batchCreate = "Batch create"; -$lang->task->batchEdit = "Batch edit"; -$lang->task->import = "Import undone"; -$lang->task->edit = "Update"; -$lang->task->delete = "Delete"; -$lang->task->view = "Info"; -$lang->task->logEfforts = "Efforts"; -$lang->task->record = "Estimate"; -$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->module = 'Module'; -$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->hour = 'Hour'; -$lang->task->beforeConsumed = 'Before consumed'; -$lang->task->consumedThisTime = 'This time consumed'; -$lang->task->estStarted = 'Estimate start'; -$lang->task->realStarted = 'Real start'; -$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->assignTo = $lang->task->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->ditto = 'Ditto'; - -$lang->task->statusList[''] = ''; -$lang->task->statusList['wait'] = 'Pending'; -$lang->task->statusList['doing'] = 'In progress'; -$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 to add task for this story. '; -$lang->task->afterChoices['toTaskList'] = '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 you want to delete this task?"; -$lang->task->copyStoryTitle = "Same as story"; -$lang->task->afterSubmit = "After created"; -$lang->task->successSaved = "Successfully saved"; -$lang->task->delayWarning = " Postponed %s days "; -$lang->task->remindBug = "This task from Bug, update the Bug:%s or not?"; -$lang->task->confirmChangeProject = 'Change project will change module, story and assignedTo also, are you sure?'; -$lang->task->confirmFinish = '"Left" is 0, this task will be done. Are you sure?'; - -$lang->task->error = new stdclass(); -$lang->task->error->consumed = '"Consumed" must be number'; -$lang->task->error->newConsumed = '"Consumed" must be more than consumed before'; - -/* Report. */ -$lang->task->report = new stdclass(); -$lang->task->report->common = 'Report'; -$lang->task->report->select = 'Select'; -$lang->task->report->create = 'Create'; - -$lang->task->report->charts['tasksPerProject'] = 'Project tasks'; -$lang->task->report->charts['tasksPerModule'] = 'Module 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 = new stdclass(); -$lang->task->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->task->report->tasksPerModule = new stdclass(); -$lang->task->report->tasksPerAssignedTo = new stdclass(); -$lang->task->report->tasksPerType = new stdclass(); -$lang->task->report->tasksPerPri = new stdclass(); -$lang->task->report->tasksPerStatus = new stdclass(); -$lang->task->report->tasksPerDeadline = new stdclass(); -$lang->task->report->tasksPerEstimate = new stdclass(); -$lang->task->report->tasksPerLeft = new stdclass(); -$lang->task->report->tasksPerConsumed = new stdclass(); -$lang->task->report->tasksPerFinishedBy = new stdclass(); -$lang->task->report->tasksPerClosedReason = new stdclass(); -$lang->task->report->finishedTasksPerDay = new stdclass(); - -$lang->task->report->tasksPerProject->graph = new stdclass(); -$lang->task->report->tasksPerModule->graph = new stdclass(); -$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); -$lang->task->report->tasksPerType->graph = new stdclass(); -$lang->task->report->tasksPerPri->graph = new stdclass(); -$lang->task->report->tasksPerStatus->graph = new stdclass(); -$lang->task->report->tasksPerDeadline->graph = new stdclass(); -$lang->task->report->tasksPerEstimate->graph = new stdclass(); -$lang->task->report->tasksPerLeft->graph = new stdclass(); -$lang->task->report->tasksPerConsumed->graph = new stdclass(); -$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); -$lang->task->report->tasksPerClosedReason->graph = new stdclass(); -$lang->task->report->finishedTasksPerDay->graph = new stdclass(); - -$lang->task->report->tasksPerProject->graph->xAxisName = 'Project'; -$lang->task->report->tasksPerModule->graph->xAxisName = 'Module'; -$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'; - -$lang->task->placeholder = new stdclass(); -$lang->task->placeholder->estimate = 'The estimated time for this task'; -$lang->task->placeholder->mailto = 'Mail to'; + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->task->index = "Index"; +$lang->task->create = "Create"; +$lang->task->batchCreate = "Batch create"; +$lang->task->batchEdit = "Batch edit"; +$lang->task->import = "Import undone"; +$lang->task->edit = "Update"; +$lang->task->delete = "Delete"; +$lang->task->view = "Info"; +$lang->task->logEfforts = "Efforts"; +$lang->task->record = "Estimate"; +$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->module = 'Module'; +$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->hour = 'Hour'; +$lang->task->beforeConsumed = 'Before consumed'; +$lang->task->consumedThisTime = 'This time consumed'; +$lang->task->estStarted = 'Estimate start'; +$lang->task->realStarted = 'Real start'; +$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->assignTo = $lang->task->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->ditto = 'Ditto'; + +$lang->task->statusList[''] = ''; +$lang->task->statusList['wait'] = 'Pending'; +$lang->task->statusList['doing'] = 'In progress'; +$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 to add task for this story. '; +$lang->task->afterChoices['toTaskList'] = '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 you want to delete this task?"; +$lang->task->copyStoryTitle = "Same as story"; +$lang->task->afterSubmit = "After created"; +$lang->task->successSaved = "Successfully saved"; +$lang->task->delayWarning = " Postponed %s days "; +$lang->task->remindBug = "This task from Bug, update the Bug:%s or not?"; +$lang->task->confirmChangeProject = 'Change project will change module, story and assignedTo also, are you sure?'; +$lang->task->confirmFinish = '"Left" is 0, this task will be done. Are you sure?'; + +$lang->task->error = new stdclass(); +$lang->task->error->consumed = '"Consumed" must be number'; +$lang->task->error->newConsumed = '"Consumed" must be more than consumed before'; + +/* Report. */ +$lang->task->report = new stdclass(); +$lang->task->report->common = 'Report'; +$lang->task->report->select = 'Select'; +$lang->task->report->create = 'Create'; + +$lang->task->report->charts['tasksPerProject'] = 'Project tasks'; +$lang->task->report->charts['tasksPerModule'] = 'Module 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 = new stdclass(); +$lang->task->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->task->report->tasksPerModule = new stdclass(); +$lang->task->report->tasksPerAssignedTo = new stdclass(); +$lang->task->report->tasksPerType = new stdclass(); +$lang->task->report->tasksPerPri = new stdclass(); +$lang->task->report->tasksPerStatus = new stdclass(); +$lang->task->report->tasksPerDeadline = new stdclass(); +$lang->task->report->tasksPerEstimate = new stdclass(); +$lang->task->report->tasksPerLeft = new stdclass(); +$lang->task->report->tasksPerConsumed = new stdclass(); +$lang->task->report->tasksPerFinishedBy = new stdclass(); +$lang->task->report->tasksPerClosedReason = new stdclass(); +$lang->task->report->finishedTasksPerDay = new stdclass(); + +$lang->task->report->tasksPerProject->graph = new stdclass(); +$lang->task->report->tasksPerModule->graph = new stdclass(); +$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); +$lang->task->report->tasksPerType->graph = new stdclass(); +$lang->task->report->tasksPerPri->graph = new stdclass(); +$lang->task->report->tasksPerStatus->graph = new stdclass(); +$lang->task->report->tasksPerDeadline->graph = new stdclass(); +$lang->task->report->tasksPerEstimate->graph = new stdclass(); +$lang->task->report->tasksPerLeft->graph = new stdclass(); +$lang->task->report->tasksPerConsumed->graph = new stdclass(); +$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); +$lang->task->report->tasksPerClosedReason->graph = new stdclass(); +$lang->task->report->finishedTasksPerDay->graph = new stdclass(); + +$lang->task->report->tasksPerProject->graph->xAxisName = 'Project'; +$lang->task->report->tasksPerModule->graph->xAxisName = 'Module'; +$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'; + +$lang->task->placeholder = new stdclass(); +$lang->task->placeholder->estimate = 'The estimated time for this task'; +$lang->task->placeholder->mailto = 'Mail to'; diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index 57c1ef7679..6738a875d4 100644 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -1,228 +1,228 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->task->index = "任务一览"; -$lang->task->create = "建任务"; -$lang->task->batchCreate = "批量添加"; -$lang->task->batchEdit = "批量编辑"; -$lang->task->import = "导入之前未完任务"; -$lang->task->edit = "编辑"; -$lang->task->delete = "删除"; -$lang->task->view = "查看任务"; -$lang->task->logEfforts = "记录工时"; -$lang->task->record = "工时"; -$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->module = '所属模块'; -$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->hour = '小时'; -$lang->task->beforeConsumed = '之前消耗'; -$lang->task->consumedThisTime = '本次消耗'; -$lang->task->estStarted = '预计开始'; -$lang->task->realStarted = '实际开始'; -$lang->task->deadline = '截止日期'; -$lang->task->deadlineAB = '截止'; -$lang->task->status = '任务状态'; -$lang->task->statusCustom = '状态排序'; -$lang->task->desc = '任务描述'; -$lang->task->assign = '指派'; -$lang->task->assignTo = $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->ditto = '同上'; - -$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['toTaskList'] = '返回任务列表'; -$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->confirmChangeProject = '修改项目会导致相应的所属模块、相关需求和指派人发生变化,确定吗?'; -$lang->task->confirmFinish = '"预计剩余"为0,确认将任务状态改为"已完成"吗?'; - -$lang->task->error = new stdclass(); -$lang->task->error->consumed = '"已经消耗"必须为数字'; -$lang->task->error->newConsumed = '"已经消耗"必须大于之前消耗'; - -/* 统计报表。*/ -$lang->task->report = new stdclass(); -$lang->task->report->common = '报表'; -$lang->task->report->select = '请选择报表类型'; -$lang->task->report->create = '生成报表'; - -$lang->task->report->charts['tasksPerProject'] = '项目任务数统计'; -$lang->task->report->charts['tasksPerModule'] = '模块任务数统计'; -$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 = new stdclass(); -$lang->task->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->task->report->tasksPerModule = new stdclass(); -$lang->task->report->tasksPerAssignedTo = new stdclass(); -$lang->task->report->tasksPerType = new stdclass(); -$lang->task->report->tasksPerPri = new stdclass(); -$lang->task->report->tasksPerStatus = new stdclass(); -$lang->task->report->tasksPerDeadline = new stdclass(); -$lang->task->report->tasksPerEstimate = new stdclass(); -$lang->task->report->tasksPerLeft = new stdclass(); -$lang->task->report->tasksPerConsumed = new stdclass(); -$lang->task->report->tasksPerFinishedBy = new stdclass(); -$lang->task->report->tasksPerClosedReason = new stdclass(); -$lang->task->report->finishedTasksPerDay = new stdclass(); - -$lang->task->report->tasksPerProject->graph = new stdclass(); -$lang->task->report->tasksPerModule->graph = new stdclass(); -$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); -$lang->task->report->tasksPerType->graph = new stdclass(); -$lang->task->report->tasksPerPri->graph = new stdclass(); -$lang->task->report->tasksPerStatus->graph = new stdclass(); -$lang->task->report->tasksPerDeadline->graph = new stdclass(); -$lang->task->report->tasksPerEstimate->graph = new stdclass(); -$lang->task->report->tasksPerLeft->graph = new stdclass(); -$lang->task->report->tasksPerConsumed->graph = new stdclass(); -$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); -$lang->task->report->tasksPerClosedReason->graph = new stdclass(); -$lang->task->report->finishedTasksPerDay->graph = new stdclass(); - -$lang->task->report->tasksPerProject->graph->xAxisName = '项目'; -$lang->task->report->tasksPerModule->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'; - -$lang->task->placeholder = new stdclass(); -$lang->task->placeholder->estimate = '对该任务最初的预计'; -$lang->task->placeholder->mailto = '输入用户名进行选择'; + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->task->index = "任务一览"; +$lang->task->create = "建任务"; +$lang->task->batchCreate = "批量添加"; +$lang->task->batchEdit = "批量编辑"; +$lang->task->import = "导入之前未完任务"; +$lang->task->edit = "编辑"; +$lang->task->delete = "删除"; +$lang->task->view = "查看任务"; +$lang->task->logEfforts = "记录工时"; +$lang->task->record = "工时"; +$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->module = '所属模块'; +$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->hour = '小时'; +$lang->task->beforeConsumed = '之前消耗'; +$lang->task->consumedThisTime = '本次消耗'; +$lang->task->estStarted = '预计开始'; +$lang->task->realStarted = '实际开始'; +$lang->task->deadline = '截止日期'; +$lang->task->deadlineAB = '截止'; +$lang->task->status = '任务状态'; +$lang->task->statusCustom = '状态排序'; +$lang->task->desc = '任务描述'; +$lang->task->assign = '指派'; +$lang->task->assignTo = $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->ditto = '同上'; + +$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['toTaskList'] = '返回任务列表'; +$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->confirmChangeProject = '修改项目会导致相应的所属模块、相关需求和指派人发生变化,确定吗?'; +$lang->task->confirmFinish = '"预计剩余"为0,确认将任务状态改为"已完成"吗?'; + +$lang->task->error = new stdclass(); +$lang->task->error->consumed = '"已经消耗"必须为数字'; +$lang->task->error->newConsumed = '"已经消耗"必须大于之前消耗'; + +/* 统计报表。*/ +$lang->task->report = new stdclass(); +$lang->task->report->common = '报表'; +$lang->task->report->select = '请选择报表类型'; +$lang->task->report->create = '生成报表'; + +$lang->task->report->charts['tasksPerProject'] = '项目任务数统计'; +$lang->task->report->charts['tasksPerModule'] = '模块任务数统计'; +$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 = new stdclass(); +$lang->task->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->task->report->tasksPerModule = new stdclass(); +$lang->task->report->tasksPerAssignedTo = new stdclass(); +$lang->task->report->tasksPerType = new stdclass(); +$lang->task->report->tasksPerPri = new stdclass(); +$lang->task->report->tasksPerStatus = new stdclass(); +$lang->task->report->tasksPerDeadline = new stdclass(); +$lang->task->report->tasksPerEstimate = new stdclass(); +$lang->task->report->tasksPerLeft = new stdclass(); +$lang->task->report->tasksPerConsumed = new stdclass(); +$lang->task->report->tasksPerFinishedBy = new stdclass(); +$lang->task->report->tasksPerClosedReason = new stdclass(); +$lang->task->report->finishedTasksPerDay = new stdclass(); + +$lang->task->report->tasksPerProject->graph = new stdclass(); +$lang->task->report->tasksPerModule->graph = new stdclass(); +$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); +$lang->task->report->tasksPerType->graph = new stdclass(); +$lang->task->report->tasksPerPri->graph = new stdclass(); +$lang->task->report->tasksPerStatus->graph = new stdclass(); +$lang->task->report->tasksPerDeadline->graph = new stdclass(); +$lang->task->report->tasksPerEstimate->graph = new stdclass(); +$lang->task->report->tasksPerLeft->graph = new stdclass(); +$lang->task->report->tasksPerConsumed->graph = new stdclass(); +$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); +$lang->task->report->tasksPerClosedReason->graph = new stdclass(); +$lang->task->report->finishedTasksPerDay->graph = new stdclass(); + +$lang->task->report->tasksPerProject->graph->xAxisName = '项目'; +$lang->task->report->tasksPerModule->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'; + +$lang->task->placeholder = new stdclass(); +$lang->task->placeholder->estimate = '对该任务最初的预计'; +$lang->task->placeholder->mailto = '输入用户名进行选择'; diff --git a/module/task/lang/zh-tw.php b/module/task/lang/zh-tw.php index 89232a50d2..7793531812 100644 --- a/module/task/lang/zh-tw.php +++ b/module/task/lang/zh-tw.php @@ -1,223 +1,223 @@ - - * @package task - * @version $Id: zh-tw.php 3872 2012-12-24 00:50:43Z zhujinyonging@gmail.com $ - * @link http://www.zentao.net - */ -$lang->task->index = "任務一覽"; -$lang->task->create = "新增"; -$lang->task->batchCreate = "批量添加"; -$lang->task->batchEdit = "批量編輯"; -$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->module = '所屬模組'; -$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->hour = '小時'; -$lang->task->estStarted = '預計開始'; -$lang->task->realStarted = '實際開始'; -$lang->task->deadline = '截止日期'; -$lang->task->deadlineAB = '截止'; -$lang->task->status = '任務狀態'; -$lang->task->statusCustom = '狀態排序'; -$lang->task->desc = '任務描述'; -$lang->task->assign = '指派'; -$lang->task->assignTo = $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->ditto = '同上'; - -$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['toTaskList'] = '返回任務列表'; -$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->confirmChangeProject = '修改項目會導致相應的所屬模組、相關需求和指派人發生變化,確定嗎?'; - -$lang->task->error = new stdclass(); -$lang->task->error->consumed = '"已經消耗"必須為數字'; - -/* 統計報表。*/ -$lang->task->report = new stdclass(); -$lang->task->report->common = '報表'; -$lang->task->report->select = '請選擇報表類型'; -$lang->task->report->create = '生成報表'; - -$lang->task->report->charts['tasksPerProject'] = '項目任務數統計'; -$lang->task->report->charts['tasksPerModule'] = '模組任務數統計'; -$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 = new stdclass(); -$lang->task->report->options->graph = new stdclass(); -$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 = new stdclass(); -$lang->task->report->tasksPerModule = new stdclass(); -$lang->task->report->tasksPerAssignedTo = new stdclass(); -$lang->task->report->tasksPerType = new stdclass(); -$lang->task->report->tasksPerPri = new stdclass(); -$lang->task->report->tasksPerStatus = new stdclass(); -$lang->task->report->tasksPerDeadline = new stdclass(); -$lang->task->report->tasksPerEstimate = new stdclass(); -$lang->task->report->tasksPerLeft = new stdclass(); -$lang->task->report->tasksPerConsumed = new stdclass(); -$lang->task->report->tasksPerFinishedBy = new stdclass(); -$lang->task->report->tasksPerClosedReason = new stdclass(); -$lang->task->report->finishedTasksPerDay = new stdclass(); - -$lang->task->report->tasksPerProject->graph = new stdclass(); -$lang->task->report->tasksPerModule->graph = new stdclass(); -$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); -$lang->task->report->tasksPerType->graph = new stdclass(); -$lang->task->report->tasksPerPri->graph = new stdclass(); -$lang->task->report->tasksPerStatus->graph = new stdclass(); -$lang->task->report->tasksPerDeadline->graph = new stdclass(); -$lang->task->report->tasksPerEstimate->graph = new stdclass(); -$lang->task->report->tasksPerLeft->graph = new stdclass(); -$lang->task->report->tasksPerConsumed->graph = new stdclass(); -$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); -$lang->task->report->tasksPerClosedReason->graph = new stdclass(); -$lang->task->report->finishedTasksPerDay->graph = new stdclass(); - -$lang->task->report->tasksPerProject->graph->xAxisName = '項目'; -$lang->task->report->tasksPerModule->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'; - -$lang->task->placeholder = new stdclass(); -$lang->task->placeholder->estimate = '對該任務最初的預計'; -$lang->task->placeholder->mailto = '輸入用戶名進行選擇'; + + * @package task + * @version $Id: zh-tw.php 3872 2012-12-24 00:50:43Z zhujinyonging@gmail.com $ + * @link http://www.zentao.net + */ +$lang->task->index = "任務一覽"; +$lang->task->create = "新增"; +$lang->task->batchCreate = "批量添加"; +$lang->task->batchEdit = "批量編輯"; +$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->module = '所屬模組'; +$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->hour = '小時'; +$lang->task->estStarted = '預計開始'; +$lang->task->realStarted = '實際開始'; +$lang->task->deadline = '截止日期'; +$lang->task->deadlineAB = '截止'; +$lang->task->status = '任務狀態'; +$lang->task->statusCustom = '狀態排序'; +$lang->task->desc = '任務描述'; +$lang->task->assign = '指派'; +$lang->task->assignTo = $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->ditto = '同上'; + +$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['toTaskList'] = '返回任務列表'; +$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->confirmChangeProject = '修改項目會導致相應的所屬模組、相關需求和指派人發生變化,確定嗎?'; + +$lang->task->error = new stdclass(); +$lang->task->error->consumed = '"已經消耗"必須為數字'; + +/* 統計報表。*/ +$lang->task->report = new stdclass(); +$lang->task->report->common = '報表'; +$lang->task->report->select = '請選擇報表類型'; +$lang->task->report->create = '生成報表'; + +$lang->task->report->charts['tasksPerProject'] = '項目任務數統計'; +$lang->task->report->charts['tasksPerModule'] = '模組任務數統計'; +$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 = new stdclass(); +$lang->task->report->options->graph = new stdclass(); +$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 = new stdclass(); +$lang->task->report->tasksPerModule = new stdclass(); +$lang->task->report->tasksPerAssignedTo = new stdclass(); +$lang->task->report->tasksPerType = new stdclass(); +$lang->task->report->tasksPerPri = new stdclass(); +$lang->task->report->tasksPerStatus = new stdclass(); +$lang->task->report->tasksPerDeadline = new stdclass(); +$lang->task->report->tasksPerEstimate = new stdclass(); +$lang->task->report->tasksPerLeft = new stdclass(); +$lang->task->report->tasksPerConsumed = new stdclass(); +$lang->task->report->tasksPerFinishedBy = new stdclass(); +$lang->task->report->tasksPerClosedReason = new stdclass(); +$lang->task->report->finishedTasksPerDay = new stdclass(); + +$lang->task->report->tasksPerProject->graph = new stdclass(); +$lang->task->report->tasksPerModule->graph = new stdclass(); +$lang->task->report->tasksPerAssignedTo->graph = new stdclass(); +$lang->task->report->tasksPerType->graph = new stdclass(); +$lang->task->report->tasksPerPri->graph = new stdclass(); +$lang->task->report->tasksPerStatus->graph = new stdclass(); +$lang->task->report->tasksPerDeadline->graph = new stdclass(); +$lang->task->report->tasksPerEstimate->graph = new stdclass(); +$lang->task->report->tasksPerLeft->graph = new stdclass(); +$lang->task->report->tasksPerConsumed->graph = new stdclass(); +$lang->task->report->tasksPerFinishedBy->graph = new stdclass(); +$lang->task->report->tasksPerClosedReason->graph = new stdclass(); +$lang->task->report->finishedTasksPerDay->graph = new stdclass(); + +$lang->task->report->tasksPerProject->graph->xAxisName = '項目'; +$lang->task->report->tasksPerModule->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'; + +$lang->task->placeholder = new stdclass(); +$lang->task->placeholder->estimate = '對該任務最初的預計'; +$lang->task->placeholder->mailto = '輸入用戶名進行選擇'; diff --git a/module/task/model.php b/module/task/model.php index 68887edf2a..9a411b7184 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1,1162 +1,1162 @@ - - * @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('estStarted', '0000-00-00') - ->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') - ->checkIF($task->deadline != '0000-00-00', 'deadline', 'ge', $task->estStarted) - ->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(); - $mails = array(); - for($i = 0; $i < $this->config->task->batchCreate; $i++) - { - if($tasks->type[$i] != '' and $tasks->name[$i] != '' and $tasks->pri[$i] != 0) - { - $data[$i] = new stdclass(); - $data[$i]->story = $tasks->story[$i] != 'ditto' ? ($tasks->story[$i] ? $tasks->story[$i] : 0) : ($i == 0 ? 0 : $data[$i-1]->story); - $data[$i]->type = $tasks->type[$i] == 'ditto' ? ($i == 0 ? '' : $data[$i-1]->type) : $tasks->type[$i]; - $data[$i]->assignedTo = $tasks->assignedTo[$i] == 'ditto' ? ($i == 0 ? '' : $data[$i-1]->assignedTo) : $tasks->assignedTo[$i]; - $data[$i]->name = $tasks->name[$i]; - $data[$i]->desc = $tasks->desc[$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; - - if($task->consumed < $oldTask->consumed) - { - die(js::error($this->lang->task->error->newConsumed)); - } - else if($task->consumed != $oldTask->consumed or $task->left != $oldTask->left) - { - $estimate = new stdClass(); - $estimate->consumed = $task->consumed - $oldTask->consumed; - $estimate->left = $task->left; - $estimate->task = $taskID; - $estimate->account = $this->app->user->account; - $estimate->date = helper::now(); - - $this->dao->insert(TABLE_TASKESTIMATE)->data($estimate) - ->autoCheck() - ->exec(); - } - $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->status != 'wait' and $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); - } - - /** - * Batch update task. - * - * @access public - * @return void - */ - public function batchUpdate() - { - $tasks = array(); - $allChanges = array(); - $now = helper::now(); - $taskIDList = $this->post->taskIDList ? $this->post->taskIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $taskIDList. */ - if($this->session->showSuhosinInfo) array_pop($taskIDList); - - /* Initialize tasks from the post data.*/ - if(!empty($taskIDList)) - { - foreach($taskIDList as $taskID) - { - $oldTask = $this->getById($taskID); - - $task->name = htmlspecialchars($this->post->names[$taskID]); - $task->module = $this->post->modules[$taskID]; - $task->type = $this->post->types[$taskID]; - $task->status = $this->post->statuses[$taskID]; - $task->assignedTo = $task->status == 'closed' ? 'closed' : $this->post->assignedTos[$taskID]; - $task->pri = $this->post->pris[$taskID]; - $task->estimate = $this->post->estimates[$taskID]; - $task->consumed = $this->post->consumeds[$taskID]; - $task->left = $this->post->lefts[$taskID]; - $task->finishedBy = $this->post->finishedBys[$taskID]; - $task->canceledBy = $this->post->canceledBys[$taskID]; - $task->closedBy = $this->post->closedBys[$taskID]; - $task->closedReason = $this->post->closedReasons[$taskID]; - $task->finishedDate = ""; - $task->canceledDate = ""; - $task->closedDate = ""; - $task->lastEditedBy = $this->app->user->account; - $task->lastEditedDate = $now; - if(isset($this->post->assignedTos[$taskID])) - { - $task->assignedDate = $this->post->assignedTos[$taskID] == $oldTask->assignedTo ? $oldTask->assignedDate : $now; - } - - switch($task->status) - { - case 'done': - { - $task->left = 0; - if(!$task->finishedBy) $task->finishedBy = $this->app->user->account; - if(!$task->finishedDate) $task->finishedDate = $now; - if($task->closedReason) $task->closedDate = $now; - } - break; - case 'cancel': - { - $task->assignedTo = $oldTask->openedBy; - $task->assignedDate = $now; - - if(!$task->canceledBy) $task->canceledBy = $this->app->user->account; - if(!$task->canceledDate) $task->canceledDate = $now; - } - break; - case 'closed': - { - if(!$task->closedBy) $task->closedBy = $this->app->user->account; - if(!$task->closedDate) $task->closedDate = $now; - } - break; - case 'wait': - { - if($task->consumed > 0 and $task->left > 0) $task->status = 'doing'; - if($task->left == $oldTask->left and $task->consumed == 0) $task->left = $task->estimate; - } - default:break; - } - if($task->assignedTo) $task->assignedDate = $now; - - $tasks[$taskID] = $task; - unset($task); - } - - /* Update task data. */ - foreach($tasks as $taskID => $task) - { - $oldTask = $this->getById($taskID); - $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->consumed != false, 'consumed', 'float') - ->checkIF($task->left != false, 'left', 'float') - ->checkIF($task->left == 0 and $task->status != 'cancel' and $task->status != 'closed' and $task->consumed != 0, '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($task->status == 'done' and $task->closedReason) $this->dao->update(TABLE_TASK)->set('status')->eq('closed')->where('id')->eq($taskID)->exec(); - - if($oldTask->story != false) $this->loadModel('story')->setStage($oldTask->story); - if(!dao::isError()) - { - $allChanges[$taskID] = common::createChanges($oldTask, $task); - } - else - { - die(js::error('task#' . $taskID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - /** - * 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); - $task = fixer::input('post') - ->cleanFloat('left') - ->setDefault('lastEditedBy', $this->app->user->account) - ->setDefault('lastEditedDate', $now) - ->remove('comment') - ->get(); - - $this->dao->update(TABLE_TASK) - ->data($task) - ->autoCheck() - ->check('left', 'float') - ->where('id')->eq($taskID)->exec(); - - if(!dao::isError()) return common::createChanges($oldTask, $task); - } - - /** - * 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); - } - - /** - * Record estimate and left of task. - * - * @param int $taskID - * @access public - * @return void - */ - public function record($taskID) - { - $oldTask = $this->getById($taskID); - $estimate = fixer::input('post') - ->setDefault('account', $this->app->user->account) - ->setDefault('task', $taskID) - ->setDefault('date', helper::now()) - ->cleanFloat('consumed, left') - ->remove('comment') - ->get(); - $this->dao->insert(TABLE_TASKESTIMATE)->data($estimate) - ->autoCheck() - ->exec(); - - $consumed = $this->getBeforeConsumed($taskID); - $this->dao->update(TABLE_TASK) - ->set('consumed')->eq($consumed) - ->set('`left`')->eq($estimate->left) - ->where('id')->eq($taskID) - ->exec(); - $task = $this->getById($taskID); - 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(); - - if(!is_numeric($task->consumed)) die(js::error($this->lang->task->error->consumed));; - - $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('_recPerPage') - ->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 - * @param bool $setImgSize - * @access public - * @return object|bool - */ - public function getById($taskID, $setImgSize = false) - { - $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; - if($setImgSize) $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 list of a project. - * - * @param int $projectID - * @param array|string $moduleIds - * @param string $status - * @param string $orderBy - * @param object $pager - * @access public - * @return array - */ - public function getTasksByModule($projectID = 0, $moduleIds = 0, $orderBy = 'id_desc', $pager = null) - { - $orderBy = str_replace('status', 'statusCustom', $orderBy); - $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) - ->beginIF(!empty($moduleIds))->andWhere('t1.module')->in($moduleIds)->fi() - ->andWhere('t1.deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task'); - - if($tasks) return $this->processTasks($tasks); - return array(); - } - - /** - * 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(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task', $type == 'needconfirm' ? false : true); - - 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 - * @param object $pager - * @access public - * @return array - */ - public function getUserTasks($account, $type = 'assignedto', $limit = 0, $pager = null, $orderBy="id_desc") - { - $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($orderBy) - ->beginIF($limit > 0)->limit($limit)->fi() - ->page($pager) - ->fetchAll(); - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task'); - - 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; - } - - /** - * Get before consumed. - * - * @param int $taskID - * @access public - * @return int - */ - public function getBeforeConsumed($taskID) - { - $tasks = $this->dao->select('consumed')->from(TABLE_TASKESTIMATE)->where('task')->eq($taskID)->fetchAll(); - $beforeConsumed = 0; - foreach($tasks as $task) - { - $beforeConsumed += $task->consumed; - } - return $beforeConsumed; - } - - /** - * Batch process tasks. - * - * @param int $tasks - * @access private - * @return void - */ - public function processTasks($tasks) - { - foreach($tasks as $task) - { - $task = $this->processTask($task); - } - return $tasks; - } - - /** - * Process a task, judge it's status. - * - * @param object $task - * @access private - * @return object - */ - public function processTask($task) - { - $today = helper::today(); - - /* Delayed or not?. */ - if($task->status !== 'done' and $task->status !== 'cancel' and $task->status != 'closed') - { - 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 $task; - } - - /** - * Set the status field of a task. - * - * @param object $task - * @access private - * @return void - */ - public 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->reportCondition()) - ->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 module - * - * @access public - * @return array - */ - public function getDataOftasksPerModule() - { - $datas = $this->dao->select('module as name, count(*) as value') - ->from(TABLE_TASK)->alias('t1') - ->where($this->reportCondition()) - ->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 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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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->reportCondition()) - ->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; - } - - /** - * Judge an action is clickable or not. - * - * @param object $task - * @param string $action - * @access public - * @return bool - */ - public function isClickable($task, $action) - { - $action = strtolower($action); - - if($action == 'assignto') return $task->status != 'closed' and $task->status != 'cancel'; - if($action == 'start') return $task->status != 'doing' and $task->status != 'closed' and $task->status != 'cancel'; - if($action == 'record') return $task->status != 'done' and $task->status != 'closed' and $task->status != 'cancel'; - if($action == 'finish') return $task->status != 'done' and $task->status != 'closed' and $task->status != 'cancel'; - if($action == 'close') return $task->status == 'done' or $task->status == 'cancel'; - if($action == 'activate') return $task->status == 'done' or $task->status == 'closed' or $task->status == 'cancel' ; - if($action == 'cancel') return $task->status != 'done ' and $task->status != 'closed' and $task->status != 'cancel'; - - return true; - } - - /** - * Get report condition from session. - * - * @access public - * @return void - */ - public function reportCondition() - { - if(!$this->session->taskOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->taskQueryCondition) . ')'; - return $this->session->taskQueryCondition; - } -} + + * @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('estStarted', '0000-00-00') + ->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') + ->checkIF($task->deadline != '0000-00-00', 'deadline', 'ge', $task->estStarted) + ->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(); + $mails = array(); + for($i = 0; $i < $this->config->task->batchCreate; $i++) + { + if($tasks->type[$i] != '' and $tasks->name[$i] != '' and $tasks->pri[$i] != 0) + { + $data[$i] = new stdclass(); + $data[$i]->story = $tasks->story[$i] != 'ditto' ? ($tasks->story[$i] ? $tasks->story[$i] : 0) : ($i == 0 ? 0 : $data[$i-1]->story); + $data[$i]->type = $tasks->type[$i] == 'ditto' ? ($i == 0 ? '' : $data[$i-1]->type) : $tasks->type[$i]; + $data[$i]->assignedTo = $tasks->assignedTo[$i] == 'ditto' ? ($i == 0 ? '' : $data[$i-1]->assignedTo) : $tasks->assignedTo[$i]; + $data[$i]->name = $tasks->name[$i]; + $data[$i]->desc = $tasks->desc[$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; + + if($task->consumed < $oldTask->consumed) + { + die(js::error($this->lang->task->error->newConsumed)); + } + else if($task->consumed != $oldTask->consumed or $task->left != $oldTask->left) + { + $estimate = new stdClass(); + $estimate->consumed = $task->consumed - $oldTask->consumed; + $estimate->left = $task->left; + $estimate->task = $taskID; + $estimate->account = $this->app->user->account; + $estimate->date = helper::now(); + + $this->dao->insert(TABLE_TASKESTIMATE)->data($estimate) + ->autoCheck() + ->exec(); + } + $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->status != 'wait' and $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); + } + + /** + * Batch update task. + * + * @access public + * @return void + */ + public function batchUpdate() + { + $tasks = array(); + $allChanges = array(); + $now = helper::now(); + $taskIDList = $this->post->taskIDList ? $this->post->taskIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $taskIDList. */ + if($this->session->showSuhosinInfo) array_pop($taskIDList); + + /* Initialize tasks from the post data.*/ + if(!empty($taskIDList)) + { + foreach($taskIDList as $taskID) + { + $oldTask = $this->getById($taskID); + + $task->name = htmlspecialchars($this->post->names[$taskID]); + $task->module = $this->post->modules[$taskID]; + $task->type = $this->post->types[$taskID]; + $task->status = $this->post->statuses[$taskID]; + $task->assignedTo = $task->status == 'closed' ? 'closed' : $this->post->assignedTos[$taskID]; + $task->pri = $this->post->pris[$taskID]; + $task->estimate = $this->post->estimates[$taskID]; + $task->consumed = $this->post->consumeds[$taskID]; + $task->left = $this->post->lefts[$taskID]; + $task->finishedBy = $this->post->finishedBys[$taskID]; + $task->canceledBy = $this->post->canceledBys[$taskID]; + $task->closedBy = $this->post->closedBys[$taskID]; + $task->closedReason = $this->post->closedReasons[$taskID]; + $task->finishedDate = ""; + $task->canceledDate = ""; + $task->closedDate = ""; + $task->lastEditedBy = $this->app->user->account; + $task->lastEditedDate = $now; + if(isset($this->post->assignedTos[$taskID])) + { + $task->assignedDate = $this->post->assignedTos[$taskID] == $oldTask->assignedTo ? $oldTask->assignedDate : $now; + } + + switch($task->status) + { + case 'done': + { + $task->left = 0; + if(!$task->finishedBy) $task->finishedBy = $this->app->user->account; + if(!$task->finishedDate) $task->finishedDate = $now; + if($task->closedReason) $task->closedDate = $now; + } + break; + case 'cancel': + { + $task->assignedTo = $oldTask->openedBy; + $task->assignedDate = $now; + + if(!$task->canceledBy) $task->canceledBy = $this->app->user->account; + if(!$task->canceledDate) $task->canceledDate = $now; + } + break; + case 'closed': + { + if(!$task->closedBy) $task->closedBy = $this->app->user->account; + if(!$task->closedDate) $task->closedDate = $now; + } + break; + case 'wait': + { + if($task->consumed > 0 and $task->left > 0) $task->status = 'doing'; + if($task->left == $oldTask->left and $task->consumed == 0) $task->left = $task->estimate; + } + default:break; + } + if($task->assignedTo) $task->assignedDate = $now; + + $tasks[$taskID] = $task; + unset($task); + } + + /* Update task data. */ + foreach($tasks as $taskID => $task) + { + $oldTask = $this->getById($taskID); + $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->consumed != false, 'consumed', 'float') + ->checkIF($task->left != false, 'left', 'float') + ->checkIF($task->left == 0 and $task->status != 'cancel' and $task->status != 'closed' and $task->consumed != 0, '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($task->status == 'done' and $task->closedReason) $this->dao->update(TABLE_TASK)->set('status')->eq('closed')->where('id')->eq($taskID)->exec(); + + if($oldTask->story != false) $this->loadModel('story')->setStage($oldTask->story); + if(!dao::isError()) + { + $allChanges[$taskID] = common::createChanges($oldTask, $task); + } + else + { + die(js::error('task#' . $taskID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + /** + * 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); + $task = fixer::input('post') + ->cleanFloat('left') + ->setDefault('lastEditedBy', $this->app->user->account) + ->setDefault('lastEditedDate', $now) + ->remove('comment') + ->get(); + + $this->dao->update(TABLE_TASK) + ->data($task) + ->autoCheck() + ->check('left', 'float') + ->where('id')->eq($taskID)->exec(); + + if(!dao::isError()) return common::createChanges($oldTask, $task); + } + + /** + * 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); + } + + /** + * Record estimate and left of task. + * + * @param int $taskID + * @access public + * @return void + */ + public function record($taskID) + { + $oldTask = $this->getById($taskID); + $estimate = fixer::input('post') + ->setDefault('account', $this->app->user->account) + ->setDefault('task', $taskID) + ->setDefault('date', helper::now()) + ->cleanFloat('consumed, left') + ->remove('comment') + ->get(); + $this->dao->insert(TABLE_TASKESTIMATE)->data($estimate) + ->autoCheck() + ->exec(); + + $consumed = $this->getBeforeConsumed($taskID); + $this->dao->update(TABLE_TASK) + ->set('consumed')->eq($consumed) + ->set('`left`')->eq($estimate->left) + ->where('id')->eq($taskID) + ->exec(); + $task = $this->getById($taskID); + 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(); + + if(!is_numeric($task->consumed)) die(js::error($this->lang->task->error->consumed));; + + $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('_recPerPage') + ->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 + * @param bool $setImgSize + * @access public + * @return object|bool + */ + public function getById($taskID, $setImgSize = false) + { + $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; + if($setImgSize) $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 list of a project. + * + * @param int $projectID + * @param array|string $moduleIds + * @param string $status + * @param string $orderBy + * @param object $pager + * @access public + * @return array + */ + public function getTasksByModule($projectID = 0, $moduleIds = 0, $orderBy = 'id_desc', $pager = null) + { + $orderBy = str_replace('status', 'statusCustom', $orderBy); + $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) + ->beginIF(!empty($moduleIds))->andWhere('t1.module')->in($moduleIds)->fi() + ->andWhere('t1.deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task'); + + if($tasks) return $this->processTasks($tasks); + return array(); + } + + /** + * 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(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task', $type == 'needconfirm' ? false : true); + + 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 + * @param object $pager + * @access public + * @return array + */ + public function getUserTasks($account, $type = 'assignedto', $limit = 0, $pager = null, $orderBy="id_desc") + { + $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($orderBy) + ->beginIF($limit > 0)->limit($limit)->fi() + ->page($pager) + ->fetchAll(); + + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task'); + + 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; + } + + /** + * Get before consumed. + * + * @param int $taskID + * @access public + * @return int + */ + public function getBeforeConsumed($taskID) + { + $tasks = $this->dao->select('consumed')->from(TABLE_TASKESTIMATE)->where('task')->eq($taskID)->fetchAll(); + $beforeConsumed = 0; + foreach($tasks as $task) + { + $beforeConsumed += $task->consumed; + } + return $beforeConsumed; + } + + /** + * Batch process tasks. + * + * @param int $tasks + * @access private + * @return void + */ + public function processTasks($tasks) + { + foreach($tasks as $task) + { + $task = $this->processTask($task); + } + return $tasks; + } + + /** + * Process a task, judge it's status. + * + * @param object $task + * @access private + * @return object + */ + public function processTask($task) + { + $today = helper::today(); + + /* Delayed or not?. */ + if($task->status !== 'done' and $task->status !== 'cancel' and $task->status != 'closed') + { + 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 $task; + } + + /** + * Set the status field of a task. + * + * @param object $task + * @access private + * @return void + */ + public 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->reportCondition()) + ->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 module + * + * @access public + * @return array + */ + public function getDataOftasksPerModule() + { + $datas = $this->dao->select('module as name, count(*) as value') + ->from(TABLE_TASK)->alias('t1') + ->where($this->reportCondition()) + ->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 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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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->reportCondition()) + ->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; + } + + /** + * Judge an action is clickable or not. + * + * @param object $task + * @param string $action + * @access public + * @return bool + */ + public function isClickable($task, $action) + { + $action = strtolower($action); + + if($action == 'assignto') return $task->status != 'closed' and $task->status != 'cancel'; + if($action == 'start') return $task->status != 'doing' and $task->status != 'closed' and $task->status != 'cancel'; + if($action == 'record') return $task->status != 'done' and $task->status != 'closed' and $task->status != 'cancel'; + if($action == 'finish') return $task->status != 'done' and $task->status != 'closed' and $task->status != 'cancel'; + if($action == 'close') return $task->status == 'done' or $task->status == 'cancel'; + if($action == 'activate') return $task->status == 'done' or $task->status == 'closed' or $task->status == 'cancel' ; + if($action == 'cancel') return $task->status != 'done ' and $task->status != 'closed' and $task->status != 'cancel'; + + return true; + } + + /** + * Get report condition from session. + * + * @access public + * @return void + */ + public function reportCondition() + { + if(!$this->session->taskOnlyCondition) return 'id in (' . preg_replace('/SELECT .* FROM/', 'SELECT t1.id FROM', $this->session->taskQueryCondition) . ')'; + return $this->session->taskQueryCondition; + } +} diff --git a/module/task/view/activate.html.php b/module/task/view/activate.html.php index c33c25105a..a5b37b7599 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;?>task->hour;?>
          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;?>task->hour;?>
          comment;?>
          + goback, $this->session->taskList); + ?> +
          + +
          + diff --git a/module/task/view/assignto.html.php b/module/task/view/assignto.html.php index c18868a7a5..702267c65c 100644 --- a/module/task/view/assignto.html.php +++ b/module/task/view/assignto.html.php @@ -1,35 +1,35 @@ - - * @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;?>
          task->left;?>left, "class='text-3'") . $lang->task->hour;?>
          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;?>
          task->left;?>left, "class='text-3'") . $lang->task->hour;?>
          comment;?>
          goback, $this->session->taskList);?>
          + +
          + diff --git a/module/task/view/batchcreate.html.php b/module/task/view/batchcreate.html.php index ff8777d2ff..33236790a5 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);?> -
          - - - - - - - - - - - - - task->batchCreate; $i++):?> - - task->typeList['ditto'] = $lang->task->ditto; $type = $i == 0 ? '' : 'ditto'; - $members['ditto'] = $lang->task->ditto; $member = $i == 0 ? '' : 'ditto'; - ?> - - - - - - - - - - - - - - -
          task->project . $lang->colon . $lang->task->batchCreate;?>
          idAB;?>task->story;?>task->name;?>typeAB;?>task->assignedTo;?>task->estimateAB;?>task->desc;?>task->pri;?>
          task->typeList, $type, 'class=select-1');?>task->priList, $pri, 'class=select-1');?>
          -
          - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +task->batchCreate);?> +
          + + + + + + + + + + + + + task->batchCreate; $i++):?> + + task->typeList['ditto'] = $lang->task->ditto; $type = $i == 0 ? '' : 'ditto'; + $members['ditto'] = $lang->task->ditto; $member = $i == 0 ? '' : 'ditto'; + ?> + + + + + + + + + + + + + + +
          task->project . $lang->colon . $lang->task->batchCreate;?>
          idAB;?>task->story;?>task->name;?>typeAB;?>task->assignedTo;?>task->estimateAB;?>task->desc;?>task->pri;?>
          task->typeList, $type, 'class=select-1');?>task->priList, $pri, 'class=select-1');?>
          +
          + diff --git a/module/task/view/batchedit.html.php b/module/task/view/batchedit.html.php index 8bbce7e7da..3eaede4ff6 100755 --- a/module/task/view/batchedit.html.php +++ b/module/task/view/batchedit.html.php @@ -1,55 +1,55 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          "> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->common . $lang->colon . $lang->task->batchEdit;?>
          idAB;?> task->name?>task->module;?>task->assignedTo;?>typeAB;?>task->status;?>task->pri;?>task->estimateAB?>task->consumedAB?>task->leftAB?>task->finishedBy;?>task->closedBy;?>task->closedReason;?>
          id . html::hidden("taskIDList[$task->id]", $task->id);?>id]", $task->name, 'class=text-1');?>id]", $modules, $task->module, 'class=select-1');?>id]", $members, $task->assignedTo, 'class=select-1');?>id]", $lang->task->typeList, $task->type, 'class=select-1');?>id]", $lang->task->statusList, $task->status, 'class=select-1');?>id]", (array)$lang->task->priList, $task->pri, 'class=select-1');?>id]", $task->estimate, 'class=text-1');?>id]", $task->consumed, 'class=text-1');?>id]", $task->left, 'class=text-1');?>id]", $members, $task->finishedBy, 'class=select-1');?>id]", $members, $task->closedBy, 'class=select-1');?>id]", $lang->task->reasonList, $task->closedReason, 'class=select-1');?>
          -
          - + + * @package task + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          "> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->common . $lang->colon . $lang->task->batchEdit;?>
          idAB;?> task->name?>task->module;?>task->assignedTo;?>typeAB;?>task->status;?>task->pri;?>task->estimateAB?>task->consumedAB?>task->leftAB?>task->finishedBy;?>task->closedBy;?>task->closedReason;?>
          id . html::hidden("taskIDList[$task->id]", $task->id);?>id]", $task->name, 'class=text-1');?>id]", $modules, $task->module, 'class=select-1');?>id]", $members, $task->assignedTo, 'class=select-1');?>id]", $lang->task->typeList, $task->type, 'class=select-1');?>id]", $lang->task->statusList, $task->status, 'class=select-1');?>id]", (array)$lang->task->priList, $task->pri, 'class=select-1');?>id]", $task->estimate, 'class=text-1');?>id]", $task->consumed, 'class=text-1');?>id]", $task->left, 'class=text-1');?>id]", $members, $task->finishedBy, 'class=select-1');?>id]", $members, $task->closedBy, 'class=select-1');?>id]", $lang->task->reasonList, $task->closedReason, 'class=select-1');?>
          +
          + diff --git a/module/task/view/browse.html.php b/module/task/view/browse.html.php index 43402665c4..194af54c67 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 740a717826..ed2ac475ce 100644 --- a/module/task/view/cancel.html.php +++ b/module/task/view/cancel.html.php @@ -1,25 +1,25 @@ - - * @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 33627e458e..bc38b90a27 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 382fc7fd96..b9285c627b 100644 --- a/module/task/view/create.html.php +++ b/module/task/view/create.html.php @@ -1,104 +1,104 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - -task->placeholder, 'json'); ?> - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          - task->create;?> -
          - id", $lang->project->importTask); - common::printLink('project', 'importBug', "projectID=$project->id", $lang->project->importBug); - ?> -
          -
          task->project;?>name;?>
          task->module;?>
          task->assignedTo;?>
          task->story;?> - - preview;?> -
          task->name;?> - task->copyStoryTitle, 'onclick=copyStoryTitle()');?> -
          task->desc;?>
          task->pri;?>task->priList, '', 'class=select-3');?> -
          task->estimate;?>task->hour;?>
          task->estStarted;?>
          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->placeholder, 'json'); ?> + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          + task->create;?> +
          + id", $lang->project->importTask); + common::printLink('project', 'importBug', "projectID=$project->id", $lang->project->importBug); + ?> +
          +
          task->project;?>name;?>
          task->module;?>
          task->assignedTo;?>
          task->story;?> + + preview;?> +
          task->name;?> + task->copyStoryTitle, 'onclick=copyStoryTitle()');?> +
          task->desc;?>
          task->pri;?>task->priList, '', 'class=select-3');?> +
          task->estimate;?>task->hour;?>
          task->estStarted;?>
          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 965bab5852..18d1c3a06f 100644 --- a/module/task/view/edit.html.php +++ b/module/task/view/edit.html.php @@ -1,161 +1,161 @@ - - * @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;?>project, 'class="select-1" onchange="loadAll(this.value)"');?>
          task->module;?>module);?>
          task->story;?>story, 'class=select-1');?>
          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->estStarted;?>estStarted, "class='text-1 date'");?>
          task->realStarted;?>realStarted, "class='text-1 date'");?>
          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;?>project, 'class="select-1" onchange="loadAll(this.value)"');?>
          task->module;?>module);?>
          task->story;?>story, 'class=select-1');?>
          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->estStarted;?>estStarted, "class='text-1 date'");?>
          task->realStarted;?>realStarted, "class='text-1 date'");?>
          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 81a6aeff3d..d69bccde53 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 4e87ddb9d8..ad68339f4d 100644 --- a/module/task/view/finish.html.php +++ b/module/task/view/finish.html.php @@ -1,36 +1,36 @@ - - * @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'") . $lang->task->hour;?>
          task->finishedDate;?>
          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'") . $lang->task->hour;?>
          task->finishedDate;?>
          comment;?>
          goback, $this->session->taskList);?>
          + +
          + diff --git a/module/task/view/import.html.php b/module/task/view/import.html.php index 99527942ac..da9f547dad 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/record.html.php b/module/task/view/record.html.php index cba928d728..5172f3315d 100644 --- a/module/task/view/record.html.php +++ b/module/task/view/record.html.php @@ -1,40 +1,40 @@ - - * @package task - * @version $Id: record.html.php 935 2013-01-08 07:49:24Z wwccss@gmail.com $ - * @link http://www.zentao.net - */ -?> - -task->confirmFinish);?> -
          - - - - - - - - - - - - - - - - - - - - - -
          name;?>
          task->beforeConsumed;?>task->hour;?>
          task->consumedThisTime;?>task->hour;?>
          task->left;?>task->hour;?>
          comment;?>
          goback, $this->session->taskList); ?>
          - -
          - + + * @package task + * @version $Id: record.html.php 935 2013-01-08 07:49:24Z wwccss@gmail.com $ + * @link http://www.zentao.net + */ +?> + +task->confirmFinish);?> +
          + + + + + + + + + + + + + + + + + + + + + +
          name;?>
          task->beforeConsumed;?>task->hour;?>
          task->consumedThisTime;?>task->hour;?>
          task->left;?>task->hour;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/task/view/report.html.php b/module/task/view/report.html.php index 70f94114a3..d2aff9159b 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;?>
          -
          createLink('project', 'task', "projectID=$projectID&browseType=$browseType")); ?>
          -
          - - - - - - - -
          -
          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;?>
          +
          createLink('project', 'task', "projectID=$projectID&browseType=$browseType")); ?>
          +
          + + + + + + + +
          +
          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 b2dacdc382..a1412b21e4 100644 --- a/module/task/view/sendmail.html.php +++ b/module/task/view/sendmail.html.php @@ -1,39 +1,39 @@ - - * @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);?> -
          -
          - task->legendDesc;?> -
          - desc, 'src="data/upload')) - { - $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); - $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); - } - echo $task->desc; - ?> -
          -
          -
          + + * @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);?> +
          +
          + task->legendDesc;?> +
          + desc, 'src="data/upload')) + { + $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); + $task->desc = str_replace('server->http_host . $this->config->webRoot, $task->desc); + } + echo $task->desc; + ?> +
          +
          +
          diff --git a/module/task/view/start.html.php b/module/task/view/start.html.php index 3b23a54e2b..c60aaa844c 100644 --- a/module/task/view/start.html.php +++ b/module/task/view/start.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->realStarted;?>
          task->consumed;?>consumed, "class='text-2'") . $lang->task->hour;?>
          task->left;?>left, "class='text-2'") . $lang->task->hour;?>
          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->realStarted;?>
          task->consumed;?>consumed, "class='text-2'") . $lang->task->hour;?>
          task->left;?>left, "class='text-2'") . $lang->task->hour;?>
          comment;?>
          goback, $this->session->taskList); ?>
          + +
          + diff --git a/module/task/view/view.html.php b/module/task/view/view.html.php index 606e7337b7..a926a0bd3c 100644 --- a/module/task/view/view.html.php +++ b/module/task/view/view.html.php @@ -1,208 +1,208 @@ - - * @package task - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          - id $task->name"; - if($task->fromBug != 0) $name .= "({$lang->task->fromBug}$lang->colon$task->fromBug)"; - ?> -
          '>
          -
          - session->taskList != false ? $app->session->taskList : $this->createLink('project', 'browse', "projectID=$task->project"); - $actionLinks = ''; - if(!$task->deleted) - { - ob_start(); - common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task); - common::printIcon('task', 'start', "taskID=$task->id", $task); - common::printIcon('task', 'record', "taskID=$task->id", $task); - common::printIcon('task', 'finish', "taskID=$task->id", $task); - common::printIcon('task', 'close', "taskID=$task->id", $task); - common::printIcon('task', 'activate', "taskID=$task->id", $task); - common::printIcon('task', 'cancel', "taskID=$task->id", $task); - - common::printDivider(); - common::printIcon('task', 'edit', "taskID=$task->id"); - common::printCommentIcon('task'); - common::printIcon('task', 'delete',"projectID=$task->project&taskID=$task->id", '', 'button', '', 'hiddenwin'); - - common::printDivider(); - common::printRPN($browseLink, $preAndNext); - - $actionLinks = ob_get_contents(); - ob_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
          -
          - - - - - - - -
          -
          - task->legendDesc;?> -
          desc;?>
          -
          - fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true'));?> - - - -
          -
          - task->legendBasic;?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          task->project;?>project", $project->name)) echo $project->name;?>
          task->module;?> - $module) - { - if(!common::printLink('project', 'task', "projectID=$task->project&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; - if(isset($modulePath[$key + 1])) echo $lang->arrow; - } - } - ?> -
          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->estStarted;?>estStarted;?>
          task->realStarted;?>realStarted; ?>
          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 + */ +?> + +
          + id $task->name"; + if($task->fromBug != 0) $name .= "({$lang->task->fromBug}$lang->colon$task->fromBug)"; + ?> +
          '>
          +
          + session->taskList != false ? $app->session->taskList : $this->createLink('project', 'browse', "projectID=$task->project"); + $actionLinks = ''; + if(!$task->deleted) + { + ob_start(); + common::printIcon('task', 'assignTo', "projectID=$task->project&taskID=$task->id", $task); + common::printIcon('task', 'start', "taskID=$task->id", $task); + common::printIcon('task', 'record', "taskID=$task->id", $task); + common::printIcon('task', 'finish', "taskID=$task->id", $task); + common::printIcon('task', 'close', "taskID=$task->id", $task); + common::printIcon('task', 'activate', "taskID=$task->id", $task); + common::printIcon('task', 'cancel', "taskID=$task->id", $task); + + common::printDivider(); + common::printIcon('task', 'edit', "taskID=$task->id"); + common::printCommentIcon('task'); + common::printIcon('task', 'delete',"projectID=$task->project&taskID=$task->id", '', 'button', '', 'hiddenwin'); + + common::printDivider(); + common::printRPN($browseLink, $preAndNext); + + $actionLinks = ob_get_contents(); + ob_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
          +
          + + + + + + + +
          +
          + task->legendDesc;?> +
          desc;?>
          +
          + fetch('file', 'printFiles', array('files' => $task->files, 'fieldset' => 'true'));?> + + + +
          +
          + task->legendBasic;?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          task->project;?>project", $project->name)) echo $project->name;?>
          task->module;?> + $module) + { + if(!common::printLink('project', 'task', "projectID=$task->project&browseType=byModule¶m=$module->id", $module->name)) echo $module->name; + if(isset($modulePath[$key + 1])) echo $lang->arrow; + } + } + ?> +
          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->estStarted;?>estStarted;?>
          task->realStarted;?>realStarted; ?>
          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 1ec36d040f..f9cc1822e9 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -1,653 +1,653 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -class testcase extends control -{ - public $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) - ->page($pager) - ->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. - $caseQuery = $this->loadModel('search')->replaceDynamic($caseQuery); - $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 .*/ - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', $browseType == 'needconfirm' ? false : true); - - /* 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->loadModel('search')->setSearchParams($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 = new stdclass(); - $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=$productID&browseType=byModule¶m=$moduleID"), '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 = "CASE #$case->id $case->title - " . $this->products[$productID]; - $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('testcase', $caseID); - - $this->display(); - } - - /** - * Edit a case. - * - * @param int $caseID - * @access public - * @return void - */ - public function edit($caseID, $comment = false) - { - $this->loadModel('story'); - - if(!empty($_POST)) - { - $changes = array(); - $files = array(); - if($comment == false) - { - $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(); - } - - /** - * Batch edit case. - * - * @param string $from example:testcaseBrowse,testtaskCases,testcaseBatchEdit - * @param int $productID - * @param string $orderBy - * @access public - * @return void - */ - public function batchEdit($from = '', $productID = 0, $orderBy = '') - { - if($from == 'testcaseBrowse' or $from == 'testtaskCases') - { - /* Init vars. */ - $orderBy = $orderBy ? $orderBy : 'id_desc'; - $caseIDList = $this->post->caseIDList ? $this->post->caseIDList : array(); - $product = $this->product->getByID($productID); - $editedCases = array(); - $columns = 7; - $showSuhosinInfo = false; - - /* Get all cases. */ - $allCases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($caseIDList)->orderBy($orderBy)->fetchAll('id'); - - /* Set product menu. */ - $this->testcase->setMenu($this->products, $productID); - - /* Initialize the cases whose need to edited. */ - foreach($allCases as $case) if(in_array($case->id, $caseIDList)) $editedCases[$case->id] = $case; - - /* Judge whether the editedTasks is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedCases), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - $this->view->header->title = $product->name . $this->lang->colon . $this->lang->testcase->batchEdit; - $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); - $this->view->position[] = $this->lang->testcase->common; - $this->view->position[] = $this->lang->testcase->batchEdit; - - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); - $this->view->productID = $productID; - $this->view->editedCases = $editedCases; - $this->view->users = $this->user->getPairs('nodeleted,qafirst'); - - $this->display(); - } - elseif($from == 'testcaseBatchEdit') - { - if(!empty($_POST)) - { - $allChanges = $this->testcase->batchUpdate(); - if($allChanges) - { - foreach($allChanges as $caseID => $changes ) - { - $actionID = $this->loadModel('action')->create('case', $caseID, 'Edited'); - $this->action->logHistory($actionID, $changes); - } - } - } - die(js::locate($this->session->caseList, 'parent')); - } - } - - /** - * 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 int $productID - * @param string $orderBy - * @param int $taskID - * @access public - * @return void - */ - public function export($productID, $orderBy, $taskID = 0) - { - 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. */ - if($this->session->testcaseOnlyCondition) - { - if($taskID) - { - $caseIDList = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs(); - $cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition)->andWhere('id')->in($caseIDList) - ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() - ->orderBy($orderBy)->fetchAll('id'); - } - else - { - $cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition) - ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() - ->orderBy($orderBy)->fetchAll('id'); - } - } - else - { - $cases = array(); - $orderBy = " ORDER BY " . str_replace(array('|', '^A', '_'), ' ', $orderBy); - $stmt = $this->dbh->query($this->session->testcaseQueryCondition . $orderBy); - while($row = $stmt->fetch()) - { - $caseID = isset($row->case) ? $row->case : $row->id; - if($this->post->exportType == 'selected' and strpos(",{$this->cookie->checkedItem},", ",$caseID,") === false) continue; - $cases[$caseID] = $row; - $row->id = $caseID; - } - } - - /* 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'); - $relatedModules = array('0' => '/') + $relatedModules; - - foreach($cases as $case) - { - $case->stepDesc = ''; - $case->stepExpect = ''; - if(isset($relatedSteps[$case->id])) - { - $i = 1; - foreach($relatedSteps[$case->id] as $step) - { - if($step->version != $case->version) continue; - $sign = (in_array($this->post->fileType, array('html', 'xml'))) ? '
          ' : "\n"; - $case->stepDesc .= $i . ". " . $step->desc . $sign; - $case->stepExpect .= $i . ". " . $step->expect . $sign; - $i ++; - } - } - - if($this->post->fileType == 'csv') - { - $case->stepDesc = str_replace('"', '""', $case->stepDesc); - $case->stepExpect = str_replace('"', '""', $case->stepExpect); - } - - /* 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->post->set('kind', 'testcase'); - $this->fetch('file', 'export2' . $this->post->fileType, $_POST); - } - - $this->display(); - } -} + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +class testcase extends control +{ + public $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) + ->page($pager) + ->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. + $caseQuery = $this->loadModel('search')->replaceDynamic($caseQuery); + $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 .*/ + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', $browseType == 'needconfirm' ? false : true); + + /* 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->loadModel('search')->setSearchParams($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 = new stdclass(); + $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=$productID&browseType=byModule¶m=$moduleID"), '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 = "CASE #$case->id $case->title - " . $this->products[$productID]; + $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->view->preAndNext = $this->loadModel('common')->getPreAndNextObject('testcase', $caseID); + + $this->display(); + } + + /** + * Edit a case. + * + * @param int $caseID + * @access public + * @return void + */ + public function edit($caseID, $comment = false) + { + $this->loadModel('story'); + + if(!empty($_POST)) + { + $changes = array(); + $files = array(); + if($comment == false) + { + $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(); + } + + /** + * Batch edit case. + * + * @param string $from example:testcaseBrowse,testtaskCases,testcaseBatchEdit + * @param int $productID + * @param string $orderBy + * @access public + * @return void + */ + public function batchEdit($from = '', $productID = 0, $orderBy = '') + { + if($from == 'testcaseBrowse' or $from == 'testtaskCases') + { + /* Init vars. */ + $orderBy = $orderBy ? $orderBy : 'id_desc'; + $caseIDList = $this->post->caseIDList ? $this->post->caseIDList : array(); + $product = $this->product->getByID($productID); + $editedCases = array(); + $columns = 7; + $showSuhosinInfo = false; + + /* Get all cases. */ + $allCases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($caseIDList)->orderBy($orderBy)->fetchAll('id'); + + /* Set product menu. */ + $this->testcase->setMenu($this->products, $productID); + + /* Initialize the cases whose need to edited. */ + foreach($allCases as $case) if(in_array($case->id, $caseIDList)) $editedCases[$case->id] = $case; + + /* Judge whether the editedTasks is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedCases), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + $this->view->header->title = $product->name . $this->lang->colon . $this->lang->testcase->batchEdit; + $this->view->position[] = html::a($this->createLink('testcase', 'browse', "productID=$productID"), $this->products[$productID]); + $this->view->position[] = $this->lang->testcase->common; + $this->view->position[] = $this->lang->testcase->batchEdit; + + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->moduleOptionMenu = $this->tree->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); + $this->view->productID = $productID; + $this->view->editedCases = $editedCases; + $this->view->users = $this->user->getPairs('nodeleted,qafirst'); + + $this->display(); + } + elseif($from == 'testcaseBatchEdit') + { + if(!empty($_POST)) + { + $allChanges = $this->testcase->batchUpdate(); + if($allChanges) + { + foreach($allChanges as $caseID => $changes ) + { + $actionID = $this->loadModel('action')->create('case', $caseID, 'Edited'); + $this->action->logHistory($actionID, $changes); + } + } + } + die(js::locate($this->session->caseList, 'parent')); + } + } + + /** + * 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 int $productID + * @param string $orderBy + * @param int $taskID + * @access public + * @return void + */ + public function export($productID, $orderBy, $taskID = 0) + { + 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. */ + if($this->session->testcaseOnlyCondition) + { + if($taskID) + { + $caseIDList = $this->dao->select('`case`')->from(TABLE_TESTRUN)->where('task')->eq($taskID)->fetchPairs(); + $cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition)->andWhere('id')->in($caseIDList) + ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() + ->orderBy($orderBy)->fetchAll('id'); + } + else + { + $cases = $this->dao->select('*')->from(TABLE_CASE)->where($this->session->testcaseQueryCondition) + ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() + ->orderBy($orderBy)->fetchAll('id'); + } + } + else + { + $cases = array(); + $orderBy = " ORDER BY " . str_replace(array('|', '^A', '_'), ' ', $orderBy); + $stmt = $this->dbh->query($this->session->testcaseQueryCondition . $orderBy); + while($row = $stmt->fetch()) + { + $caseID = isset($row->case) ? $row->case : $row->id; + if($this->post->exportType == 'selected' and strpos(",{$this->cookie->checkedItem},", ",$caseID,") === false) continue; + $cases[$caseID] = $row; + $row->id = $caseID; + } + } + + /* 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'); + $relatedModules = array('0' => '/') + $relatedModules; + + foreach($cases as $case) + { + $case->stepDesc = ''; + $case->stepExpect = ''; + if(isset($relatedSteps[$case->id])) + { + $i = 1; + foreach($relatedSteps[$case->id] as $step) + { + if($step->version != $case->version) continue; + $sign = (in_array($this->post->fileType, array('html', 'xml'))) ? '
          ' : "\n"; + $case->stepDesc .= $i . ". " . $step->desc . $sign; + $case->stepExpect .= $i . ". " . $step->expect . $sign; + $i ++; + } + } + + if($this->post->fileType == 'csv') + { + $case->stepDesc = str_replace('"', '""', $case->stepDesc); + $case->stepExpect = str_replace('"', '""', $case->stepExpect); + } + + /* 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->post->set('kind', 'testcase'); + $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 9be91fe578..f6f468a845 100644 --- a/module/testcase/lang/en.php +++ b/module/testcase/lang/en.php @@ -1,147 +1,147 @@ - - * @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->testcase->fromBug = 'From bug'; -$lang->testcase->toBug = 'To bug'; -$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->batchEdit = "Batch edit"; -$lang->testcase->delete = "Delete"; -$lang->testcase->browse = "Browse"; -$lang->testcase->import = "Import"; -$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['interface'] = 'Interface'; -$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->stageListAB['unittest'] = 'Unit'; -$lang->testcase->stageListAB['feature'] = 'Feature'; -$lang->testcase->stageListAB['intergrate'] = 'Integrate'; -$lang->testcase->stageListAB['system'] = 'System'; -$lang->testcase->stageListAB['smoke'] = 'Smoking'; -$lang->testcase->stageListAB['bvt'] = 'BVT'; - -$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->testcase->fromBug = 'From bug'; +$lang->testcase->toBug = 'To bug'; +$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->batchEdit = "Batch edit"; +$lang->testcase->delete = "Delete"; +$lang->testcase->browse = "Browse"; +$lang->testcase->import = "Import"; +$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['interface'] = 'Interface'; +$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->stageListAB['unittest'] = 'Unit'; +$lang->testcase->stageListAB['feature'] = 'Feature'; +$lang->testcase->stageListAB['intergrate'] = 'Integrate'; +$lang->testcase->stageListAB['system'] = 'System'; +$lang->testcase->stageListAB['smoke'] = 'Smoking'; +$lang->testcase->stageListAB['bvt'] = 'BVT'; + +$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 7b52918e10..a850df962c 100644 --- a/module/testcase/lang/zh-cn.php +++ b/module/testcase/lang/zh-cn.php @@ -1,147 +1,147 @@ - - * @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->testcase->fromBug = '来源Bug'; -$lang->testcase->toBug = '生成Bug'; -$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->batchEdit = "批量编辑 "; -$lang->testcase->delete = "删除"; -$lang->testcase->browse = "用例列表"; -$lang->testcase->import = "导入用例"; -$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 = '所有'; -$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['interface'] = '接口测试'; -$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->stageListAB['unittest'] = '单元'; -$lang->testcase->stageListAB['feature'] = '功能'; -$lang->testcase->stageListAB['intergrate'] = '集成'; -$lang->testcase->stageListAB['system'] = '系统'; -$lang->testcase->stageListAB['smoke'] = '冒烟'; -$lang->testcase->stageListAB['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->testcase->fromBug = '来源Bug'; +$lang->testcase->toBug = '生成Bug'; +$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->batchEdit = "批量编辑 "; +$lang->testcase->delete = "删除"; +$lang->testcase->browse = "用例列表"; +$lang->testcase->import = "导入用例"; +$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 = '所有'; +$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['interface'] = '接口测试'; +$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->stageListAB['unittest'] = '单元'; +$lang->testcase->stageListAB['feature'] = '功能'; +$lang->testcase->stageListAB['intergrate'] = '集成'; +$lang->testcase->stageListAB['system'] = '系统'; +$lang->testcase->stageListAB['smoke'] = '冒烟'; +$lang->testcase->stageListAB['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 7189174f68..eb3ed2e0ff 100644 --- a/module/testcase/lang/zh-tw.php +++ b/module/testcase/lang/zh-tw.php @@ -1,146 +1,146 @@ - - * @package testcase - * @version $Id: zh-tw.php 3768 2012-12-12 00:44:35Z zhujinyonging@gmail.com $ - * @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->testcase->fromBug = '來源Bug'; -$lang->testcase->toBug = '生成Bug'; -$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->batchEdit = "批量編輯 "; -$lang->testcase->delete = "刪除"; -$lang->testcase->browse = "用例列表"; -$lang->testcase->import = "導入用例"; -$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 = '所有'; -$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->stageListAB['unittest'] = '單元'; -$lang->testcase->stageListAB['feature'] = '功能'; -$lang->testcase->stageListAB['intergrate'] = '整合'; -$lang->testcase->stageListAB['system'] = '系統'; -$lang->testcase->stageListAB['smoke'] = '冒煙'; -$lang->testcase->stageListAB['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 3768 2012-12-12 00:44:35Z zhujinyonging@gmail.com $ + * @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->testcase->fromBug = '來源Bug'; +$lang->testcase->toBug = '生成Bug'; +$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->batchEdit = "批量編輯 "; +$lang->testcase->delete = "刪除"; +$lang->testcase->browse = "用例列表"; +$lang->testcase->import = "導入用例"; +$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 = '所有'; +$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->stageListAB['unittest'] = '單元'; +$lang->testcase->stageListAB['feature'] = '功能'; +$lang->testcase->stageListAB['intergrate'] = '整合'; +$lang->testcase->stageListAB['system'] = '系統'; +$lang->testcase->stageListAB['smoke'] = '冒煙'; +$lang->testcase->stageListAB['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 ab1601c1a7..902a762ffe 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -1,392 +1,392 @@ - - * @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 : $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] = new stdclass(); - $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) - { - $data[$i]->story = 0; - } - else - { - $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->fromBug) $case->fromBugTitle = $this->dao->findById($case->fromBug)->from(TABLE_BUG)->fields('title')->fetch('title'); - - $case->toBugs = array(); - $toBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('`case`')->eq($caseID)->fetchAll(); - foreach($toBugs as $toBug) $case->toBugs[$toBug->id] = $toBug->title; - - 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)->orderBy('id')->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); - } - } - - /** - * Batch update testcases. - * - * @access public - * @return array - */ - public function batchUpdate() - { - $cases = array(); - $allChanges = array(); - $now = helper::now(); - $caseIDList = $this->post->caseIDList ? $this->post->caseIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $caseIDList. */ - if($this->session->showSuhosinInfo) array_pop($caseIDList); - - if(!empty($caseIDList)) - { - /* Initialize cases from the post data.*/ - foreach($caseIDList as $caseID) - { - $case->lastEditedBy = $this->app->user->account; - $caee->lastEditedDate = $now; - $case->pri = $this->post->pris[$caseID]; - $case->status = $this->post->statuses[$caseID]; - $case->module = $this->post->modules[$caseID]; - $case->title = htmlspecialchars($this->post->titles[$caseID]); - $case->type = $this->post->types[$caseID]; - $case->stage = implode(',', $this->post->stages[$caseID]); - - $cases[$caseID] = $case; - unset($case); - } - - /* Update cases. */ - foreach($cases as $caseID => $case) - { - $oldCase = $this->getByID($caseID); - $this->dao->update(TABLE_CASE)->data($case) - ->autoCheck() - ->batchCheck($this->config->testcase->edit->requiredFields, 'notempty') - ->where('id')->eq($caseID) - ->exec(); - - if(!dao::isError()) - { - unset($oldCase->steps); - $allChanges[$caseID] = common::createChanges($oldCase, $case); - } - else - { - die(js::error('case#' . $caseID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - - /** - * Join steps to a string, thus can diff them. - * - * @param array $steps - * @access public - * @return string - */ - public function joinStep($steps) - { - $return = ''; - 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; - } - - /** - * Adjust the action is clickable. - * - * @param object $case - * @param string $action - * @access public - * @return void - */ - public function isClickable($case, $action) - { - $action = strtolower($action); - - if($action == 'createbug') return $case->lastRunResult == 'fail'; - - return true; - } -} + + * @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 : $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] = new stdclass(); + $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) + { + $data[$i]->story = 0; + } + else + { + $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->fromBug) $case->fromBugTitle = $this->dao->findById($case->fromBug)->from(TABLE_BUG)->fields('title')->fetch('title'); + + $case->toBugs = array(); + $toBugs = $this->dao->select('id, title')->from(TABLE_BUG)->where('`case`')->eq($caseID)->fetchAll(); + foreach($toBugs as $toBug) $case->toBugs[$toBug->id] = $toBug->title; + + 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)->orderBy('id')->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); + } + } + + /** + * Batch update testcases. + * + * @access public + * @return array + */ + public function batchUpdate() + { + $cases = array(); + $allChanges = array(); + $now = helper::now(); + $caseIDList = $this->post->caseIDList ? $this->post->caseIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $caseIDList. */ + if($this->session->showSuhosinInfo) array_pop($caseIDList); + + if(!empty($caseIDList)) + { + /* Initialize cases from the post data.*/ + foreach($caseIDList as $caseID) + { + $case->lastEditedBy = $this->app->user->account; + $caee->lastEditedDate = $now; + $case->pri = $this->post->pris[$caseID]; + $case->status = $this->post->statuses[$caseID]; + $case->module = $this->post->modules[$caseID]; + $case->title = htmlspecialchars($this->post->titles[$caseID]); + $case->type = $this->post->types[$caseID]; + $case->stage = implode(',', $this->post->stages[$caseID]); + + $cases[$caseID] = $case; + unset($case); + } + + /* Update cases. */ + foreach($cases as $caseID => $case) + { + $oldCase = $this->getByID($caseID); + $this->dao->update(TABLE_CASE)->data($case) + ->autoCheck() + ->batchCheck($this->config->testcase->edit->requiredFields, 'notempty') + ->where('id')->eq($caseID) + ->exec(); + + if(!dao::isError()) + { + unset($oldCase->steps); + $allChanges[$caseID] = common::createChanges($oldCase, $case); + } + else + { + die(js::error('case#' . $caseID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + + /** + * Join steps to a string, thus can diff them. + * + * @param array $steps + * @access public + * @return string + */ + public function joinStep($steps) + { + $return = ''; + 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; + } + + /** + * Adjust the action is clickable. + * + * @param object $case + * @param string $action + * @access public + * @return void + */ + public function isClickable($case, $action) + { + $action = strtolower($action); + + if($action == 'createbug') return $case->lastRunResult == 'fail'; + + return true; + } +} diff --git a/module/testcase/view/batchcreate.html.php b/module/testcase/view/batchcreate.html.php index 03e5436a59..0d013a2ac9 100644 --- a/module/testcase/view/batchcreate.html.php +++ b/module/testcase/view/batchcreate.html.php @@ -1,47 +1,47 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -testcase->batchCreate);?> -
          - - - - - - - - - - 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);?> +
          + + + + + + + + + + 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/batchedit.html.php b/module/testcase/view/batchedit.html.php index 798bfb9556..4530dfcd3c 100644 --- a/module/testcase/view/batchedit.html.php +++ b/module/testcase/view/batchedit.html.php @@ -1,57 +1,57 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -?> - -
          "> - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testcase->common . $lang->colon . $lang->testcase->batchEdit;?>
          idAB;?>priAB;?>statusAB;?>testcase->module;?>testcase->title;?>testcase->type;?>testcase->stage;?>
          id . html::hidden("caseIDList[$case->id]", $case->id);?>id]", $lang->testcase->priList, $case->pri, 'class=select-1');?>id]", (array)$lang->testcase->statusList, $case->status, 'class=select-1');?>id]", $moduleOptionMenu, $case->module, "class='select-1'");?>id]", $case->title, 'class=text-1'); echo "*";?>id]", $lang->testcase->typeList, $case->type, 'class=select-1');?> - testcase->stageListAB as $key => $stage) - { - if(in_array($key, explode(',', $case->stage))) - { - echo "$stage "; - } - else - { - echo "$stage "; - } - } - ?> -
          -
          - + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          "> + + + + + + + + + + + + + + + + + + + + + + + + + + +
          testcase->common . $lang->colon . $lang->testcase->batchEdit;?>
          idAB;?>priAB;?>statusAB;?>testcase->module;?>testcase->title;?>testcase->type;?>testcase->stage;?>
          id . html::hidden("caseIDList[$case->id]", $case->id);?>id]", $lang->testcase->priList, $case->pri, 'class=select-1');?>id]", (array)$lang->testcase->statusList, $case->status, 'class=select-1');?>id]", $moduleOptionMenu, $case->module, "class='select-1'");?>id]", $case->title, 'class=text-1'); echo "*";?>id]", $lang->testcase->typeList, $case->type, 'class=select-1');?> + testcase->stageListAB as $key => $stage) + { + if(in_array($key, explode(',', $case->stage))) + { + echo "$stage "; + } + else + { + echo "$stage "; + } + } + ?> +
          +
          + diff --git a/module/testcase/view/browse.html.php b/module/testcase/view/browse.html.php index 2c87811fc1..92522ae5d5 100644 --- a/module/testcase/view/browse.html.php +++ b/module/testcase/view/browse.html.php @@ -1,128 +1,128 @@ - - * @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} "; - ?> -
          -
          - - - -
          -
          -
          '>
          - - - - - - -
          -
          -
          - -
          - tree->manage);?> - tree->fix, 'hiddenwin');?> -
          -
          -
          - recTotal}&recPerPage={$pager->recPerPage}"; ?> -
          '> - - - - - - - - - - - - - - - - - - - - - - id");?> - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB);?>priAB);?>testcase->title);?>testcase->story);?>actions;?> typeAB);?> openedByAB);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?>statusAB);?>actions;?>
          - - id));?> - pri?>'>pri?>title);?>createLink('story', 'view', "storyID=$case->story"), $case->storyTitle, '_blank');?>testcase->confirmStoryChange = $lang->confirm; common::printIcon('testcase', 'confirmStoryChange', "caseID=$case->id", '', 'list', '', '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];?> - id&version=$case->version", '', 'list'); - common::printIcon('testtask', 'results', "runID=0&caseID=$case->id", '', 'list'); - common::printIcon('testcase', 'edit', "caseID=$case->id", $case, 'list'); - common::printIcon('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'list', 'copy'); - common::printIcon('testcase', 'delete', "caseID=$case->id", '', 'list', '', 'hiddenwin'); - common::printIcon('testcase', 'createBug', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $case, 'list', 'createBug'); - ?> -
          - -
          - testcase->batchEdit, "onclick='changeAction(\"" . inLink('batchEdit', "from=testcaseBrowse&productID=$productID&orderBy=$orderBy") . "\")'"); - if(common::hasPriv('testtask', 'batchRun')) echo html::submitButton($lang->testtask->batchRun, "onclick='changeAction(\"" . $this->createLink('testtask', 'batchRun', "productID=$productID&orderBy=$orderBy") . "\")'"); - ?> -
          - - 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} "; + ?> +
          +
          + + + +
          +
          +
          '>
          + + + + + + +
          +
          +
          + +
          + tree->manage);?> + tree->fix, 'hiddenwin');?> +
          +
          +
          + recTotal}&recPerPage={$pager->recPerPage}"; ?> +
          '> + + + + + + + + + + + + + + + + + + + + + + id");?> + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB);?>priAB);?>testcase->title);?>testcase->story);?>actions;?> typeAB);?> openedByAB);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?>statusAB);?>actions;?>
          + + id));?> + pri?>'>pri?>title);?>createLink('story', 'view', "storyID=$case->story"), $case->storyTitle, '_blank');?>testcase->confirmStoryChange = $lang->confirm; common::printIcon('testcase', 'confirmStoryChange', "caseID=$case->id", '', 'list', '', '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];?> + id&version=$case->version", '', 'list'); + common::printIcon('testtask', 'results', "runID=0&caseID=$case->id", '', 'list'); + common::printIcon('testcase', 'edit', "caseID=$case->id", $case, 'list'); + common::printIcon('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", $case, 'list', 'copy'); + common::printIcon('testcase', 'delete', "caseID=$case->id", '', 'list', '', 'hiddenwin'); + common::printIcon('testcase', 'createBug', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", $case, 'list', 'createBug'); + ?> +
          + +
          + testcase->batchEdit, "onclick='changeAction(\"" . inLink('batchEdit', "from=testcaseBrowse&productID=$productID&orderBy=$orderBy") . "\")'"); + if(common::hasPriv('testtask', 'batchRun')) echo html::submitButton($lang->testtask->batchRun, "onclick='changeAction(\"" . $this->createLink('testtask', 'batchRun', "productID=$productID&orderBy=$orderBy") . "\")'"); + ?> +
          + + show();?> +
          +
          + + diff --git a/module/testcase/view/create.html.php b/module/testcase/view/create.html.php index fb1bc00af5..ccd3e255aa 100644 --- a/module/testcase/view/create.html.php +++ b/module/testcase/view/create.html.php @@ -1,98 +1,98 @@ - - * @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 49c728b86b..88faf813bc 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 a80d0f7dc8..42cc77b580 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/import.html.php b/module/testcase/view/import.html.php index d912cb2c94..b2c175d5d4 100755 --- a/module/testcase/view/import.html.php +++ b/module/testcase/view/import.html.php @@ -1,32 +1,32 @@ - - * @package file - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - importEncodeList,'gbk');?> - -
          -
          - - - - - - - - -
          - -
          -
          - + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
          + + importEncodeList,'gbk');?> + +
          +
          + + + + + + + + +
          + +
          +
          + diff --git a/module/testcase/view/index.html.php b/module/testcase/view/index.html.php index 61e8305262..4c6c2e4456 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 9e6e978a68..f6fdf507f8 100644 --- a/module/testcase/view/view.html.php +++ b/module/testcase/view/view.html.php @@ -1,232 +1,232 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          deleted) echo "class='deleted'";?>>CASE #id . ' ' . $case->title;?>
          -
          - session->caseList != false ? $app->session->caseList : $this->createLink('testcase', 'browse', "productID=$case->product"); - $actionLinks = ''; - if(!$case->deleted) - { - ob_start(); - - common::printIcon('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->currentVersion"); - common::printIcon('testtask', 'results', "runID=0&caseID=$case->id&version=$case->version"); - - if($case->lastRunResult == 'fail') common::printIcon('testcase', 'createBug', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", '', 'button', 'createBug'); - - common::printDivider(); - common::printIcon('testcase', 'edit',"caseID=$case->id"); - common::printCommentIcon('testcase'); - common::printIcon('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", '', 'button', 'copy'); - common::printIcon('testcase', 'delete', "caseID=$case->id", '', 'button', '', 'hiddenwin'); - - common::printDivider(); - common::printRPN($browseLink, $preAndNext); - - $actionLinks = ob_get_contents(); - ob_clean(); - echo $actionLinks; - } - else - { - common::printRPN($browseLink); - } - ?> -
          -
          - - - - - - - -
          -
          - 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'));?> - - - -
          -
          - 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->legendLinkBugs;?> - - - - - - - - - -
          testcase->fromBug;?>fromBug) echo html::a($this->createLink('bug', 'view', "bugID=$case->fromBug"), $case->fromBugTitle);?>
          testcase->toBug;?> - toBugs as $bugID => $bugTitle) - { - echo '

          ' . html::a($this->createLink('bug', 'view', "bugID=$bugID"), $bugTitle) . '

          '; - } - ?> -
          -
          - -
          - 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 . ' ' . $case->title;?>
          +
          + session->caseList != false ? $app->session->caseList : $this->createLink('testcase', 'browse', "productID=$case->product"); + $actionLinks = ''; + if(!$case->deleted) + { + ob_start(); + + common::printIcon('testtask', 'runCase', "runID=0&caseID=$case->id&version=$case->currentVersion"); + common::printIcon('testtask', 'results', "runID=0&caseID=$case->id&version=$case->version"); + + if($case->lastRunResult == 'fail') common::printIcon('testcase', 'createBug', "product=$case->product&extra=caseID=$case->id,version=$case->version,runID=", '', 'button', 'createBug'); + + common::printDivider(); + common::printIcon('testcase', 'edit',"caseID=$case->id"); + common::printCommentIcon('testcase'); + common::printIcon('testcase', 'create', "productID=$case->product&moduleID=$case->module&from=testcase¶m=$case->id", '', 'button', 'copy'); + common::printIcon('testcase', 'delete', "caseID=$case->id", '', 'button', '', 'hiddenwin'); + + common::printDivider(); + common::printRPN($browseLink, $preAndNext); + + $actionLinks = ob_get_contents(); + ob_clean(); + echo $actionLinks; + } + else + { + common::printRPN($browseLink); + } + ?> +
          +
          + + + + + + + +
          +
          + 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'));?> + + + +
          +
          + 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->legendLinkBugs;?> + + + + + + + + + +
          testcase->fromBug;?>fromBug) echo html::a($this->createLink('bug', 'view', "bugID=$case->fromBug"), $case->fromBugTitle);?>
          testcase->toBug;?> + toBugs as $bugID => $bugTitle) + { + echo '

          ' . html::a($this->createLink('bug', 'view', "bugID=$bugID"), $bugTitle) . '

          '; + } + ?> +
          +
          + +
          + 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 aa6f088e18..d2c35a5066 100644 --- a/module/testtask/control.php +++ b/module/testtask/control.php @@ -1,592 +1,592 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -class testtask extends control -{ - public $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())); - $actionID = $this->loadModel('action')->create('testtask', $taskID, 'opened'); - if($this->post->owner) - { - $this->sendmail($taskID, $actionID, '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|qdfirst'); - - $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, true); - if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); - $productID = $task->product; - $this->testtask->setMenu($this->products, $productID); - - $this->view->header->title = "TASK #$task->id $task->name/" . $this->products[$productID]; - $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 string $taskID - * @param string $browseType bymodule|all|assignedtome - * @param int $param - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function cases($taskID, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save the session. */ - $this->app->loadLang('testcase'); - $this->session->set('caseList', $this->app->getURI(true)); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - /* 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, $orderBy, $pager); - } - elseif($browseType == 'assignedtome') - { - $this->view->runs = $this->testtask->getUserRuns($taskID, $this->session->user->account, $orderBy, $pager); - } - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', false); - - /* Save testcaseIDs session for get the pre and next testcase. */ - $testcaseIDs = ''; - foreach($this->view->runs as $run) $testcaseIDs .= ',' . $run->case; - $this->session->set('testcaseIDs', $testcaseIDs . ','); - - $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,nodeleted,qafirst'); - $this->view->moduleTree = $this->loadModel('tree')->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createTestTaskLink'), $extra = $taskID); - $this->view->browseType = $browseType; - $this->view->param = $param; - $this->view->orderBy = $orderBy; - $this->view->taskID = $taskID; - $this->view->moduleID = $moduleID; - $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; - $this->view->pager = $pager; - - $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); - - /* send mail.*/ - $this->sendmail($taskID, $actionID, 'edited'); - } - 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->loadModel('search')->setSearchParams($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); - - $nextCase = ''; - $caseID = $caseID ? $caseID : $run->case->id; - $preAndNext = $this->loadModel('common')->getPreAndNextObject('testcase', $caseID); - if($runID and $preAndNext->next) $preAndNext->next = $this->dao->select('*')->from(TABLE_TESTRUN)->where('`case`')->eq($preAndNext->next->id)->fetch(); - if($preAndNext->next) - { - $nextCase['runID'] = $runID ? $preAndNext->next->id : 0; - $nextCase['caseID'] = $runID ? $preAndNext->next->case : $preAndNext->next->id; - $nextCase['version'] = $preAndNext->next->version; - } - - $this->view->run = $run; - $this->view->nextCase = $nextCase; - - die($this->display()); - } - - /** - * Batch run case. - * - * @param int $productID - * @param string $orderBy - * @param string $from - * @access public - * @return void - */ - public function batchRun($productID, $orderBy = 'id_desc', $from = 'testcase') - { - if(isset($_POST['caseIDList'])) - { - if($from == 'testcase') $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($this->post->caseIDList)->orderBy($orderBy)->fetchAll('id'); - if($from == 'testtask') - { - $this->view->cases = $this->dao->select('t1.*,t2.lastRunResult')->from(TABLE_CASE)->alias('t1') - ->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.id = t2.case') - ->where('t1.id')->in($this->post->caseIDList) - ->orderBy($orderBy) - ->fetchAll('id'); - } - } - else - { - $this->testtask->batchRun($from); - $method = $from == 'testcase' ? 'browse' : 'cases'; - die(js::locate($this->createLink($from, $method, "productID=$productID"), 'parent')); - } - $this->app->loadLang('testcase'); - $this->testtask->setMenu($this->products, $productID); - - $resultList = $this->lang->testcase->resultList; - unset($resultList['n/a']); - - $steps = $this->dao->select('t1.*')->from(TABLE_CASESTEP)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case=t2.id') - ->where('t2.id')->in($this->post->caseIDList) - ->andWhere('t1.version=t2.version') - ->fetchGroup('case', 'id'); - - $this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); - $this->view->resultList = $resultList; - $this->view->steps = $steps; - $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) - { - $case = $this->loadModel('testcase')->getByID($caseID, $version); - $results = $this->testtask->getResults(0, $caseID); - } - else - { - $case = $this->testtask->getRunById($runID)->case; - $results = $this->testtask->getResults($runID); - - $testtaskID = $this->dao->select('task')->from(TABLE_TESTRUN)->where('id')->eq($runID)->fetch('task', false); - $testtask = $this->dao->select('build, product')->from(TABLE_TESTTASK)->where('id')->eq($testtaskID)->fetch(); - $builds = $this->loadModel('build')->getProductBuildPairs($testtask->product); - $this->view->build = isset($builds[$testtask->build]) ? $builds[$testtask->build] : ''; - } - - $this->view->case = $case; - $this->view->results = $results; - $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->caseIDList) - ->exec(); - die(js::locate($this->session->caseList)); - } - - /** - * Send mail. - * - * @param int $testtaskID - * @param int $actionID - * @param string $action - * @access public - * @return void - */ - public function sendmail($testtaskID, $actionID, $actionType) - { - $testtask = $this->testtask->getByID($testtaskID); - $action = $this->action->getById($actionID); - $users = $this->loadModel('user')->getPairs('noletter'); - - $this->view->testtask = $testtask; - $this->view->action = $action; - $this->view->users = $users; - - $mailContent = $this->parse($this->moduleName, 'sendmail'); - - if($actionType == 'opened') - { - $mailTitle = sprintf($this->lang->testtask->mail->create->title, $this->app->user->realname, $testtaskID, $this->post->name); - } - else - { - $mailTitle = sprintf($this->lang->testtask->mail->edit->title, $this->app->user->realname, $testtaskID, $this->post->name); - } - $this->loadModel('mail')->send($this->post->owner, $mailTitle, $mailContent); - if($this->mail->isError()) echo js::error($this->mail->getError()); - } -} + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +class testtask extends control +{ + public $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())); + $actionID = $this->loadModel('action')->create('testtask', $taskID, 'opened'); + if($this->post->owner) + { + $this->sendmail($taskID, $actionID, '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|qdfirst'); + + $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, true); + if(!$task) die(js::error($this->lang->notFound) . js::locate('back')); + $productID = $task->product; + $this->testtask->setMenu($this->products, $productID); + + $this->view->header->title = "TASK #$task->id $task->name/" . $this->products[$productID]; + $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 string $taskID + * @param string $browseType bymodule|all|assignedtome + * @param int $param + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function cases($taskID, $browseType = 'byModule', $param = 0, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save the session. */ + $this->app->loadLang('testcase'); + $this->session->set('caseList', $this->app->getURI(true)); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + /* 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, $orderBy, $pager); + } + elseif($browseType == 'assignedtome') + { + $this->view->runs = $this->testtask->getUserRuns($taskID, $this->session->user->account, $orderBy, $pager); + } + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', false); + + /* Save testcaseIDs session for get the pre and next testcase. */ + $testcaseIDs = ''; + foreach($this->view->runs as $run) $testcaseIDs .= ',' . $run->case; + $this->session->set('testcaseIDs', $testcaseIDs . ','); + + $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,nodeleted,qafirst'); + $this->view->moduleTree = $this->loadModel('tree')->getTreeMenu($productID, $viewType = 'case', $startModuleID = 0, array('treeModel', 'createTestTaskLink'), $extra = $taskID); + $this->view->browseType = $browseType; + $this->view->param = $param; + $this->view->orderBy = $orderBy; + $this->view->taskID = $taskID; + $this->view->moduleID = $moduleID; + $this->view->treeClass = $browseType == 'bymodule' ? '' : 'hidden'; + $this->view->pager = $pager; + + $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); + + /* send mail.*/ + $this->sendmail($taskID, $actionID, 'edited'); + } + 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->loadModel('search')->setSearchParams($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); + + $nextCase = ''; + $caseID = $caseID ? $caseID : $run->case->id; + $preAndNext = $this->loadModel('common')->getPreAndNextObject('testcase', $caseID); + if($runID and $preAndNext->next) $preAndNext->next = $this->dao->select('*')->from(TABLE_TESTRUN)->where('`case`')->eq($preAndNext->next->id)->fetch(); + if($preAndNext->next) + { + $nextCase['runID'] = $runID ? $preAndNext->next->id : 0; + $nextCase['caseID'] = $runID ? $preAndNext->next->case : $preAndNext->next->id; + $nextCase['version'] = $preAndNext->next->version; + } + + $this->view->run = $run; + $this->view->nextCase = $nextCase; + + die($this->display()); + } + + /** + * Batch run case. + * + * @param int $productID + * @param string $orderBy + * @param string $from + * @access public + * @return void + */ + public function batchRun($productID, $orderBy = 'id_desc', $from = 'testcase') + { + if(isset($_POST['caseIDList'])) + { + if($from == 'testcase') $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($this->post->caseIDList)->orderBy($orderBy)->fetchAll('id'); + if($from == 'testtask') + { + $this->view->cases = $this->dao->select('t1.*,t2.lastRunResult')->from(TABLE_CASE)->alias('t1') + ->leftJoin(TABLE_TESTRUN)->alias('t2')->on('t1.id = t2.case') + ->where('t1.id')->in($this->post->caseIDList) + ->orderBy($orderBy) + ->fetchAll('id'); + } + } + else + { + $this->testtask->batchRun($from); + $method = $from == 'testcase' ? 'browse' : 'cases'; + die(js::locate($this->createLink($from, $method, "productID=$productID"), 'parent')); + } + $this->app->loadLang('testcase'); + $this->testtask->setMenu($this->products, $productID); + + $resultList = $this->lang->testcase->resultList; + unset($resultList['n/a']); + + $steps = $this->dao->select('t1.*')->from(TABLE_CASESTEP)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case=t2.id') + ->where('t2.id')->in($this->post->caseIDList) + ->andWhere('t1.version=t2.version') + ->fetchGroup('case', 'id'); + + $this->view->moduleOptionMenu = $this->loadModel('tree')->getOptionMenu($productID, $viewType = 'case', $startModuleID = 0); + $this->view->resultList = $resultList; + $this->view->steps = $steps; + $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) + { + $case = $this->loadModel('testcase')->getByID($caseID, $version); + $results = $this->testtask->getResults(0, $caseID); + } + else + { + $case = $this->testtask->getRunById($runID)->case; + $results = $this->testtask->getResults($runID); + + $testtaskID = $this->dao->select('task')->from(TABLE_TESTRUN)->where('id')->eq($runID)->fetch('task', false); + $testtask = $this->dao->select('build, product')->from(TABLE_TESTTASK)->where('id')->eq($testtaskID)->fetch(); + $builds = $this->loadModel('build')->getProductBuildPairs($testtask->product); + $this->view->build = isset($builds[$testtask->build]) ? $builds[$testtask->build] : ''; + } + + $this->view->case = $case; + $this->view->results = $results; + $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->caseIDList) + ->exec(); + die(js::locate($this->session->caseList)); + } + + /** + * Send mail. + * + * @param int $testtaskID + * @param int $actionID + * @param string $action + * @access public + * @return void + */ + public function sendmail($testtaskID, $actionID, $actionType) + { + $testtask = $this->testtask->getByID($testtaskID); + $action = $this->action->getById($actionID); + $users = $this->loadModel('user')->getPairs('noletter'); + + $this->view->testtask = $testtask; + $this->view->action = $action; + $this->view->users = $users; + + $mailContent = $this->parse($this->moduleName, 'sendmail'); + + if($actionType == 'opened') + { + $mailTitle = sprintf($this->lang->testtask->mail->create->title, $this->app->user->realname, $testtaskID, $this->post->name); + } + else + { + $mailTitle = sprintf($this->lang->testtask->mail->edit->title, $this->app->user->realname, $testtaskID, $this->post->name); + } + $this->loadModel('mail')->send($this->post->owner, $mailTitle, $mailContent); + if($this->mail->isError()) echo js::error($this->mail->getError()); + } +} diff --git a/module/testtask/lang/en.php b/module/testtask/lang/en.php index 7680487b43..2fa2a3824d 100644 --- a/module/testtask/lang/en.php +++ b/module/testtask/lang/en.php @@ -1,85 +1,85 @@ - - * @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 = "Testtask browse"; -$lang->testtask->linkCase = "Link case"; -$lang->testtask->linkCaseAB = "Link"; -$lang->testtask->unlinkCase = "Del"; -$lang->testtask->batchAssign = "Batch Assign"; -$lang->testtask->runCase = "Run"; -$lang->testtask->batchRun = "Batch Run"; -$lang->testtask->results = "Result"; -$lang->testtask->createBug = "Bug(+)"; -$lang->testtask->assign = 'Assign'; -$lang->testtask->cases = 'Cases'; -$lang->testtask->next = 'Next'; - -$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->pri = 'Priority'; -$lang->testtask->name = 'Name'; -$lang->testtask->begin = 'Begin'; -$lang->testtask->end = 'End'; -$lang->testtask->desc = 'Desc'; -$lang->testtask->status = 'Status'; -$lang->testtask->assignedTo = 'Assign'; -$lang->testtask->linkVersion = 'Version'; -$lang->testtask->lastRunAccount = "Run"; -$lang->testtask->lastRunTime = 'Time'; -$lang->testtask->lastRunResult = 'Result'; - -$lang->testtask->statusList['wait'] = 'Pending'; -$lang->testtask->statusList['doing'] = 'In progress'; -$lang->testtask->statusList['done'] = 'Done'; -$lang->testtask->statusList['blocked'] = 'Blocked'; - -$lang->testtask->priList[0] = ''; -$lang->testtask->priList[3] = '3'; -$lang->testtask->priList[1] = '1'; -$lang->testtask->priList[2] = '2'; -$lang->testtask->priList[4] = '4'; - -$lang->testtask->unlinkedCases = 'Unlinked'; -$lang->testtask->linkedCases = 'Linked'; -$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'; - -$lang->testtask->placeholder = new stdclass(); -$lang->testtask->placeholder->begin = 'begin date'; -$lang->testtask->placeholder->end = 'end date'; - -$lang->testtask->mail = new stdclass(); -$lang->testtask->mail->create = new stdclass(); -$lang->testtask->mail->edit = new stdclass(); -$lang->testtask->mail->create->title = "%s created testtask #%s:%s"; -$lang->testtask->mail->edit->title = "%s finished testtask #%s:%s"; + + * @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 = "Testtask browse"; +$lang->testtask->linkCase = "Link case"; +$lang->testtask->linkCaseAB = "Link"; +$lang->testtask->unlinkCase = "Del"; +$lang->testtask->batchAssign = "Batch Assign"; +$lang->testtask->runCase = "Run"; +$lang->testtask->batchRun = "Batch Run"; +$lang->testtask->results = "Result"; +$lang->testtask->createBug = "Bug(+)"; +$lang->testtask->assign = 'Assign'; +$lang->testtask->cases = 'Cases'; +$lang->testtask->next = 'Next'; + +$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->pri = 'Priority'; +$lang->testtask->name = 'Name'; +$lang->testtask->begin = 'Begin'; +$lang->testtask->end = 'End'; +$lang->testtask->desc = 'Desc'; +$lang->testtask->status = 'Status'; +$lang->testtask->assignedTo = 'Assign'; +$lang->testtask->linkVersion = 'Version'; +$lang->testtask->lastRunAccount = "Run"; +$lang->testtask->lastRunTime = 'Time'; +$lang->testtask->lastRunResult = 'Result'; + +$lang->testtask->statusList['wait'] = 'Pending'; +$lang->testtask->statusList['doing'] = 'In progress'; +$lang->testtask->statusList['done'] = 'Done'; +$lang->testtask->statusList['blocked'] = 'Blocked'; + +$lang->testtask->priList[0] = ''; +$lang->testtask->priList[3] = '3'; +$lang->testtask->priList[1] = '1'; +$lang->testtask->priList[2] = '2'; +$lang->testtask->priList[4] = '4'; + +$lang->testtask->unlinkedCases = 'Unlinked'; +$lang->testtask->linkedCases = 'Linked'; +$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'; + +$lang->testtask->placeholder = new stdclass(); +$lang->testtask->placeholder->begin = 'begin date'; +$lang->testtask->placeholder->end = 'end date'; + +$lang->testtask->mail = new stdclass(); +$lang->testtask->mail->create = new stdclass(); +$lang->testtask->mail->edit = new stdclass(); +$lang->testtask->mail->create->title = "%s created testtask #%s:%s"; +$lang->testtask->mail->edit->title = "%s finished testtask #%s:%s"; diff --git a/module/testtask/lang/zh-cn.php b/module/testtask/lang/zh-cn.php index 025d24a078..68dff128e9 100644 --- a/module/testtask/lang/zh-cn.php +++ b/module/testtask/lang/zh-cn.php @@ -1,85 +1,85 @@ - - * @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->batchRun = "批量执行"; -$lang->testtask->results = "结果"; -$lang->testtask->createBug = "提Bug"; -$lang->testtask->assign = '指派'; -$lang->testtask->cases = '用例'; -$lang->testtask->next = '下一个'; - -$lang->testtask->common = '测试任务'; -$lang->testtask->id = '任务编号'; -$lang->testtask->product = '所属产品'; -$lang->testtask->project = '所属项目'; -$lang->testtask->build = '版本'; -$lang->testtask->owner = '负责人'; -$lang->testtask->pri = '优先级'; -$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->priList[0] = ''; -$lang->testtask->priList[3] = '3'; -$lang->testtask->priList[1] = '1'; -$lang->testtask->priList[2] = '2'; -$lang->testtask->priList[4] = '4'; - -$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 = '所有用例'; - -$lang->testtask->lblCases = '用例列表'; -$lang->testtask->lblUnlinkCase = '移除用例'; -$lang->testtask->lblRunCase = '执行用例'; -$lang->testtask->lblResults = '执行结果'; - -$lang->testtask->placeholder = new stdclass(); -$lang->testtask->placeholder->begin = '开始日期'; -$lang->testtask->placeholder->end = '结束日期'; - -$lang->testtask->mail = new stdclass(); -$lang->testtask->mail->create = new stdclass(); -$lang->testtask->mail->edit = new stdclass(); -$lang->testtask->mail->create->title = "%s创建了测试任务 #%s:%s"; -$lang->testtask->mail->edit->title = "%s编辑了测试任务 #%s:%s"; + + * @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->batchRun = "批量执行"; +$lang->testtask->results = "结果"; +$lang->testtask->createBug = "提Bug"; +$lang->testtask->assign = '指派'; +$lang->testtask->cases = '用例'; +$lang->testtask->next = '下一个'; + +$lang->testtask->common = '测试任务'; +$lang->testtask->id = '任务编号'; +$lang->testtask->product = '所属产品'; +$lang->testtask->project = '所属项目'; +$lang->testtask->build = '版本'; +$lang->testtask->owner = '负责人'; +$lang->testtask->pri = '优先级'; +$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->priList[0] = ''; +$lang->testtask->priList[3] = '3'; +$lang->testtask->priList[1] = '1'; +$lang->testtask->priList[2] = '2'; +$lang->testtask->priList[4] = '4'; + +$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 = '所有用例'; + +$lang->testtask->lblCases = '用例列表'; +$lang->testtask->lblUnlinkCase = '移除用例'; +$lang->testtask->lblRunCase = '执行用例'; +$lang->testtask->lblResults = '执行结果'; + +$lang->testtask->placeholder = new stdclass(); +$lang->testtask->placeholder->begin = '开始日期'; +$lang->testtask->placeholder->end = '结束日期'; + +$lang->testtask->mail = new stdclass(); +$lang->testtask->mail->create = new stdclass(); +$lang->testtask->mail->edit = new stdclass(); +$lang->testtask->mail->create->title = "%s创建了测试任务 #%s:%s"; +$lang->testtask->mail->edit->title = "%s编辑了测试任务 #%s:%s"; diff --git a/module/testtask/lang/zh-tw.php b/module/testtask/lang/zh-tw.php index 842555a557..4fd9493713 100644 --- a/module/testtask/lang/zh-tw.php +++ b/module/testtask/lang/zh-tw.php @@ -1,85 +1,85 @@ - - * @package testtask - * @version $Id: zh-tw.php 3860 2012-12-19 10:08:20Z wyd621@gmail.com $ - * @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->batchRun = "批量執行"; -$lang->testtask->results = "結果"; -$lang->testtask->createBug = "提Bug"; -$lang->testtask->assign = '指派'; -$lang->testtask->cases = '用例'; -$lang->testtask->next = '下一個'; - -$lang->testtask->common = '測試任務'; -$lang->testtask->id = '任務編號'; -$lang->testtask->product = '所屬產品'; -$lang->testtask->project = '所屬項目'; -$lang->testtask->build = '版本'; -$lang->testtask->owner = '負責人'; -$lang->testtask->pri = '優先順序'; -$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->priList[0] = ''; -$lang->testtask->priList[3] = '3'; -$lang->testtask->priList[1] = '1'; -$lang->testtask->priList[2] = '2'; -$lang->testtask->priList[4] = '4'; - -$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 = '執行結果'; - -$lang->testtask->placeholder = new stdclass(); -$lang->testtask->placeholder->begin = '開始日期'; -$lang->testtask->placeholder->end = '結束日期'; - -$lang->testtask->mail = new stdclass(); -$lang->testtask->mail->create = new stdclass(); -$lang->testtask->mail->edit = new stdclass(); -$lang->testtask->mail->create->title = "%s創建了測試任務 #%s:%s"; -$lang->testtask->mail->edit->title = "%s編輯了測試任務 #%s:%s"; + + * @package testtask + * @version $Id: zh-tw.php 3860 2012-12-19 10:08:20Z wyd621@gmail.com $ + * @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->batchRun = "批量執行"; +$lang->testtask->results = "結果"; +$lang->testtask->createBug = "提Bug"; +$lang->testtask->assign = '指派'; +$lang->testtask->cases = '用例'; +$lang->testtask->next = '下一個'; + +$lang->testtask->common = '測試任務'; +$lang->testtask->id = '任務編號'; +$lang->testtask->product = '所屬產品'; +$lang->testtask->project = '所屬項目'; +$lang->testtask->build = '版本'; +$lang->testtask->owner = '負責人'; +$lang->testtask->pri = '優先順序'; +$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->priList[0] = ''; +$lang->testtask->priList[3] = '3'; +$lang->testtask->priList[1] = '1'; +$lang->testtask->priList[2] = '2'; +$lang->testtask->priList[4] = '4'; + +$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 = '執行結果'; + +$lang->testtask->placeholder = new stdclass(); +$lang->testtask->placeholder->begin = '開始日期'; +$lang->testtask->placeholder->end = '結束日期'; + +$lang->testtask->mail = new stdclass(); +$lang->testtask->mail->create = new stdclass(); +$lang->testtask->mail->edit = new stdclass(); +$lang->testtask->mail->create->title = "%s創建了測試任務 #%s:%s"; +$lang->testtask->mail->edit->title = "%s編輯了測試任務 #%s:%s"; diff --git a/module/testtask/model.php b/module/testtask/model.php index 49dd677862..e8be1e6506 100644 --- a/module/testtask/model.php +++ b/module/testtask/model.php @@ -1,424 +1,424 @@ - - * @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 : $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 - * @param bool $setImgSize - * @access public - * @return void - */ - public function getById($taskID, $setImgSize = false) - { - $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(); - if($setImgSize) $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, $pager = null, $orderBy = 'id_desc') - { - 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($orderBy) - ->page($pager) - ->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 - * @param object $pager - * @access public - * @return array - */ - public function getRuns($taskID, $moduleID, $orderBy, $pager = null) - { - $orderBy = strpos($orderBy, 'assignedTo') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy); - - 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() - ->orderBy($orderBy) - ->page($pager) - ->fetchAll('', false); - } - - /** - * Get test runs of a user. - * - * @param int $taskID - * @param int $user - * @param obejct $pager - * @access public - * @return array - */ - public function getUserRuns($taskID, $user, $orderBy, $pager = null) - { - $orderBy = strpos($orderBy, 'assignedTo') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy); - - 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) - ->orderBy($orderBy) - ->page($pager) - ->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'] = $this->post->passall ? 'pass' : $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(); - } - } - } - - /** - * Batch run case - * - * @param string $runCaseType - * @access public - * @return void - */ - public function batchRun($runCaseType = 'testcase') - { - $this->post->a(); - $runs = array(); - $caseIdList = array_keys($this->post->results); - if($runCaseType == 'testtask') $runs = $this->dao->select('id, `case`')->from(TABLE_TESTRUN)->where('`case`')->in($caseIdList)->fetchPairs('case', 'id'); - - $stepGroups = $this->dao->select('t1.*')->from(TABLE_CASESTEP)->alias('t1') - ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') - ->where('t1.case')->in($caseIdList) - ->andWhere('t1.version=t2.version') - ->fetchGroup('case', 'id'); - - $now = helper::now(); - foreach($this->post->results as $caseID => $result) - { - $runID = isset($runs[$caseID]) ? $runs[$caseID] : 0; - $dbSteps = $stepGroups[$caseID]; - $postSteps = $this->post->steps[$caseID]; - $postReals = $this->post->reals[$caseID]; - - $caseResult = $result ? $result : 'pass'; - $stepResults = array(); - foreach($dbSteps as $stepID => $step) - { - $step = array(); - $step['result'] = $caseResult == 'pass' ? $caseResult : $postSteps[$stepID]; - $step['real'] = $caseResult == 'pass' ? '' : $postReals[$stepID]; - $stepResults[$stepID] = $step; - } - - $result = new stdClass(); - $result->run = $runID; - $result->case = $caseID; - $result->version = $this->post->version[$caseID]; - $result->caseResult = $caseResult; - $result->stepResults = serialize($stepResults); - $result->lastRunner = $this->app->user->account; - $result->date = $now; - $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($caseID)->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 : $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 + * @param bool $setImgSize + * @access public + * @return void + */ + public function getById($taskID, $setImgSize = false) + { + $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(); + if($setImgSize) $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, $pager = null, $orderBy = 'id_desc') + { + 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($orderBy) + ->page($pager) + ->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 + * @param object $pager + * @access public + * @return array + */ + public function getRuns($taskID, $moduleID, $orderBy, $pager = null) + { + $orderBy = strpos($orderBy, 'assignedTo') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy); + + 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() + ->orderBy($orderBy) + ->page($pager) + ->fetchAll('', false); + } + + /** + * Get test runs of a user. + * + * @param int $taskID + * @param int $user + * @param obejct $pager + * @access public + * @return array + */ + public function getUserRuns($taskID, $user, $orderBy, $pager = null) + { + $orderBy = strpos($orderBy, 'assignedTo') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy); + + 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) + ->orderBy($orderBy) + ->page($pager) + ->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'] = $this->post->passall ? 'pass' : $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(); + } + } + } + + /** + * Batch run case + * + * @param string $runCaseType + * @access public + * @return void + */ + public function batchRun($runCaseType = 'testcase') + { + $this->post->a(); + $runs = array(); + $caseIdList = array_keys($this->post->results); + if($runCaseType == 'testtask') $runs = $this->dao->select('id, `case`')->from(TABLE_TESTRUN)->where('`case`')->in($caseIdList)->fetchPairs('case', 'id'); + + $stepGroups = $this->dao->select('t1.*')->from(TABLE_CASESTEP)->alias('t1') + ->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id') + ->where('t1.case')->in($caseIdList) + ->andWhere('t1.version=t2.version') + ->fetchGroup('case', 'id'); + + $now = helper::now(); + foreach($this->post->results as $caseID => $result) + { + $runID = isset($runs[$caseID]) ? $runs[$caseID] : 0; + $dbSteps = $stepGroups[$caseID]; + $postSteps = $this->post->steps[$caseID]; + $postReals = $this->post->reals[$caseID]; + + $caseResult = $result ? $result : 'pass'; + $stepResults = array(); + foreach($dbSteps as $stepID => $step) + { + $step = array(); + $step['result'] = $caseResult == 'pass' ? $caseResult : $postSteps[$stepID]; + $step['real'] = $caseResult == 'pass' ? '' : $postReals[$stepID]; + $stepResults[$stepID] = $step; + } + + $result = new stdClass(); + $result->run = $runID; + $result->case = $caseID; + $result->version = $this->post->version[$caseID]; + $result->caseResult = $caseResult; + $result->stepResults = serialize($stepResults); + $result->lastRunner = $this->app->user->account; + $result->date = $now; + $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($caseID)->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/batchrun.html.php b/module/testtask/view/batchrun.html.php index 0b862abb8e..5b6853166c 100644 --- a/module/testtask/view/batchrun.html.php +++ b/module/testtask/view/batchrun.html.php @@ -1,70 +1,70 @@ - - * @package testcase - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - $case):?> - - - - - - - - - - -
          testtask->common . $lang->colon . $lang->testtask->batchRun;?>
          idAB;?>priAB;?>testcase->module;?>testcase->title;?>testcase->result?>testcase->stepDesc . '/' . $lang->testcase->stepExpect?>
          id . html::hidden("version[$case->id]", $case->version)?>testcase->priList[$case->pri]?>module] . "'>" . $moduleOptionMenu[$case->module] . ""?>title'>$case->title"?>id]", $resultList, 'pass', "onclick='showAction(this.value,\".action$caseID\")'")?> - - - $step):?> - - - - - - - - -
          desc'>" . $i . "、" . $step->desc . ''?>expect'>" . $lang->testcase->stepExpect . ":" . $step->expect . ''?>
          -
          -
          - - + + * @package testcase + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + $case):?> + + + + + + + + + + +
          testtask->common . $lang->colon . $lang->testtask->batchRun;?>
          idAB;?>priAB;?>testcase->module;?>testcase->title;?>testcase->result?>testcase->stepDesc . '/' . $lang->testcase->stepExpect?>
          id . html::hidden("version[$case->id]", $case->version)?>testcase->priList[$case->pri]?>module] . "'>" . $moduleOptionMenu[$case->module] . ""?>title'>$case->title"?>id]", $resultList, 'pass', "onclick='showAction(this.value,\".action$caseID\")'")?> + + + $step):?> + + + + + + + + +
          desc'>" . $i . "、" . $step->desc . ''?>expect'>" . $lang->testcase->stepExpect . ":" . $step->expect . ''?>
          +
          +
          + + diff --git a/module/testtask/view/browse.html.php b/module/testtask/view/browse.html.php index bd0513d6f5..3e8863df68 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;?>
          -
          -
          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", '', 'list'); - common::printIcon('testtask', 'linkCase', "taskID=$task->id", '', 'list'); - common::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); - common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', 'hiddenwin'); - ?> -
          - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          testtask->browse;?>
          +
          +
          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", '', 'list'); + common::printIcon('testtask', 'linkCase', "taskID=$task->id", '', 'list'); + common::printIcon('testtask', 'edit', "taskID=$task->id", '', 'list'); + common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'list', '', 'hiddenwin'); + ?> +
          + diff --git a/module/testtask/view/cases.html.php b/module/testtask/view/cases.html.php index 1b8a0bffac..2d1133160e 100644 --- a/module/testtask/view/cases.html.php +++ b/module/testtask/view/cases.html.php @@ -1,113 +1,113 @@ - - * @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"); - common::printIcon('testcase', 'export', "productID=$productID&orderBy=`case`_desc&taskID=$task->id"); - common::printRPN($this->session->testtaskList, ''); - ?> -
          -
          - -
          - - - - - - -
          -
          -
          -
          - id&browseType=$browseType¶m=$param&orderBy=%s&recToal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          idAB);?> priAB);?> testcase->title);?> testcase->type);?> testtask->assignedTo);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?> statusAB);?>actions;?>
          case);?>pri?>'>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", '', 'list', '', '', 'iframe'); - common::printIcon('testtask', 'results', "id=$run->id", '', 'list', '', '', 'iframe'); - common::printIcon('testtask', 'unlinkCase', "id=$run->id", '', 'list', '', 'hiddenwin'); - common::printIcon('testcase', 'createBug', "product=$productID&extra=projectID=$task->project,buildID=$task->build,caseID=$run->case,runID=$run->id", $run, 'list', 'createBug'); - ?> -
          - -
          - - ';casesform.submit();"> - - - - id");?>';casesform.submit();"> - ';casesform.submit();"> - -
          - - show();?> -
          -
          -
          - + + * @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"); + common::printIcon('testcase', 'export', "productID=$productID&orderBy=`case`_desc&taskID=$task->id"); + common::printRPN($this->session->testtaskList, ''); + ?> +
          +
          + +
          + + + + + + +
          +
          +
          +
          + id&browseType=$browseType¶m=$param&orderBy=%s&recToal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          idAB);?> priAB);?> testcase->title);?> testcase->type);?> testtask->assignedTo);?> testtask->lastRunAccount);?> testtask->lastRunTime);?> testtask->lastRunResult);?> statusAB);?>actions;?>
          case);?>pri?>'>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", '', 'list', '', '', 'iframe'); + common::printIcon('testtask', 'results', "id=$run->id", '', 'list', '', '', 'iframe'); + common::printIcon('testtask', 'unlinkCase', "id=$run->id", '', 'list', '', 'hiddenwin'); + common::printIcon('testcase', 'createBug', "product=$productID&extra=projectID=$task->project,buildID=$task->build,caseID=$run->case,runID=$run->id", $run, 'list', 'createBug'); + ?> +
          + +
          + + ';casesform.submit();"> + + + + id");?>';casesform.submit();"> + ';casesform.submit();"> + +
          + + show();?> +
          +
          +
          + diff --git a/module/testtask/view/create.html.php b/module/testtask/view/create.html.php index b7e69806e2..a63749c164 100644 --- a/module/testtask/view/create.html.php +++ b/module/testtask/view/create.html.php @@ -1,71 +1,71 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          testtask->create;?>
          testtask->product;?>
          testtask->project;?>
          testtask->build;?>
          testtask->owner;?>
          testtask->pri;?>testtask->priList, 0, 'class=select-3');?>
          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->pri;?>testtask->priList, 0, 'class=select-3');?>
          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 13b0c35037..90088d7539 100644 --- a/module/testtask/view/edit.html.php +++ b/module/testtask/view/edit.html.php @@ -1,60 +1,60 @@ - - * @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->pri;?>testtask->priList, $task->pri, '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->pri;?>testtask->priList, $task->pri, '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 8edd6d75bd..468171fe65 100644 --- a/module/testtask/view/linkcase.html.php +++ b/module/testtask/view/linkcase.html.php @@ -1,79 +1,79 @@ - - * @package testtask - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
          -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          -
          testtask->unlinkedCases;?>
          -
          - testtask->linCase = $lang->testtask->linkByStory; - common::printIcon('testtask', 'linkCase', "taskID=$taskID¶m=bystory"); - $lang->testtask->linCase = $lang->testtask->linkByBug; - common::printIcon('testtask', 'linkCase', "taskID=$taskID¶m=bybug"); - common::printRPN($this->session->testtaskList); - ?> -
          -
          idAB;?>testtask->linkVersion;?>priAB;?>testcase->title;?>testcase->type;?>openedByAB;?>statusAB;?>
          - - createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?> - id]", array_combine(range($case->version, 1), range($case->version, 1)), '', 'class=select-1');?> pri?>'>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];?>
          - -
          - -
          show();?>
          -
          -
          - - + + * @package testtask + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
          +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          testtask->unlinkedCases;?>
          +
          + testtask->linCase = $lang->testtask->linkByStory; + common::printIcon('testtask', 'linkCase', "taskID=$taskID¶m=bystory"); + $lang->testtask->linCase = $lang->testtask->linkByBug; + common::printIcon('testtask', 'linkCase', "taskID=$taskID¶m=bybug"); + common::printRPN($this->session->testtaskList); + ?> +
          +
          idAB;?>testtask->linkVersion;?>priAB;?>testcase->title;?>testcase->type;?>openedByAB;?>statusAB;?>
          + + createLink('testcase', 'view', "testcaseID=$case->id"), sprintf('%03d', $case->id));?> + id]", array_combine(range($case->version, 1), range($case->version, 1)), '', 'class=select-1');?> pri?>'>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];?>
          + +
          + +
          show();?>
          +
          +
          + + diff --git a/module/testtask/view/results.html.php b/module/testtask/view/results.html.php index 9f3bf94e94..f8cdd1e866 100644 --- a/module/testtask/view/results.html.php +++ b/module/testtask/view/results.html.php @@ -1,52 +1,52 @@ - - * @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] . '';?>
          -
          testtask->build . $lang->colon . $build;?>
          -
          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] . '';?>
          +
          testtask->build . $lang->colon . $build;?>
          +
          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 dad1aedd25..51be346e64 100644 --- a/module/testtask/view/runcase.html.php +++ b/module/testtask/view/runcase.html.php @@ -1,60 +1,60 @@ - - * @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($nextCase) echo html::linkButton($lang->testtask->next, inlink('runCase', "runID={$nextCase['runID']}&caseID={$nextCase['caseID']}&version={$nextCase['version']}")); - 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($nextCase) echo html::linkButton($lang->testtask->next, inlink('runCase', "runID={$nextCase['runID']}&caseID={$nextCase['caseID']}&version={$nextCase['version']}")); + if(!$run->case->steps) echo html::hidden('result', ''); + ?> +
          +
          + diff --git a/module/testtask/view/sendmail.html.php b/module/testtask/view/sendmail.html.php index 94ff78230b..50e0aa0688 100644 --- a/module/testtask/view/sendmail.html.php +++ b/module/testtask/view/sendmail.html.php @@ -1,39 +1,39 @@ - - * @package bug - * @version $Id: sendmail.html.php 3717 2012-12-10 00:37:07Z zhujinyonging@gmail.com $ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - -
          - TESTTASK #id . "=>$testtask->owner " . html::a(common::getSysURL() . $this->createLink('testtask', 'view', "testtaskID=$testtask->id"), $testtask->name);?> -
          -
          - testtask->desc;?> -
          - desc, 'src="data/upload')) - { - $testtask->desc = str_replace('server->http_host . $this->config->webRoot, $testtask->desc); - $testtask->desc = str_replace('server->http_host . $this->config->webRoot, $testtask->desc); - } - echo $testtask->desc; - ?> -
          -
          -
          + + * @package bug + * @version $Id: sendmail.html.php 3717 2012-12-10 00:37:07Z zhujinyonging@gmail.com $ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + +
          + TESTTASK #id . "=>$testtask->owner " . html::a(common::getSysURL() . $this->createLink('testtask', 'view', "testtaskID=$testtask->id"), $testtask->name);?> +
          +
          + testtask->desc;?> +
          + desc, 'src="data/upload')) + { + $testtask->desc = str_replace('server->http_host . $this->config->webRoot, $testtask->desc); + $testtask->desc = str_replace('server->http_host . $this->config->webRoot, $testtask->desc); + } + echo $testtask->desc; + ?> +
          +
          +
          diff --git a/module/testtask/view/view.html.php b/module/testtask/view/view.html.php index d654dcd5e6..03a17a7f76 100644 --- a/module/testtask/view/view.html.php +++ b/module/testtask/view/view.html.php @@ -1,70 +1,70 @@ - - * @package case - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          deleted) echo "class='deleted'";?>>TASK #id . ' ' . $task->name;?>
          testtask->name;?>name;?> -
          testtask->project;?>projectName;?>
          testtask->build;?>buildName ? print($task->buildName) : print($task->build);?>
          testtask->owner;?>owner];?>
          testtask->pri;?>pri;?>
          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::printIcon('testtask', 'cases', "taskID=$task->id"); - common::printIcon('testtask', 'linkCase', "taskID=$task->id"); - - common::printDivider(); - common::printIcon('testtask', 'edit', "taskID=$task->id"); - common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'button', '', 'hiddenwin'); - } - common::printRPN($browseLink); - ?> -
          - - + + * @package case + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          deleted) echo "class='deleted'";?>>TASK #id . ' ' . $task->name;?>
          testtask->name;?>name;?> +
          testtask->project;?>projectName;?>
          testtask->build;?>buildName ? print($task->buildName) : print($task->build);?>
          testtask->owner;?>owner];?>
          testtask->pri;?>pri;?>
          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::printIcon('testtask', 'cases', "taskID=$task->id"); + common::printIcon('testtask', 'linkCase', "taskID=$task->id"); + + common::printDivider(); + common::printIcon('testtask', 'edit', "taskID=$task->id"); + common::printIcon('testtask', 'delete', "taskID=$task->id", '', 'button', '', 'hiddenwin'); + } + common::printRPN($browseLink); + ?> +
          + + diff --git a/module/todo/control.php b/module/todo/control.php index 5fec21442d..de81d3d75c 100644 --- a/module/todo/control.php +++ b/module/todo/control.php @@ -1,372 +1,372 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -class todo extends control -{ - /** - * Construct function, load model of task, bug, my. - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->app->loadClass('date'); - $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 = date::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=" . str_replace('-', '', $this->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->date = strftime("%Y-%m-%d", strtotime($date)); - $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->time = date::now(); - $this->display(); - } - - /** - * Batch create todo - * - * @param string $date - * @param string $account - * @access public - * @return void - */ - public function batchCreate($date = 'today', $account = '') - { - if($date == 'today') $date = date(DT_DATE1, time()); - if(!empty($_POST)) - { - $this->todo->batchCreate(); - if(dao::isError()) die(js::error(dao::getError())); - - /* Locate the browser. */ - $date = str_replace('-', '', $this->post->date); - die(js::locate($this->createLink('my', 'todo', "date=$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->date = (int)$date == 0 ? $date : date('Y-m-d', strtotime($date)); - $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->time = date::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'); - - $todo->date = strftime("%Y-%m-%d", strtotime($todo->date)); - $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->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->todo = $todo; - $this->display(); - } - - /** - * Batch edit todo. - * - * @param string $from example:myTodo, todoBatchEdit. - * @param string $type - * @param string $account - * @param string $status - * @access public - * @return void - */ - public function batchEdit($from = '', $type = 'today', $account = '', $status = 'all') - { - /* Get form data for my-todo. */ - if($from == 'myTodo') - { - /* Initialize vars. */ - $editedTodos = array(); - $todoIDList = array(); - $columns = 7; - $showSuhosinInfo = false; - - if($account == '') $account = $this->app->user->account; - $bugs = $this->bug->getUserBugPairs($account); - $tasks = $this->task->getUserTaskPairs($account, $status); - $allTodos = $this->todo->getList($type, $account, $status); - if($this->post->todoIDList) $todoIDList = $this->post->todoIDList; - - /* Initialize todos whose need to edited. */ - foreach($allTodos as $todo) - { - if(in_array($todo->id, $todoIDList)) - { - $editedTodos[$todo->id] = $todo; - } - } - foreach($editedTodos as $todo) - { - 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); - $todo->begin = str_replace(':', '', $todo->begin); - $todo->end = str_replace(':', '', $todo->end); - } - - /* Judge whether the edited todos is too large. */ - $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedTodos), $columns); - - /* Set the sessions. */ - $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); - - /* Assign. */ - $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->batchEdit; - $position[] = $this->lang->todo->common; - $position[] = $this->lang->todo->batchEdit; - - if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; - $this->view->bugs = $bugs; - $this->view->tasks = $tasks; - $this->view->editedTodos = $editedTodos; - $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); - $this->view->time = date::now(); - $this->view->header = $header; - $this->view->position = $position; - - $this->display(); - } - /* Get form data from todo-batchEdit. */ - elseif($from == 'todoBatchEdit') - { - $allChanges = $this->todo->batchUpdate(); - foreach($allChanges as $todoID => $changes) - { - if(!empty($changes)) - { - $actionID = $this->loadModel('action')->create('todo', $todoID, 'edited'); - $this->action->logHistory($actionID, $changes); - } - } - - die(js::locate($this->session->todoList, 'parent')); - } - } - - /** - * 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, true); - 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->lang->todo->menuOrder = $this->lang->user->menuOrder; - $this->loadModel('user')->setMenu($this->user->getPairs(), $todo->account); - $this->lang->set('menugroup.todo', $from); - - $this->view->header->title = "TODO #$todo->id $todo->name"; - $this->view->position[] = $this->lang->todo->view; - $this->view->todo = $todo; - $this->view->times = date::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() - { - $todoIDList = $this->post->todoIDList; - $today = date::today(); - $this->dao->update(TABLE_TODO)->set('date')->eq($today)->where('id')->in($todoIDList)->exec(); - die(js::locate($this->session->todoList)); - } - - /** - * 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) - ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() - ->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 = date::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->post->set('kind', 'todo'); - $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 void + */ + public function __construct() + { + parent::__construct(); + $this->app->loadClass('date'); + $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 = date::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=" . str_replace('-', '', $this->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->date = strftime("%Y-%m-%d", strtotime($date)); + $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->time = date::now(); + $this->display(); + } + + /** + * Batch create todo + * + * @param string $date + * @param string $account + * @access public + * @return void + */ + public function batchCreate($date = 'today', $account = '') + { + if($date == 'today') $date = date(DT_DATE1, time()); + if(!empty($_POST)) + { + $this->todo->batchCreate(); + if(dao::isError()) die(js::error(dao::getError())); + + /* Locate the browser. */ + $date = str_replace('-', '', $this->post->date); + die(js::locate($this->createLink('my', 'todo', "date=$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->date = (int)$date == 0 ? $date : date('Y-m-d', strtotime($date)); + $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->time = date::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'); + + $todo->date = strftime("%Y-%m-%d", strtotime($todo->date)); + $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->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->todo = $todo; + $this->display(); + } + + /** + * Batch edit todo. + * + * @param string $from example:myTodo, todoBatchEdit. + * @param string $type + * @param string $account + * @param string $status + * @access public + * @return void + */ + public function batchEdit($from = '', $type = 'today', $account = '', $status = 'all') + { + /* Get form data for my-todo. */ + if($from == 'myTodo') + { + /* Initialize vars. */ + $editedTodos = array(); + $todoIDList = array(); + $columns = 7; + $showSuhosinInfo = false; + + if($account == '') $account = $this->app->user->account; + $bugs = $this->bug->getUserBugPairs($account); + $tasks = $this->task->getUserTaskPairs($account, $status); + $allTodos = $this->todo->getList($type, $account, $status); + if($this->post->todoIDList) $todoIDList = $this->post->todoIDList; + + /* Initialize todos whose need to edited. */ + foreach($allTodos as $todo) + { + if(in_array($todo->id, $todoIDList)) + { + $editedTodos[$todo->id] = $todo; + } + } + foreach($editedTodos as $todo) + { + 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); + $todo->begin = str_replace(':', '', $todo->begin); + $todo->end = str_replace(':', '', $todo->end); + } + + /* Judge whether the edited todos is too large. */ + $showSuhosinInfo = $this->loadModel('common')->judgeSuhosinSetting(count($editedTodos), $columns); + + /* Set the sessions. */ + $this->app->session->set('showSuhosinInfo', $showSuhosinInfo); + + /* Assign. */ + $header['title'] = $this->lang->my->common . $this->lang->colon . $this->lang->todo->batchEdit; + $position[] = $this->lang->todo->common; + $position[] = $this->lang->todo->batchEdit; + + if($showSuhosinInfo) $this->view->suhosinInfo = $this->lang->suhosinInfo; + $this->view->bugs = $bugs; + $this->view->tasks = $tasks; + $this->view->editedTodos = $editedTodos; + $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); + $this->view->time = date::now(); + $this->view->header = $header; + $this->view->position = $position; + + $this->display(); + } + /* Get form data from todo-batchEdit. */ + elseif($from == 'todoBatchEdit') + { + $allChanges = $this->todo->batchUpdate(); + foreach($allChanges as $todoID => $changes) + { + if(!empty($changes)) + { + $actionID = $this->loadModel('action')->create('todo', $todoID, 'edited'); + $this->action->logHistory($actionID, $changes); + } + } + + die(js::locate($this->session->todoList, 'parent')); + } + } + + /** + * 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, true); + 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->lang->todo->menuOrder = $this->lang->user->menuOrder; + $this->loadModel('user')->setMenu($this->user->getPairs(), $todo->account); + $this->lang->set('menugroup.todo', $from); + + $this->view->header->title = "TODO #$todo->id $todo->name"; + $this->view->position[] = $this->lang->todo->view; + $this->view->todo = $todo; + $this->view->times = date::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() + { + $todoIDList = $this->post->todoIDList; + $today = date::today(); + $this->dao->update(TABLE_TODO)->set('date')->eq($today)->where('id')->in($todoIDList)->exec(); + die(js::locate($this->session->todoList)); + } + + /** + * 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) + ->beginIF($this->post->exportType == 'selected')->andWhere('id')->in($this->cookie->checkedItem)->fi() + ->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 = date::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->post->set('kind', 'todo'); + $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 63b191df9c..d38964e238 100644 --- a/module/todo/lang/en.php +++ b/module/todo/lang/en.php @@ -1,82 +1,82 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "Index"; -$lang->todo->create = "Create"; -$lang->todo->batchCreate = "Batch create"; -$lang->todo->edit = "Edit"; -$lang->todo->batchEdit = "Batch 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->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'; -$lang->todo->allUndone = 'Undone'; -$lang->todo->todayTodos = 'Today'; -$lang->todo->yesterdayTodos = 'Yesterday'; -$lang->todo->lastmonthTodos = 'Last Month'; -$lang->todo->thisseasonTodos = 'This Season'; -$lang->todo->thisyearTodos = 'This Year'; -$lang->todo->thismonthTodos = 'This Month'; - -$lang->todo->action = new stdclass(); -$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->batchCreate = "Batch create"; +$lang->todo->edit = "Edit"; +$lang->todo->batchEdit = "Batch 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->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'; +$lang->todo->allUndone = 'Undone'; +$lang->todo->todayTodos = 'Today'; +$lang->todo->yesterdayTodos = 'Yesterday'; +$lang->todo->lastmonthTodos = 'Last Month'; +$lang->todo->thisseasonTodos = 'This Season'; +$lang->todo->thisyearTodos = 'This Year'; +$lang->todo->thismonthTodos = 'This Month'; + +$lang->todo->action = new stdclass(); +$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 5217fd5db3..5f1539f9d3 100644 --- a/module/todo/lang/zh-cn.php +++ b/module/todo/lang/zh-cn.php @@ -1,82 +1,82 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "todo一览"; -$lang->todo->create = "新增"; -$lang->todo->batchCreate = "批量添加"; -$lang->todo->edit = "更新TODO"; -$lang->todo->batchEdit = "批量编辑"; -$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->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 = '所有'; -$lang->todo->allUndone = '之前未完'; -$lang->todo->todayTodos = '今日'; -$lang->todo->yesterdayTodos = '昨日'; -$lang->todo->lastmonthTodos = '上月'; -$lang->todo->thisseasonTodos = '本季'; -$lang->todo->thisyearTodos = '本年'; -$lang->todo->thismonthTodos = '本月'; - -$lang->todo->action = new stdclass(); -$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 = "新增"; +$lang->todo->batchCreate = "批量添加"; +$lang->todo->edit = "更新TODO"; +$lang->todo->batchEdit = "批量编辑"; +$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->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 = '所有'; +$lang->todo->allUndone = '之前未完'; +$lang->todo->todayTodos = '今日'; +$lang->todo->yesterdayTodos = '昨日'; +$lang->todo->lastmonthTodos = '上月'; +$lang->todo->thisseasonTodos = '本季'; +$lang->todo->thisyearTodos = '本年'; +$lang->todo->thismonthTodos = '本月'; + +$lang->todo->action = new stdclass(); +$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 2c602b61bb..2cb50c0843 100644 --- a/module/todo/lang/zh-tw.php +++ b/module/todo/lang/zh-tw.php @@ -1,86 +1,86 @@ - - * @package todo - * @version $Id: zh-tw.php 3753 2012-12-11 05:51:16Z wwccss $ - * @link http://www.zentao.net - */ -$lang->todo->common = 'TODO'; -$lang->todo->index = "todo一覽"; -$lang->todo->create = "新增"; -$lang->todo->batchCreate = "批量添加"; -$lang->todo->edit = "更新TODO"; -$lang->todo->batchEdit = "批量編輯"; -$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 = '所有'; -$lang->todo->allUndone = '之前未完'; -$lang->todo->todayTodos = '今日'; -$lang->todo->yesterdayTodos = '昨日'; -$lang->todo->lastmonthTodos = '上月'; -$lang->todo->thisseasonTodos = '本季'; -$lang->todo->thisyearTodos = '本年'; -$lang->todo->thismonthTodos = '本月'; - -$lang->todo->action = new stdclass(); -$lang->todo->action->marked = array('main' => '$date, 由 $actor 標記為$extra。', 'extra' => $lang->todo->statusList); + + * @package todo + * @version $Id: zh-tw.php 3753 2012-12-11 05:51:16Z wwccss $ + * @link http://www.zentao.net + */ +$lang->todo->common = 'TODO'; +$lang->todo->index = "todo一覽"; +$lang->todo->create = "新增"; +$lang->todo->batchCreate = "批量添加"; +$lang->todo->edit = "更新TODO"; +$lang->todo->batchEdit = "批量編輯"; +$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 = '所有'; +$lang->todo->allUndone = '之前未完'; +$lang->todo->todayTodos = '今日'; +$lang->todo->yesterdayTodos = '昨日'; +$lang->todo->lastmonthTodos = '上月'; +$lang->todo->thisseasonTodos = '本季'; +$lang->todo->thisyearTodos = '本年'; +$lang->todo->thismonthTodos = '本月'; + +$lang->todo->action = new stdclass(); +$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 c8b83feb6b..3183bab75c 100644 --- a/module/todo/model.php +++ b/module/todo/model.php @@ -1,324 +1,324 @@ - - * @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->date == false, 'date', '2030-01-01') - ->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(); - } - - /** - * Create batch todo - * - * @access public - * @return void - */ - public function batchCreate() - { - $todos = fixer::input('post')->cleanInt('date')->get(); - for($i = 0; $i < $this->config->todo->batchCreate; $i++) - { - if($todos->names[$i] != '' || isset($todos->bugs[$i + 1]) || isset($todos->tasks[$i + 1])) - { - $todo->account = $this->app->user->account; - if($this->post->date == false) - { - $todo->date = '2030-01-01'; - } - else - { - $todo->date = $this->post->date; - } - $todo->type = $todos->types[$i]; - $todo->pri = $todos->pris[$i]; - $todo->name = isset($todos->names[$i]) ? $todos->names[$i] : ''; - $todo->desc = $todos->descs[$i]; - $todo->begin = $todos->begins[$i]; - $todo->end = $todos->ends[$i]; - $todo->status = "wait"; - $todo->private = 0; - $todo->idvalue = 0; - if($todo->type == 'bug') $todo->idvalue = isset($todos->bugs[$i + 1]) ? $todos->bugs[$i + 1] : 0; - if($todo->type == 'task') $todo->idvalue = isset($todos->tasks[$i + 1]) ? $todos->tasks[$i + 1] : 0; - - $this->dao->insert(TABLE_TODO)->data($todo)->autoCheck()->exec(); - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - } - else - { - unset($todos->types[$i]); - unset($todos->pris[$i]); - unset($todos->names[$i]); - unset($todos->descs[$i]); - unset($todos->begins[$i]); - unset($todos->ends[$i]); - } - } - } - - /** - * 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->date == false, 'date', '2030-01-01') - ->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); - } - - /** - * Batch update todos. - * - * @access public - * @return array - */ - public function batchUpdate() - { - $todos = array(); - $allChanges = array(); - $todoIDList = $this->post->todoIDList ? $this->post->todoIDList : array(); - - /* Adjust whether the post data is complete, if not, remove the last element of $todoIDList. */ - if($this->session->showSuhosinInfo) array_pop($taskIDList); - - if(!empty($todoIDList)) - { - /* Initialize todos from the post data. */ - foreach($todoIDList as $todoID) - { - $todo->date = $this->post->dates[$todoID]; - $todo->type = $this->post->types[$todoID]; - $todo->pri = $this->post->pris[$todoID]; - $todo->name = $todo->type == 'custom' ? htmlspecialchars($this->post->names[$todoID]) : ''; - $todo->begin = $this->post->begins[$todoID]; - $todo->end = $this->post->ends[$todoID]; - if($todo->type == 'task') $todo->idvalue = isset($this->post->tasks[$todoID]) ? $this->post->tasks[$todoID] : 0; - if($todo->type == 'bug') $todo->idvalue = isset($this->post->bugs[$todoID]) ? $this->post->bugs[$todoID] : 0; - - $todos[$todoID] = $todo; - unset($todo); - } - - foreach($todos as $todoID => $todo) - { - $oldTodo = $this->getById($todoID); - if($oldTodo->type != 'custom') $oldTodo->name = ''; - $this->dao->update(TABLE_TODO)->data($todo) - ->autoCheck() - ->checkIF($todo->type == 'custom', $this->config->todo->edit->requiredFields, 'notempty') - ->checkIF($todo->type == 'bug', 'idvalue', 'notempty') - ->checkIF($todo->type == 'task', 'idvalue', 'notempty') - ->where('id')->eq($todoID) - ->exec(); - - if(!dao::isError()) - { - $allChanges[$todoID] = common::createChanges($oldTodo, $todo); - } - else - { - die(js::error('todo#' . $todoID . dao::getError(true))); - } - } - } - - return $allChanges; - } - - /** - * 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 - * @param bool $setImgSize - * @access public - * @return object|bool - */ - public function getById($todoID, $setImgSize = false) - { - $todo = $this->dao->findById((int)$todoID)->from(TABLE_TODO)->fetch(); - if(!$todo) return false; - if($setImgSize) $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, $pager = null, $orderBy="date, status, begin") - { - $this->app->loadClass('date'); - $todos = array(); - if($date == 'today') - { - $begin = date::today(); - $end = $begin; - } - elseif($date == 'yesterday') - { - $begin = date::yesterday(); - $end = $begin; - } - elseif($date == 'thisweek') - { - extract(date::getThisWeek()); - } - elseif($date == 'lastweek') - { - extract(date::getLastWeek()); - } - elseif($date == 'thismonth') - { - extract(date::getThisMonth()); - } - elseif($date == 'lastmonth') - { - extract(date::getLastMonth()); - } - elseif($date == 'thisseason') - { - extract(date::getThisSeason()); - } - elseif($date == 'thisyear') - { - extract(date::getThisYear()); - } - 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 = date::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($orderBy) - ->beginIF($limit > 0)->limit($limit)->fi() - ->page($pager) - ->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 = date::formatTime($todo->begin); - $todo->end = date::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; - } -} - - - + + * @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->date == false, 'date', '2030-01-01') + ->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(); + } + + /** + * Create batch todo + * + * @access public + * @return void + */ + public function batchCreate() + { + $todos = fixer::input('post')->cleanInt('date')->get(); + for($i = 0; $i < $this->config->todo->batchCreate; $i++) + { + if($todos->names[$i] != '' || isset($todos->bugs[$i + 1]) || isset($todos->tasks[$i + 1])) + { + $todo->account = $this->app->user->account; + if($this->post->date == false) + { + $todo->date = '2030-01-01'; + } + else + { + $todo->date = $this->post->date; + } + $todo->type = $todos->types[$i]; + $todo->pri = $todos->pris[$i]; + $todo->name = isset($todos->names[$i]) ? $todos->names[$i] : ''; + $todo->desc = $todos->descs[$i]; + $todo->begin = $todos->begins[$i]; + $todo->end = $todos->ends[$i]; + $todo->status = "wait"; + $todo->private = 0; + $todo->idvalue = 0; + if($todo->type == 'bug') $todo->idvalue = isset($todos->bugs[$i + 1]) ? $todos->bugs[$i + 1] : 0; + if($todo->type == 'task') $todo->idvalue = isset($todos->tasks[$i + 1]) ? $todos->tasks[$i + 1] : 0; + + $this->dao->insert(TABLE_TODO)->data($todo)->autoCheck()->exec(); + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + } + else + { + unset($todos->types[$i]); + unset($todos->pris[$i]); + unset($todos->names[$i]); + unset($todos->descs[$i]); + unset($todos->begins[$i]); + unset($todos->ends[$i]); + } + } + } + + /** + * 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->date == false, 'date', '2030-01-01') + ->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); + } + + /** + * Batch update todos. + * + * @access public + * @return array + */ + public function batchUpdate() + { + $todos = array(); + $allChanges = array(); + $todoIDList = $this->post->todoIDList ? $this->post->todoIDList : array(); + + /* Adjust whether the post data is complete, if not, remove the last element of $todoIDList. */ + if($this->session->showSuhosinInfo) array_pop($taskIDList); + + if(!empty($todoIDList)) + { + /* Initialize todos from the post data. */ + foreach($todoIDList as $todoID) + { + $todo->date = $this->post->dates[$todoID]; + $todo->type = $this->post->types[$todoID]; + $todo->pri = $this->post->pris[$todoID]; + $todo->name = $todo->type == 'custom' ? htmlspecialchars($this->post->names[$todoID]) : ''; + $todo->begin = $this->post->begins[$todoID]; + $todo->end = $this->post->ends[$todoID]; + if($todo->type == 'task') $todo->idvalue = isset($this->post->tasks[$todoID]) ? $this->post->tasks[$todoID] : 0; + if($todo->type == 'bug') $todo->idvalue = isset($this->post->bugs[$todoID]) ? $this->post->bugs[$todoID] : 0; + + $todos[$todoID] = $todo; + unset($todo); + } + + foreach($todos as $todoID => $todo) + { + $oldTodo = $this->getById($todoID); + if($oldTodo->type != 'custom') $oldTodo->name = ''; + $this->dao->update(TABLE_TODO)->data($todo) + ->autoCheck() + ->checkIF($todo->type == 'custom', $this->config->todo->edit->requiredFields, 'notempty') + ->checkIF($todo->type == 'bug', 'idvalue', 'notempty') + ->checkIF($todo->type == 'task', 'idvalue', 'notempty') + ->where('id')->eq($todoID) + ->exec(); + + if(!dao::isError()) + { + $allChanges[$todoID] = common::createChanges($oldTodo, $todo); + } + else + { + die(js::error('todo#' . $todoID . dao::getError(true))); + } + } + } + + return $allChanges; + } + + /** + * 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 + * @param bool $setImgSize + * @access public + * @return object|bool + */ + public function getById($todoID, $setImgSize = false) + { + $todo = $this->dao->findById((int)$todoID)->from(TABLE_TODO)->fetch(); + if(!$todo) return false; + if($setImgSize) $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, $pager = null, $orderBy="date, status, begin") + { + $this->app->loadClass('date'); + $todos = array(); + if($date == 'today') + { + $begin = date::today(); + $end = $begin; + } + elseif($date == 'yesterday') + { + $begin = date::yesterday(); + $end = $begin; + } + elseif($date == 'thisweek') + { + extract(date::getThisWeek()); + } + elseif($date == 'lastweek') + { + extract(date::getLastWeek()); + } + elseif($date == 'thismonth') + { + extract(date::getThisMonth()); + } + elseif($date == 'lastmonth') + { + extract(date::getLastMonth()); + } + elseif($date == 'thisseason') + { + extract(date::getThisSeason()); + } + elseif($date == 'thisyear') + { + extract(date::getThisYear()); + } + 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 = date::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($orderBy) + ->beginIF($limit > 0)->limit($limit)->fi() + ->page($pager) + ->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 = date::formatTime($todo->begin); + $todo->end = date::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; + } +} + + + diff --git a/module/todo/view/batchcreate.html.php b/module/todo/view/batchcreate.html.php index 9e79a1acb6..528d40d9fa 100755 --- a/module/todo/view/batchcreate.html.php +++ b/module/todo/view/batchcreate.html.php @@ -1,54 +1,54 @@ - - * @package todo - * @version $Id: create.html.php 2741 2012-04-07 07:24:21Z areyou123456 $ - * @link http://www.zentao.net - */ -?> - - -
          - - - - - - - - - - - - - todo->batchCreate; $i++):?> - - - - - - - - - -
          todo->batchCreate . $lang->colon . html::input('date', $date, "class='select-2 date' onchange='updateAction(this.value)'");?> - todo->futureTodos;?>
          idAB;?>todo->type;?>todo->pri;?>todo->name;?>todo->desc;?>todo->beginAndEnd;?>
          todo->typeList, '', "onchange=loadList(this.value,$i+1) class='select-1'");?>todo->priList, $pri, 'class=select-1');?> - -
          -
          - - -
          -
          - - + + * @package todo + * @version $Id: create.html.php 2741 2012-04-07 07:24:21Z areyou123456 $ + * @link http://www.zentao.net + */ +?> + + +
          + + + + + + + + + + + + + todo->batchCreate; $i++):?> + + + + + + + + + +
          todo->batchCreate . $lang->colon . html::input('date', $date, "class='select-2 date' onchange='updateAction(this.value)'");?> + todo->futureTodos;?>
          idAB;?>todo->type;?>todo->pri;?>todo->name;?>todo->desc;?>todo->beginAndEnd;?>
          todo->typeList, '', "onchange=loadList(this.value,$i+1) class='select-1'");?>todo->priList, $pri, 'class=select-1');?> + +
          +
          + + +
          +
          + + diff --git a/module/todo/view/batchedit.html.php b/module/todo/view/batchedit.html.php index 89fdf481be..ae617f4060 100644 --- a/module/todo/view/batchedit.html.php +++ b/module/todo/view/batchedit.html.php @@ -1,62 +1,62 @@ - - * @package todo - * @version $Id: create.html.php 2741 2012-04-07 07:24:21Z areyou123456 $ - * @link http://www.zentao.net - */ -?> - - -
          '> - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->batchEdit . $lang->colon;?>
          idAB;?>todo->date;?>todo->type;?>todo->pri;?>todo->name;?>todo->beginAndEnd;?>
          id . html::hidden("todoIDList[$todo->id]", $todo->id);?>id]", $todo->date, "class='text-1 date'");?>id]", $lang->todo->typeList, $todo->type, "onchange=loadList(this.value,$todo->id) class='select-1'");?>id]", $lang->todo->priList, $todo->pri, 'class=select-1');?> - -
          - type == 'custom') - { - echo html::input("names[$todo->id]", $todo->name, "class='f-left text-1'"); echo "*"; - } - elseif($todo->type == 'task') - { - echo html::select("tasks[$todo->id]", $tasks, $todo->idvalue, 'class="select-1 f-left"'); - } - elseif($todo->type == 'bug') - { - echo html::select("bugs[$todo->id]", $bugs, $todo->idvalue, 'class="select-1 f-left"'); - } - ?> -
          -
          id]", $times, $todo->begin) . html::select("ends[$todo->id]", $times, $todo->end);?> -
          -
          - - + + * @package todo + * @version $Id: create.html.php 2741 2012-04-07 07:24:21Z areyou123456 $ + * @link http://www.zentao.net + */ +?> + + +
          '> + + + + + + + + + + + + + + + + + + + + + + + + +
          todo->batchEdit . $lang->colon;?>
          idAB;?>todo->date;?>todo->type;?>todo->pri;?>todo->name;?>todo->beginAndEnd;?>
          id . html::hidden("todoIDList[$todo->id]", $todo->id);?>id]", $todo->date, "class='text-1 date'");?>id]", $lang->todo->typeList, $todo->type, "onchange=loadList(this.value,$todo->id) class='select-1'");?>id]", $lang->todo->priList, $todo->pri, 'class=select-1');?> + +
          + type == 'custom') + { + echo html::input("names[$todo->id]", $todo->name, "class='f-left text-1'"); echo "*"; + } + elseif($todo->type == 'task') + { + echo html::select("tasks[$todo->id]", $tasks, $todo->idvalue, 'class="select-1 f-left"'); + } + elseif($todo->type == 'bug') + { + echo html::select("bugs[$todo->id]", $bugs, $todo->idvalue, 'class="select-1 f-left"'); + } + ?> +
          +
          id]", $times, $todo->begin) . html::select("ends[$todo->id]", $times, $todo->end);?> +
          +
          + + diff --git a/module/todo/view/create.html.php b/module/todo/view/create.html.php index 965c3c2166..a1fd807748 100644 --- a/module/todo/view/create.html.php +++ b/module/todo/view/create.html.php @@ -1,71 +1,71 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->create;?>
          todo->date;?> - todo->futureTodos;?>
          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->futureTodos;?>
          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 f8b93f954e..5717d692f3 100644 --- a/module/todo/view/edit.html.php +++ b/module/todo/view/edit.html.php @@ -1,69 +1,69 @@ - - * @package todo - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
          - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          todo->edit;?>
          todo->date;?>date, "class='select-3 date'");?> - todo->futureTodos;?>
          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 date'");?> + todo->futureTodos;?>
          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 6bc1e78954..6d78e263af 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 c46ce4ebac..dd7a041696 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 #id . ' ' . $todo->name;?>
          todo->account;?>account;?>
          todo->date;?>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::printIcon('todo', 'edit', "todoID=$todo->id"); - common::printIcon('todo', 'delete', "todoID=$todo->id", '', 'button', '', 'hiddenwin'); - } - common::printRPN($browseLink); - ?> -
          - - -todo->thisIsPrivate;?> - - + + * @package todo + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +private or ($todo->private and $todo->account == $app->user->account)):?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          TODO #id . ' ' . $todo->name;?>
          todo->account;?>account;?>
          todo->date;?>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::printIcon('todo', 'edit', "todoID=$todo->id"); + common::printIcon('todo', 'delete', "todoID=$todo->id", '', 'button', '', 'hiddenwin'); + } + common::printRPN($browseLink); + ?> +
          + + +todo->thisIsPrivate;?> + + diff --git a/module/tree/control.php b/module/tree/control.php index e9ceb434e1..e3d1e37784 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -1,293 +1,293 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -class tree extends control -{ - const NEW_CHILD_COUNT = 10; - - /** - * 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'); - } - elseif($viewType == 'task') - { - $project = $this->loadModel('project')->getById($rootID); - $this->view->root = $project; - $this->view->projectModules = $this->tree->getOptionMenu($rootID, 'task'); - } - /* The viewType is doc. */ - elseif(strpos($viewType, 'doc') !== false) - { - $this->loadModel('doc'); - if($rootID == 'product' or $rootID == 'project') - { - $viewType = $rootID . 'doc'; - $lib = new stdclass(); - $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; - $this->lang->tree->menuOrder = $this->lang->product->menuOrder; - - $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'] = $product->name . $this->lang->colon . $this->lang->tree->manageProduct; - $position[] = html::a($this->createLink('product', 'browse', "product=$rootID"), $product->name); - $position[] = $this->lang->tree->manageProduct; - } - elseif($viewType == 'task') - { - $this->lang->set('menugroup.tree', 'project'); - $this->project->setMenu($this->project->getPairs(), $rootID, 'task'); - $this->lang->tree->menu = $this->lang->project->menu; - $this->lang->tree->menuOrder = $this->lang->project->menuOrder; - - $projects = $this->project->getPairs(); - unset($projects[$rootID]); - $currentProject = key($projects); - - $this->view->allProject = $projects; - $this->view->currentProject = $currentProject; - $this->view->projectModules = $this->tree->getOptionMenu($currentProject, 'task'); - - $header['title'] = $project->name . $this->lang->colon . $this->lang->tree->manageProject; - $position[] = html::a($this->createLink('project', 'task', "projectID=$rootID"), $project->name); - $position[] = $this->lang->tree->manageProject; - } - elseif($viewType == 'bug') - { - $this->loadModel('bug')->setMenu($this->product->getPairs(), $rootID); - $this->lang->tree->menu = $this->lang->bug->menu; - $this->lang->tree->menuOrder = $this->lang->bug->menuOrder; - $this->lang->set('menugroup.tree', 'qa'); - - $header['title'] = $product->name . $this->lang->colon . $this->lang->tree->manageBug; - $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->tree->menuOrder = $this->lang->testcase->menuOrder; - $this->lang->set('menugroup.tree', 'qa'); - - $header['title'] = $product->name . $this->lang->colon . $this->lang->tree->manageCase; - $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->tree->menuOrder = $this->lang->doc->menuOrder; - $this->lang->set('menugroup.tree', 'doc'); - - $header['title'] = $lib->name . $this->lang->colon . $this->lang->tree->manageCustomDoc; - $position[] = html::a($this->createLink('doc', 'browse', "libID=$rootID"), $lib->name); - $position[] = $this->lang->tree->manageCustomDoc; - } - elseif(strpos($viewType, 'webapp') !== false) - { - $this->loadModel('webapp')->setMenu(); - $this->lang->tree->menu = $this->lang->webapp->menu; - $this->lang->set('menugroup.tree', 'webapp'); - - $header['title'] = $this->lang->tree->manageWebapp; - $position[] = $this->lang->tree->manageWebapp; - - $root->name = $this->lang->tree->manageWebapp; - $root->id = 0; - $this->view->root = $root; - } - - $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)->QD; - } - $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()); - } - - /** - * Fix path, grades. - * - * @param string $root - * @param string $type - * @access public - * @return void - */ - public function fix($root, $type) - { - $this->tree->fixModulePath($root, $type); - die(js::alert($this->lang->tree->successFixed) . js::reload('parent')); - } - - /** - * 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') - { - $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 - * @param string $type - * @access public - * @return string json_encoded modules. - */ - public function ajaxGetSonModules($moduleID, $rootID = 0, $type = 'story') - { - 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($type) - ->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 = 10; + + /** + * 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'); + } + elseif($viewType == 'task') + { + $project = $this->loadModel('project')->getById($rootID); + $this->view->root = $project; + $this->view->projectModules = $this->tree->getOptionMenu($rootID, 'task'); + } + /* The viewType is doc. */ + elseif(strpos($viewType, 'doc') !== false) + { + $this->loadModel('doc'); + if($rootID == 'product' or $rootID == 'project') + { + $viewType = $rootID . 'doc'; + $lib = new stdclass(); + $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; + $this->lang->tree->menuOrder = $this->lang->product->menuOrder; + + $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'] = $product->name . $this->lang->colon . $this->lang->tree->manageProduct; + $position[] = html::a($this->createLink('product', 'browse', "product=$rootID"), $product->name); + $position[] = $this->lang->tree->manageProduct; + } + elseif($viewType == 'task') + { + $this->lang->set('menugroup.tree', 'project'); + $this->project->setMenu($this->project->getPairs(), $rootID, 'task'); + $this->lang->tree->menu = $this->lang->project->menu; + $this->lang->tree->menuOrder = $this->lang->project->menuOrder; + + $projects = $this->project->getPairs(); + unset($projects[$rootID]); + $currentProject = key($projects); + + $this->view->allProject = $projects; + $this->view->currentProject = $currentProject; + $this->view->projectModules = $this->tree->getOptionMenu($currentProject, 'task'); + + $header['title'] = $project->name . $this->lang->colon . $this->lang->tree->manageProject; + $position[] = html::a($this->createLink('project', 'task', "projectID=$rootID"), $project->name); + $position[] = $this->lang->tree->manageProject; + } + elseif($viewType == 'bug') + { + $this->loadModel('bug')->setMenu($this->product->getPairs(), $rootID); + $this->lang->tree->menu = $this->lang->bug->menu; + $this->lang->tree->menuOrder = $this->lang->bug->menuOrder; + $this->lang->set('menugroup.tree', 'qa'); + + $header['title'] = $product->name . $this->lang->colon . $this->lang->tree->manageBug; + $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->tree->menuOrder = $this->lang->testcase->menuOrder; + $this->lang->set('menugroup.tree', 'qa'); + + $header['title'] = $product->name . $this->lang->colon . $this->lang->tree->manageCase; + $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->tree->menuOrder = $this->lang->doc->menuOrder; + $this->lang->set('menugroup.tree', 'doc'); + + $header['title'] = $lib->name . $this->lang->colon . $this->lang->tree->manageCustomDoc; + $position[] = html::a($this->createLink('doc', 'browse', "libID=$rootID"), $lib->name); + $position[] = $this->lang->tree->manageCustomDoc; + } + elseif(strpos($viewType, 'webapp') !== false) + { + $this->loadModel('webapp')->setMenu(); + $this->lang->tree->menu = $this->lang->webapp->menu; + $this->lang->set('menugroup.tree', 'webapp'); + + $header['title'] = $this->lang->tree->manageWebapp; + $position[] = $this->lang->tree->manageWebapp; + + $root->name = $this->lang->tree->manageWebapp; + $root->id = 0; + $this->view->root = $root; + } + + $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)->QD; + } + $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()); + } + + /** + * Fix path, grades. + * + * @param string $root + * @param string $type + * @access public + * @return void + */ + public function fix($root, $type) + { + $this->tree->fixModulePath($root, $type); + die(js::alert($this->lang->tree->successFixed) . js::reload('parent')); + } + + /** + * 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') + { + $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 + * @param string $type + * @access public + * @return string json_encoded modules. + */ + public function ajaxGetSonModules($moduleID, $rootID = 0, $type = 'story') + { + 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($type) + ->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 fc592ce81e..4c995761ce 100644 --- a/module/tree/lang/en.php +++ b/module/tree/lang/en.php @@ -1,43 +1,43 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->tree = new stdclass(); -$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 = 'Modules'; -$lang->tree->fix = 'Fix'; -$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->manageWebapp = 'Manage web app type'; -$lang->tree->manageCustomDoc = 'Manage doc library type'; -$lang->tree->updateOrder = 'Update order'; -$lang->tree->manageChild = 'Manage child'; -$lang->tree->syncFromProduct = 'Copy from product module'; -$lang->tree->syncFromProject = 'Copy from project 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 = 'Successfully saved'; -$lang->tree->successFixed = 'Successfully fixed.'; - -$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 = new stdclass(); +$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 = 'Modules'; +$lang->tree->fix = 'Fix'; +$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->manageWebapp = 'Manage web app type'; +$lang->tree->manageCustomDoc = 'Manage doc library type'; +$lang->tree->updateOrder = 'Update order'; +$lang->tree->manageChild = 'Manage child'; +$lang->tree->syncFromProduct = 'Copy from product module'; +$lang->tree->syncFromProject = 'Copy from project 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 = 'Successfully saved'; +$lang->tree->successFixed = 'Successfully fixed.'; + +$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 5a4d2268c0..8c4f194e5d 100644 --- a/module/tree/lang/zh-cn.php +++ b/module/tree/lang/zh-cn.php @@ -1,43 +1,43 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->tree = new stdclass(); -$lang->tree->common = '模块维护'; -$lang->tree->add = '添加'; -$lang->tree->edit = '编辑'; -$lang->tree->addChild = '添加子模块'; -$lang->tree->delete = '删除模块'; -$lang->tree->browse = '模块维护'; -$lang->tree->manage = '维护模块'; -$lang->tree->fix = '修正数据'; -$lang->tree->manageProduct = '维护产品视图模块'; -$lang->tree->manageProject = '维护项目视图模块'; -$lang->tree->manageBug = '维护测试视图模块'; -$lang->tree->manageCase = '维护用例视图模块'; -$lang->tree->manageWebapp = '维护WEB应用分类'; -$lang->tree->manageCustomDoc = '维护文档库分类'; -$lang->tree->updateOrder = '更新排序'; -$lang->tree->manageChild = '维护子模块'; -$lang->tree->syncFromProduct = '复制产品视图模块'; -$lang->tree->syncFromProject = '复制项目视图模块'; -$lang->tree->ajaxGetOptionMenu = '接口:获取下拉列表'; -$lang->tree->ajaxGetSonModules = '接口:获得子菜单列表'; - -$lang->tree->confirmDelete = '您确定删除该模块吗?'; -$lang->tree->successSave = '成功保存'; -$lang->tree->successFixed = '成功修正数据!'; - -$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 = new stdclass(); +$lang->tree->common = '模块维护'; +$lang->tree->add = '添加'; +$lang->tree->edit = '编辑'; +$lang->tree->addChild = '添加子模块'; +$lang->tree->delete = '删除模块'; +$lang->tree->browse = '模块维护'; +$lang->tree->manage = '维护模块'; +$lang->tree->fix = '修正数据'; +$lang->tree->manageProduct = '维护产品视图模块'; +$lang->tree->manageProject = '维护项目视图模块'; +$lang->tree->manageBug = '维护测试视图模块'; +$lang->tree->manageCase = '维护用例视图模块'; +$lang->tree->manageWebapp = '维护WEB应用分类'; +$lang->tree->manageCustomDoc = '维护文档库分类'; +$lang->tree->updateOrder = '更新排序'; +$lang->tree->manageChild = '维护子模块'; +$lang->tree->syncFromProduct = '复制产品视图模块'; +$lang->tree->syncFromProject = '复制项目视图模块'; +$lang->tree->ajaxGetOptionMenu = '接口:获取下拉列表'; +$lang->tree->ajaxGetSonModules = '接口:获得子菜单列表'; + +$lang->tree->confirmDelete = '您确定删除该模块吗?'; +$lang->tree->successSave = '成功保存'; +$lang->tree->successFixed = '成功修正数据!'; + +$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 9e625d5e23..1663ca8d0e 100644 --- a/module/tree/lang/zh-tw.php +++ b/module/tree/lang/zh-tw.php @@ -1,43 +1,43 @@ - - * @package tree - * @version $Id: zh-tw.php 3772 2012-12-12 02:18:16Z wwccss $ - * @link http://www.zentao.net - */ -$lang->tree = new stdclass(); -$lang->tree->common = '模組維護'; -$lang->tree->add = '添加'; -$lang->tree->edit = '編輯'; -$lang->tree->addChild = '添加子模組'; -$lang->tree->delete = '刪除模組'; -$lang->tree->browse = '模組維護'; -$lang->tree->manage = '維護模組'; -$lang->tree->fix = '修正數據'; -$lang->tree->manageProduct = '維護產品視圖模組'; -$lang->tree->manageProject = '維護項目視圖模組'; -$lang->tree->manageBug = '維護測試視圖模組'; -$lang->tree->manageCase = '維護用例視圖模組'; -$lang->tree->manageWebapp = '維護WEB應用分類'; -$lang->tree->manageCustomDoc = '維護文檔庫分類'; -$lang->tree->updateOrder = '更新排序'; -$lang->tree->manageChild = '維護子模組'; -$lang->tree->syncFromProduct = '複製產品視圖模組'; -$lang->tree->syncFromProject = '複製項目視圖模組'; -$lang->tree->ajaxGetOptionMenu = '介面:獲取下拉列表'; -$lang->tree->ajaxGetSonModules = '介面:獲得子菜單列表'; - -$lang->tree->confirmDelete = '您確定刪除該模組嗎?'; -$lang->tree->successSave = '成功保存'; -$lang->tree->successFixed = '成功修正數據!'; - -$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 3772 2012-12-12 02:18:16Z wwccss $ + * @link http://www.zentao.net + */ +$lang->tree = new stdclass(); +$lang->tree->common = '模組維護'; +$lang->tree->add = '添加'; +$lang->tree->edit = '編輯'; +$lang->tree->addChild = '添加子模組'; +$lang->tree->delete = '刪除模組'; +$lang->tree->browse = '模組維護'; +$lang->tree->manage = '維護模組'; +$lang->tree->fix = '修正數據'; +$lang->tree->manageProduct = '維護產品視圖模組'; +$lang->tree->manageProject = '維護項目視圖模組'; +$lang->tree->manageBug = '維護測試視圖模組'; +$lang->tree->manageCase = '維護用例視圖模組'; +$lang->tree->manageWebapp = '維護WEB應用分類'; +$lang->tree->manageCustomDoc = '維護文檔庫分類'; +$lang->tree->updateOrder = '更新排序'; +$lang->tree->manageChild = '維護子模組'; +$lang->tree->syncFromProduct = '複製產品視圖模組'; +$lang->tree->syncFromProject = '複製項目視圖模組'; +$lang->tree->ajaxGetOptionMenu = '介面:獲取下拉列表'; +$lang->tree->ajaxGetSonModules = '介面:獲得子菜單列表'; + +$lang->tree->confirmDelete = '您確定刪除該模組嗎?'; +$lang->tree->successSave = '成功保存'; +$lang->tree->successFixed = '成功修正數據!'; + +$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 0768e88ad1..7003e3445a 100644 --- a/module/tree/model.php +++ b/module/tree/model.php @@ -1,587 +1,587 @@ - - * @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 public - * @return void - */ - public 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 public - * @return string - */ - public 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 task. - * - * @param object $module - * @access public - * @return string - */ - public function createTaskLink($module) - { - $linkHtml = html::a(helper::createLink('project', 'task', "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 public - * @return string - */ - public 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 public - * @return string - */ - public 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 public - * @return string - */ - public 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 public - * @return string - */ - public 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 public - * @return string - */ - public 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; - } - - /** - * Create Webapp Link - * - * @param int $module - * @param int $extra - * @access public - * @return void - */ - public function createWebappLink($module, $extra) - { - $linkHtml = html::a(helper::createLink('webapp', 'index', "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) - { - asort($orders); - $i = 0; - foreach($orders as $moduleID => $order) - { - $i++; - $newOrder = $i * 10; - if($newOrder == $order) continue; - $this->dao->update(TABLE_MODULE)->set('`order`')->eq($newOrder)->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($self->root, $self->type); - } - - /** - * 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($module->root, $module->type); - - 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 the path, grade fields according to the id and parent fields. - * - * @param string $root - * @param string $type - * @access public - * @return void - */ - public function fixModulePath($root, $type) - { - /* Get all modules grouped by parent. */ - $groupModules = $this->dao->select('id, parent')->from(TABLE_MODULE)->where('root')->eq($root)->andWhere('type')->eq($type)->fetchGroup('parent', 'id'); - $modules = array(); - - /* Cycle the groupModules until it has no item any more. */ - while(count($groupModules) > 0) - { - $oldCounts = count($groupModules); // Record the counts before processing. - foreach($groupModules as $parentModuleID => $childModules) - { - /* If the parentModule doesn't exsit in the modules, skip it. If exists, compute it's child modules. */ - if(!isset($modules[$parentModuleID]) and $parentModuleID != 0) continue; - if($parentModuleID == 0) - { - $parentModule->grade = 0; - $parentModule->path = ','; - } - else - { - $parentModule = $modules[$parentModuleID]; - } - - /* Compute it's child modules. */ - foreach($childModules as $childModuleID => $childModule) - { - $childModule->grade = $parentModule->grade + 1; - $childModule->path = $parentModule->path . $childModule->id . ','; - $modules[$childModuleID] = $childModule; // Save child module to modules, thus the child of child can compute it's grade and path. - } - unset($groupModules[$parentModuleID]); // Remove it from the groupModules. - } - if(count($groupModules) == $oldCounts) break; // If after processing, no module processed, break the cycle. - } - - /* Save modules to database. */ - foreach($modules as $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 public + * @return void + */ + public 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 public + * @return string + */ + public 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 task. + * + * @param object $module + * @access public + * @return string + */ + public function createTaskLink($module) + { + $linkHtml = html::a(helper::createLink('project', 'task', "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 public + * @return string + */ + public 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 public + * @return string + */ + public 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 public + * @return string + */ + public 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 public + * @return string + */ + public 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 public + * @return string + */ + public 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; + } + + /** + * Create Webapp Link + * + * @param int $module + * @param int $extra + * @access public + * @return void + */ + public function createWebappLink($module, $extra) + { + $linkHtml = html::a(helper::createLink('webapp', 'index', "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) + { + asort($orders); + $i = 0; + foreach($orders as $moduleID => $order) + { + $i++; + $newOrder = $i * 10; + if($newOrder == $order) continue; + $this->dao->update(TABLE_MODULE)->set('`order`')->eq($newOrder)->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($self->root, $self->type); + } + + /** + * 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($module->root, $module->type); + + 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 the path, grade fields according to the id and parent fields. + * + * @param string $root + * @param string $type + * @access public + * @return void + */ + public function fixModulePath($root, $type) + { + /* Get all modules grouped by parent. */ + $groupModules = $this->dao->select('id, parent')->from(TABLE_MODULE)->where('root')->eq($root)->andWhere('type')->eq($type)->fetchGroup('parent', 'id'); + $modules = array(); + + /* Cycle the groupModules until it has no item any more. */ + while(count($groupModules) > 0) + { + $oldCounts = count($groupModules); // Record the counts before processing. + foreach($groupModules as $parentModuleID => $childModules) + { + /* If the parentModule doesn't exsit in the modules, skip it. If exists, compute it's child modules. */ + if(!isset($modules[$parentModuleID]) and $parentModuleID != 0) continue; + if($parentModuleID == 0) + { + $parentModule->grade = 0; + $parentModule->path = ','; + } + else + { + $parentModule = $modules[$parentModuleID]; + } + + /* Compute it's child modules. */ + foreach($childModules as $childModuleID => $childModule) + { + $childModule->grade = $parentModule->grade + 1; + $childModule->path = $parentModule->path . $childModule->id . ','; + $modules[$childModuleID] = $childModule; // Save child module to modules, thus the child of child can compute it's grade and path. + } + unset($groupModules[$parentModuleID]); // Remove it from the groupModules. + } + if(count($groupModules) == $oldCounts) break; // If after processing, no module processed, break the cycle. + } + + /* Save modules to database. */ + foreach($modules as $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 4a8f222f01..d29dd7d013 100644 --- a/module/tree/view/browse.html.php +++ b/module/tree/view/browse.html.php @@ -1,116 +1,116 @@ - - * @package tree - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
              -
              id}&viewType=$viewType");?>'> - - - - - -
              title;?>
              -
              -
              - tree->updateOrder);?> -
              -
              -
              -
              -
              id}&viewType=$viewType");?>'> - - - - - - - - - - -
              doc->manageType : $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->syncFromProject, "id='copyModule' onclick='syncModule($currentProject, \"task\")'"); - } - echo '
              '; - } - elseif($viewType != 'story' and strpos($viewType, 'doc') === false and $viewType != 'webapp') - { - echo html::select('productModule', $productModules, '', 'class=select-3'); - echo html::commonButton($lang->tree->syncFromProduct, 'onclick="syncModule('.$rootID.')"'); - echo '
              '; - } - else if($viewType == 'story') - { - if($allProduct) - { - echo html::select('allProduct', $allProduct, '', 'onchange=syncProductOrProject(this,"product")'); - echo html::select('productModule', $productModules, ''); - echo html::commonButton($lang->tree->syncFromProduct, "id='copyModule' onclick='syncModule($currentProduct, \"story\")'"); - } - 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");?>'> + + + + + + + + + + +
              doc->manageType : $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->syncFromProject, "id='copyModule' onclick='syncModule($currentProject, \"task\")'"); + } + echo '
              '; + } + elseif($viewType != 'story' and strpos($viewType, 'doc') === false and $viewType != 'webapp') + { + echo html::select('productModule', $productModules, '', 'class=select-3'); + echo html::commonButton($lang->tree->syncFromProduct, 'onclick="syncModule('.$rootID.')"'); + echo '
              '; + } + else if($viewType == 'story') + { + if($allProduct) + { + echo html::select('allProduct', $allProduct, '', 'onchange=syncProductOrProject(this,"product")'); + echo html::select('productModule', $productModules, ''); + echo html::commonButton($lang->tree->syncFromProduct, "id='copyModule' onclick='syncModule($currentProduct, \"story\")'"); + } + 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 790ec37473..6b72c28d4e 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 c3bbf2930a..0329a990c6 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 f0d4f17f5a..ef901ffad9 100644 --- a/module/upgrade/lang/en.php +++ b/module/upgrade/lang/en.php @@ -1,68 +1,68 @@ - - * @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'; -$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; -$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; -$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; -$lang->upgrade->fromVersions['3_1'] = '3.1'; -$lang->upgrade->fromVersions['3_2'] = '3.2'; -$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; -$lang->upgrade->fromVersions['3_3'] = '3.3'; -$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; + + * @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'; +$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; +$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; +$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; +$lang->upgrade->fromVersions['3_1'] = '3.1'; +$lang->upgrade->fromVersions['3_2'] = '3.2'; +$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; +$lang->upgrade->fromVersions['3_3'] = '3.3'; +$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; diff --git a/module/upgrade/lang/zh-cn.php b/module/upgrade/lang/zh-cn.php index 71faa8a275..2da7d7d0f2 100644 --- a/module/upgrade/lang/zh-cn.php +++ b/module/upgrade/lang/zh-cn.php @@ -1,68 +1,68 @@ - - * @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'; -$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; -$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; -$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; -$lang->upgrade->fromVersions['3_1'] = '3.1'; -$lang->upgrade->fromVersions['3_2'] = '3.2'; -$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; -$lang->upgrade->fromVersions['3_3'] = '3.3'; -$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; + + * @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'; +$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; +$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; +$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; +$lang->upgrade->fromVersions['3_1'] = '3.1'; +$lang->upgrade->fromVersions['3_2'] = '3.2'; +$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; +$lang->upgrade->fromVersions['3_3'] = '3.3'; +$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; diff --git a/module/upgrade/lang/zh-tw.php b/module/upgrade/lang/zh-tw.php index 4a83b29148..7ed2f1944e 100644 --- a/module/upgrade/lang/zh-tw.php +++ b/module/upgrade/lang/zh-tw.php @@ -1,68 +1,68 @@ - - * @package upgrade - * @version $Id: zh-tw.php 3837 2012-12-18 03:05:26Z wyd621@gmail.com $ - * @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'; -$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; -$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; -$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; -$lang->upgrade->fromVersions['3_1'] = '3.1'; -$lang->upgrade->fromVersions['3_2'] = '3.2'; -$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; -$lang->upgrade->fromVersions['3_3'] = '3.3'; -$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; + + * @package upgrade + * @version $Id: zh-tw.php 3837 2012-12-18 03:05:26Z wyd621@gmail.com $ + * @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'; +$lang->upgrade->fromVersions['3_0_beta1'] = '3.0 BETA1'; +$lang->upgrade->fromVersions['3_0_beta2'] = '3.0 BETA2'; +$lang->upgrade->fromVersions['3_0'] = '3.0 STABLE'; +$lang->upgrade->fromVersions['3_1'] = '3.1'; +$lang->upgrade->fromVersions['3_2'] = '3.2'; +$lang->upgrade->fromVersions['3_2_1'] = '3.2.1'; +$lang->upgrade->fromVersions['3_3'] = '3.3'; +$lang->upgrade->fromVersions['4_0_beta1'] = '4.0 BETA1'; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index d6756037f9..007194f75c 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -1,563 +1,563 @@ - - * @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) - { - switch($fromVersion) - { - case '0_3beta': $this->execSQL($this->getUpgradeFile('0.3')); - case '0_4beta': $this->execSQL($this->getUpgradeFile('0.4')); - case '0_5beta': $this->execSQL($this->getUpgradeFile('0.5')); - case '0_6beta': $this->execSQL($this->getUpgradeFile('0.6')); - case '1_0beta': - $this->execSQL($this->getUpgradeFile('1.0.beta')); - $this->updateCompany(); - case '1_0rc1': $this->execSQL($this->getUpgradeFile('1.0.rc1')); - case '1_0rc2': - case '1_0': - case '1_0_1': $this->execSQL($this->getUpgradeFile('1.0.1')); - case '1_1': $this->execSQL($this->getUpgradeFile('1.1')); - case '1_2': - $this->execSQL($this->getUpgradeFile('1.2')); - $this->updateUBB(); - $this->updateNL1_2(); - case '1_3': - $this->execSQL($this->getUpgradeFile('1.3')); - $this->updateNL1_3(); - $this->updateTasks(); - case '1_4': $this->execSQL($this->getUpgradeFile('1.4')); - case '1_5': $this->execSQL($this->getUpgradeFile('1.5')); - case '2_0': $this->execSQL($this->getUpgradeFile('2.0')); - case '2_1': $this->execSQL($this->getUpgradeFile('2.1')); - case '2_2': - $this->execSQL($this->getUpgradeFile('2.2')); - $this->updateCases(); - $this->updateActivatedCountOfBug(); - case '2_3': $this->execSQL($this->getUpgradeFile('2.3')); - case '2_4': $this->execSQL($this->getUpgradeFile('2.4')); - case '3_0_beta1': - $this->execSQL($this->getUpgradeFile('3.0.beta1')); - $this->updateAction(); - $this->setOrderData(); - case '3_0_beta2': - case '3_0': - case '3_1': $this->execSQL($this->getUpgradeFile('3.1')); - case '3_2': $this->execSQL($this->getUpgradeFile('3.2')); - case '3_2_1': $this->execSQL($this->getUpgradeFile('3.2.1')); - case '3_3': - $this->execSQL($this->getUpgradeFile('3.3')); - $this->updateTaskAssignedTo(); - $this->loadModel('setting')->setItem('system.common.global.flow', 'full'); - case '4_0_beta1': $this->execSQL($this->getUpgradeFile('4.0.beta1')); - - default: if(!$this->isError()) $this->setting->updateVersion($this->config->version); - } - - $this->deletePatch(); - } - - /** - * Create the confirm contents. - * - * @param string $fromVersion - * @access public - * @return string - */ - public function getConfirm($fromVersion) - { - $confirmContent = ''; - switch($fromVersion) - { - case '0_3beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.3')); - case '0_4beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); - case '0_5beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); - case '0_6beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); - case '1_0beta': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); - case '1_0rc1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); - case '1_0rc2': - case '1_0': - case '1_0_1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); - case '1_1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); - case '1_2': $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); - case '1_3': $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); - case '1_4': $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); - case '1_5': $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); - case '2_0': $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); - case '2_1': $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); - case '2_2': $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); - case '2_3': $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); - case '2_4': $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); - case '3_0_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.0.beta1')); - case '3_0_beta2': - case '3_0': - case '3_1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.1')); - case '3_2': $confirmContent .= file_get_contents($this->getUpgradeFile('3.2')); - case '3_2_1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.2.1')); - case '3_3': $confirmContent .= file_get_contents($this->getUpgradeFile('3.3')); - case '4_0_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('4.0.beta1')); - } - return str_replace('zt_', $this->config->db->prefix, $confirmContent); - } - - /** - * Update company field. - * - * This method is used to update since 1.0 beta. Any new tables added after 1.0 beta should skip. - * - * @access public - * @return void - */ - public 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 public - * @return void - */ - public 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 - */ - public 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(); - } - } - - /** - * Update the data of action. - * - * @access public - * @return void - */ - public function updateAction() - { - /* Get projects and tasks from action table. */ - $projects = $this->dao->select('id')->from(TABLE_PROJECT)->fetchPairs('id'); - $tasks = $this->dao->select('id, project')->from(TABLE_TASK)->fetchPairs('id'); - - /* Get products of projects and tasks. */ - $projectProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($projects))->fetchGroup('project', 'product'); - $taskProducts = $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(array_keys($tasks)) - ->fetchPairs('id'); - - /* Process project actions. */ - foreach($projects as $projectID) - { - $productList = isset($projectProducts[$projectID]) ? join(',', array_keys($projectProducts[$projectID])) : ''; - $this->dao->update(TABLE_ACTION)->set('product')->eq($productList)->where('objectType')->eq('project')->andWhere('objectID')->eq($projectID)->exec(); - } - - /* Process task actions. */ - foreach($tasks as $taskID => $projectID) - { - $productList = ''; - if($taskProducts[$taskID]) - { - $productList = $taskProducts[$taskID]; - } - else - { - $productList = isset($projectProducts[$projectID]) ? join(',', array_keys($projectProducts[$projectID])) : ''; - } - $this->dao->update(TABLE_ACTION)->set('product')->eq($productList)->where('objectType')->eq('task')->andWhere('objectID')->eq($taskID)->andWhere('project')->eq($projectID)->exec(); - } - - $this->dao->update(TABLE_ACTION)->set("product = concat(',',product,',')")->exec(); - return true; - } - - /** - * Init the data of product and project order field. - * - * @access public - * @return void - */ - public function setOrderData() - { - $products = $this->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->orderBy('code')->fetchAll('id'); - foreach(array_keys($products) as $key => $productID) - { - $this->dao->update(TABLE_PRODUCT)->set('`order`')->eq(($key + 1) * 10)->where('id')->eq($productID)->exec(); - } - $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('iscat')->eq(0)->andWhere('deleted')->eq(0)->orderBy('status, id desc')->fetchAll('id'); - foreach(array_keys($projects) as $key => $projectID) - { - $this->dao->update(TABLE_PROJECT)->set('`order`')->eq(($key + 1) * 10)->where('id')->eq($projectID)->exec(); - } - return true; - } - - /** - * Update task assignedTo. - * - * @access public - * @return void - */ - public function updateTaskAssignedTo() - { - $this->dao->update(TABLE_TASK)->set('assignedTo')->eq('closed') - ->where('status')->eq('closed') - ->andWhere('assignedTo')->eq('') - ->exec(); - return true; - } - - /** - * 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 public - * @return string - */ - public function getUpgradeFile($version) - { - return $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'update' . $version . '.sql'; - } - - /** - * Execute a sql. - * - * @param string $sqlFile - * @access public - * @return void - */ - public 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) + { + switch($fromVersion) + { + case '0_3beta': $this->execSQL($this->getUpgradeFile('0.3')); + case '0_4beta': $this->execSQL($this->getUpgradeFile('0.4')); + case '0_5beta': $this->execSQL($this->getUpgradeFile('0.5')); + case '0_6beta': $this->execSQL($this->getUpgradeFile('0.6')); + case '1_0beta': + $this->execSQL($this->getUpgradeFile('1.0.beta')); + $this->updateCompany(); + case '1_0rc1': $this->execSQL($this->getUpgradeFile('1.0.rc1')); + case '1_0rc2': + case '1_0': + case '1_0_1': $this->execSQL($this->getUpgradeFile('1.0.1')); + case '1_1': $this->execSQL($this->getUpgradeFile('1.1')); + case '1_2': + $this->execSQL($this->getUpgradeFile('1.2')); + $this->updateUBB(); + $this->updateNL1_2(); + case '1_3': + $this->execSQL($this->getUpgradeFile('1.3')); + $this->updateNL1_3(); + $this->updateTasks(); + case '1_4': $this->execSQL($this->getUpgradeFile('1.4')); + case '1_5': $this->execSQL($this->getUpgradeFile('1.5')); + case '2_0': $this->execSQL($this->getUpgradeFile('2.0')); + case '2_1': $this->execSQL($this->getUpgradeFile('2.1')); + case '2_2': + $this->execSQL($this->getUpgradeFile('2.2')); + $this->updateCases(); + $this->updateActivatedCountOfBug(); + case '2_3': $this->execSQL($this->getUpgradeFile('2.3')); + case '2_4': $this->execSQL($this->getUpgradeFile('2.4')); + case '3_0_beta1': + $this->execSQL($this->getUpgradeFile('3.0.beta1')); + $this->updateAction(); + $this->setOrderData(); + case '3_0_beta2': + case '3_0': + case '3_1': $this->execSQL($this->getUpgradeFile('3.1')); + case '3_2': $this->execSQL($this->getUpgradeFile('3.2')); + case '3_2_1': $this->execSQL($this->getUpgradeFile('3.2.1')); + case '3_3': + $this->execSQL($this->getUpgradeFile('3.3')); + $this->updateTaskAssignedTo(); + $this->loadModel('setting')->setItem('system.common.global.flow', 'full'); + case '4_0_beta1': $this->execSQL($this->getUpgradeFile('4.0.beta1')); + + default: if(!$this->isError()) $this->setting->updateVersion($this->config->version); + } + + $this->deletePatch(); + } + + /** + * Create the confirm contents. + * + * @param string $fromVersion + * @access public + * @return string + */ + public function getConfirm($fromVersion) + { + $confirmContent = ''; + switch($fromVersion) + { + case '0_3beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.3')); + case '0_4beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.4')); + case '0_5beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.5')); + case '0_6beta': $confirmContent .= file_get_contents($this->getUpgradeFile('0.6')); + case '1_0beta': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.beta')); + case '1_0rc1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.rc1')); + case '1_0rc2': + case '1_0': + case '1_0_1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.0.1')); + case '1_1': $confirmContent .= file_get_contents($this->getUpgradeFile('1.1')); + case '1_2': $confirmContent .= file_get_contents($this->getUpgradeFile('1.2')); + case '1_3': $confirmContent .= file_get_contents($this->getUpgradeFile('1.3')); + case '1_4': $confirmContent .= file_get_contents($this->getUpgradeFile('1.4')); + case '1_5': $confirmContent .= file_get_contents($this->getUpgradeFile('1.5')); + case '2_0': $confirmContent .= file_get_contents($this->getUpgradeFile('2.0')); + case '2_1': $confirmContent .= file_get_contents($this->getUpgradeFile('2.1')); + case '2_2': $confirmContent .= file_get_contents($this->getUpgradeFile('2.2')); + case '2_3': $confirmContent .= file_get_contents($this->getUpgradeFile('2.3')); + case '2_4': $confirmContent .= file_get_contents($this->getUpgradeFile('2.4')); + case '3_0_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.0.beta1')); + case '3_0_beta2': + case '3_0': + case '3_1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.1')); + case '3_2': $confirmContent .= file_get_contents($this->getUpgradeFile('3.2')); + case '3_2_1': $confirmContent .= file_get_contents($this->getUpgradeFile('3.2.1')); + case '3_3': $confirmContent .= file_get_contents($this->getUpgradeFile('3.3')); + case '4_0_beta1': $confirmContent .= file_get_contents($this->getUpgradeFile('4.0.beta1')); + } + return str_replace('zt_', $this->config->db->prefix, $confirmContent); + } + + /** + * Update company field. + * + * This method is used to update since 1.0 beta. Any new tables added after 1.0 beta should skip. + * + * @access public + * @return void + */ + public 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 public + * @return void + */ + public 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 + */ + public 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(); + } + } + + /** + * Update the data of action. + * + * @access public + * @return void + */ + public function updateAction() + { + /* Get projects and tasks from action table. */ + $projects = $this->dao->select('id')->from(TABLE_PROJECT)->fetchPairs('id'); + $tasks = $this->dao->select('id, project')->from(TABLE_TASK)->fetchPairs('id'); + + /* Get products of projects and tasks. */ + $projectProducts = $this->dao->select('project,product')->from(TABLE_PROJECTPRODUCT)->where('project')->in(array_keys($projects))->fetchGroup('project', 'product'); + $taskProducts = $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(array_keys($tasks)) + ->fetchPairs('id'); + + /* Process project actions. */ + foreach($projects as $projectID) + { + $productList = isset($projectProducts[$projectID]) ? join(',', array_keys($projectProducts[$projectID])) : ''; + $this->dao->update(TABLE_ACTION)->set('product')->eq($productList)->where('objectType')->eq('project')->andWhere('objectID')->eq($projectID)->exec(); + } + + /* Process task actions. */ + foreach($tasks as $taskID => $projectID) + { + $productList = ''; + if($taskProducts[$taskID]) + { + $productList = $taskProducts[$taskID]; + } + else + { + $productList = isset($projectProducts[$projectID]) ? join(',', array_keys($projectProducts[$projectID])) : ''; + } + $this->dao->update(TABLE_ACTION)->set('product')->eq($productList)->where('objectType')->eq('task')->andWhere('objectID')->eq($taskID)->andWhere('project')->eq($projectID)->exec(); + } + + $this->dao->update(TABLE_ACTION)->set("product = concat(',',product,',')")->exec(); + return true; + } + + /** + * Init the data of product and project order field. + * + * @access public + * @return void + */ + public function setOrderData() + { + $products = $this->dao->select('*')->from(TABLE_PRODUCT)->where('deleted')->eq(0)->orderBy('code')->fetchAll('id'); + foreach(array_keys($products) as $key => $productID) + { + $this->dao->update(TABLE_PRODUCT)->set('`order`')->eq(($key + 1) * 10)->where('id')->eq($productID)->exec(); + } + $projects = $this->dao->select('*')->from(TABLE_PROJECT)->where('iscat')->eq(0)->andWhere('deleted')->eq(0)->orderBy('status, id desc')->fetchAll('id'); + foreach(array_keys($projects) as $key => $projectID) + { + $this->dao->update(TABLE_PROJECT)->set('`order`')->eq(($key + 1) * 10)->where('id')->eq($projectID)->exec(); + } + return true; + } + + /** + * Update task assignedTo. + * + * @access public + * @return void + */ + public function updateTaskAssignedTo() + { + $this->dao->update(TABLE_TASK)->set('assignedTo')->eq('closed') + ->where('status')->eq('closed') + ->andWhere('assignedTo')->eq('') + ->exec(); + return true; + } + + /** + * 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 public + * @return string + */ + public function getUpgradeFile($version) + { + return $this->app->getAppRoot() . 'db' . $this->app->getPathFix() . 'update' . $version . '.sql'; + } + + /** + * Execute a sql. + * + * @param string $sqlFile + * @access public + * @return void + */ + public 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 d1928c3b04..3f3f422f31 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 9f0c65312d..6755a5ce56 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 e1d1ab74d7..5e9bb9d7b6 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 9a34aa4583..350ceb7183 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 bac616f1fe..e812c3929d 100644 --- a/module/user/control.php +++ b/module/user/control.php @@ -1,762 +1,762 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -class user extends control -{ - public $referer; - - /** - * Construct - * - * @access public - * @return void - */ - public function __construct() - { - parent::__construct(); - $this->loadModel('company')->setMenu(); - $this->loadModel('dept'); - $this->loadModel('todo'); - } - - /** - * View a user. - * - * @param string $account - * @access public - * @return void - */ - public function view($account) - { - $this->locate($this->createLink('user', 'todo', "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 - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function todo($account, $type = 'today', $status = 'all', $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* 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); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* set menus. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed|nodeleted'), $account); - $this->view->userList = $this->user->setUserList($this->user->getPairs('noempty|noclosed'), $account); - - /* Get user, totos. */ - $user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $todos = $this->todo->getList($type, $account, $status, 0, $pager); - $date = (int)$type == 0 ? helper::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->date = $date; - $this->view->todos = $todos; - $this->view->user = $user; - $this->view->account = $account; - $this->view->type = $type; - $this->view->pager = $pager; - - $this->display(); - } - - /** - * Tasks of a user. - * - * @param string $account - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function task($account, $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save the session. */ - $this->session->set('taskList', $this->app->getURI(true)); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* Set the menu. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - $this->view->userList = $this->user->setUserList($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, 'assignedto', 0, $pager); - $this->view->account = $account; - $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $this->view->pager = $pager; - - $this->display(); - } - - /** - * User bugs. - * - * @param string $account - * @param int $recTotal - * @param int $recPerPage - * @param int $pageID - * @access public - * @return void - */ - public function bug($account, $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - /* Save the session. */ - $this->session->set('bugList', $this->app->getURI(true)); - - /* Load pager. */ - $this->app->loadClass('pager', $static = true); - $pager = pager::init($recTotal, $recPerPage, $pageID); - - /* Set menu. */ - $this->lang->set('menugroup.user', 'company'); - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - $this->view->userList = $this->user->setUserList($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, $pager); - $this->view->account = $account; - $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $this->view->users = $this->user->getPairs('noletter'); - $this->view->pager = $pager; - - $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); - $this->view->userList = $this->user->setUserList($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->account = $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) - { - $position[] = $this->lang->user->profile; - - /* Set menu. */ - $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); - $this->view->userList = $this->user->setUserList($this->user->getPairs('noempty|noclosed'), $account); - - $user = $this->user->getById($account); - $deptPath = $this->dept->getParents($user->dept); - - $header['title'] = "USER #$user->id $user->account/" . $this->lang->user->profile; - $this->view->header = $header; - $this->view->position = $position; - $this->view->account = $account; - $this->view->user = $user; - - $this->view->deptPath = $deptPath; - - $this->display(); - } - - /** - * Set the rerferer. - * - * @param string $referer - * @access public - * @return void - */ - public 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; - $this->lang->user->menuOrder = $this->lang->company->menuOrder; - - if(!empty($_POST)) - { - $this->user->create(); - if(dao::isError()) die(js::error(dao::getError())); - die(js::locate($this->createLink('company', 'browse'), 'parent')); - } - $groups = $this->dao->select('id, name, role')->from(TABLE_GROUP)->fetchAll(); - $groupList = array('' => ''); - $roleGroup = array(); - foreach($groups as $group) - { - $groupList[$group->id] = $group->name; - if($group->role) $roleGroup[$group->role] = $group->id; - } - - $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->groupList = $groupList; - $this->view->roleGroup = $roleGroup; - $this->view->deptID = $deptID; - - $this->display(); - } - - - /** - * Batch create users. - * - * @param int $deptID - * @access public - * @return void - */ - public function batchCreate($deptID = 0) - { - $groups = $this->dao->select('id, name, role')->from(TABLE_GROUP)->fetchAll(); - $groupList = array('' => ''); - $roleGroup = array(); - foreach($groups as $group) - { - $groupList[$group->id] = $group->name; - if($group->role) $roleGroup[$group->role] = $group->id; - } - - $this->lang->set('menugroup.user', 'company'); - $this->lang->user->menu = $this->lang->company->menu; - $this->lang->user->menuOrder = $this->lang->company->menuOrder; - - if(!empty($_POST)) - { - $this->user->batchCreate(); - die(js::locate($this->createLink('company', 'browse'), 'parent')); - } - - $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->batchCreate; - $position[] = $this->lang->user->batchCreate; - $this->view->header = $header; - $this->view->position = $position; - $this->view->depts = $this->dept->getOptionMenu(); - $this->view->deptID = $deptID; - $this->view->groupList = $groupList; - $this->view->roleGroup = $roleGroup; - - $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; - $this->lang->user->menuOrder = $this->lang->company->menuOrder; - 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(); - } - - /** - * Batch edit user. - * - * @param int $deptID - * @access public - * @return void - */ - public function batchEdit($deptID = 0) - { - if(isset($_POST['users'])) - { - $this->view->users = $this->dao->select('*')->from(TABLE_USER)->where('account')->in($this->post->users)->orderBy('id')->fetchAll('id'); - } - elseif($_POST) - { - $this->user->batchEdit(); - die(js::locate($this->createLink('company', 'browse', "deptID=$deptID"), 'parent')); - } - $this->lang->set('menugroup.user', 'company'); - $this->lang->user->menu = $this->lang->company->menu; - $this->lang->user->menuOrder = $this->lang->company->menuOrder; - - $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->batchEdit; - $position[] = $this->lang->user->edit; - $this->view->header = $header; - $this->view->position = $position; - $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')); - } - } - - /** - * Unlock a user. - * - * @param int $account - * @param string $confirm - * @access public - * @return void - */ - public function unlock($account, $confirm = 'no') - { - if($confirm == 'no') - { - die(js::confirm($this->lang->user->confirmUnlock, $this->createLink('user', 'unlock', "account=$account&confirm=yes"))); - } - else - { - $this->user->cleanLocked($account); - 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; - - if($this->user->checkLocked($account)) die(js::error(sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes))); - - $user = $this->user->identify($account, $password); - - if($user) - { - $this->user->cleanLocked($account); - /* Authorize him and save to session. */ - $user->rights = $this->user->authorize($account); - $user->groups = $this->user->getGroups($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'))); - $fails = $this->user->failPlus($account); - $remainTimes = $this->config->user->failTimes - $fails; - if($remainTimes <= 0) - { - die(js::error(sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes))); - } - else if($remainTimes <= 3) - { - die(js::error(sprintf($this->lang->user->lockWarning, $remainTimes))); - } - die(js::error($this->lang->user->loginFailed)); - } - } - else - { - if(!empty($this->config->global->showDemoUsers)) - { - $demoUsers = $this->user->getPairs('nodeleted, noletter, noempty, noclosed'); - $this->view->demoUsers = $demoUsers; - } - - $header['title'] = $this->lang->user->login; - $this->view->header = $header; - $this->view->referer = $this->referer; - $this->view->s = $this->config->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) - { - if(isset($this->app->user->id)) $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); - $this->view->userList = $this->user->setUserList($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->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); - $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager); - $this->display(); - } - - /** - * Manage contacts. - * - * @param int $listID - * @access public - * @return void - */ - public function manageContacts($listID = 0) - { - $lists = $this->user->getContactLists($this->app->user->account); - - /* If set $mode, need to update database. */ - if($this->post->mode) - { - /* The mode is new: append or new a list. */ - if($this->post->mode == 'new') - { - if($this->post->list2Append) - { - $this->user->append2ContactList($this->post->list2Append, $this->post->users); - die(js::locate(inlink('manageContacts', "listID={$this->post->list2Append}"), 'parent')); - } - elseif($this->post->newList) - { - $listID = $this->user->createContactList($this->post->newList, $this->post->users); - die(js::locate(inlink('manageContacts', "listID=$listID"), 'parent')); - } - } - elseif($this->post->mode == 'edit') - { - $this->user->updateContactList($this->post->listID, $this->post->listName, $this->post->users); - die(js::locate(inlink('manageContacts', "listID={$this->post->listID}"), 'parent')); - } - } - if($this->post->users) - { - $mode = 'new'; - $users = $this->user->getContactUserPairs($this->post->users); - } - else - { - $mode = 'edit'; - $listID= $listID ? $listID : key($lists); - if(!$listID) die(js::alert($this->lang->user->contacts->noListYet) . js::locate($this->createLink('company', 'browse'), 'parent')); - - $list = $this->user->getContactListByID($listID); - $users = explode(',', $list->userList); - $users = $this->user->getContactUserPairs($users); - $this->view->list = $list; - } - - $this->view->lists = $this->user->getContactLists($this->app->user->account); - $this->view->users = $users; - $this->view->mode = $mode; - $this->display(); - } - - /** - * Delete a contact list. - * - * @param int $listID - * @param string $confirm - * @access public - * @return void - */ - public function deleteContacts($listID, $confirm = 'no') - { - if($confirm == 'no') - { - echo js::confirm($this->lang->user->contacts->confirmDelete, inlink('deleteContacts', "listID=$listID&confirm=yes")); - exit; - } - else - { - $this->user->deleteContactList($listID); - echo js::locate(inlink('manageContacts'), 'parent'); - exit; - } - } - - /** - * 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; - } - - /** - * AJAX: get users from a contact list. - * - * @param int $contactListID - * @access public - * @return string - */ - public function ajaxGetContactUsers($contactListID) - { - $list = $this->user->getContactListByID($contactListID); - if($list) - { - $users = str_replace(',', ', ', $list->userList) . ', '; - echo $users; - } - die(); - } -} + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +class user extends control +{ + public $referer; + + /** + * Construct + * + * @access public + * @return void + */ + public function __construct() + { + parent::__construct(); + $this->loadModel('company')->setMenu(); + $this->loadModel('dept'); + $this->loadModel('todo'); + } + + /** + * View a user. + * + * @param string $account + * @access public + * @return void + */ + public function view($account) + { + $this->locate($this->createLink('user', 'todo', "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 + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function todo($account, $type = 'today', $status = 'all', $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* 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); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* set menus. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed|nodeleted'), $account); + $this->view->userList = $this->user->setUserList($this->user->getPairs('noempty|noclosed'), $account); + + /* Get user, totos. */ + $user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $todos = $this->todo->getList($type, $account, $status, 0, $pager); + $date = (int)$type == 0 ? helper::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->date = $date; + $this->view->todos = $todos; + $this->view->user = $user; + $this->view->account = $account; + $this->view->type = $type; + $this->view->pager = $pager; + + $this->display(); + } + + /** + * Tasks of a user. + * + * @param string $account + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function task($account, $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save the session. */ + $this->session->set('taskList', $this->app->getURI(true)); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* Set the menu. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + $this->view->userList = $this->user->setUserList($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, 'assignedto', 0, $pager); + $this->view->account = $account; + $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $this->view->pager = $pager; + + $this->display(); + } + + /** + * User bugs. + * + * @param string $account + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID + * @access public + * @return void + */ + public function bug($account, $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + /* Save the session. */ + $this->session->set('bugList', $this->app->getURI(true)); + + /* Load pager. */ + $this->app->loadClass('pager', $static = true); + $pager = pager::init($recTotal, $recPerPage, $pageID); + + /* Set menu. */ + $this->lang->set('menugroup.user', 'company'); + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + $this->view->userList = $this->user->setUserList($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, $pager); + $this->view->account = $account; + $this->view->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $this->view->users = $this->user->getPairs('noletter'); + $this->view->pager = $pager; + + $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); + $this->view->userList = $this->user->setUserList($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->account = $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) + { + $position[] = $this->lang->user->profile; + + /* Set menu. */ + $this->user->setMenu($this->user->getPairs('noempty|noclosed'), $account); + $this->view->userList = $this->user->setUserList($this->user->getPairs('noempty|noclosed'), $account); + + $user = $this->user->getById($account); + $deptPath = $this->dept->getParents($user->dept); + + $header['title'] = "USER #$user->id $user->account/" . $this->lang->user->profile; + $this->view->header = $header; + $this->view->position = $position; + $this->view->account = $account; + $this->view->user = $user; + + $this->view->deptPath = $deptPath; + + $this->display(); + } + + /** + * Set the rerferer. + * + * @param string $referer + * @access public + * @return void + */ + public 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; + $this->lang->user->menuOrder = $this->lang->company->menuOrder; + + if(!empty($_POST)) + { + $this->user->create(); + if(dao::isError()) die(js::error(dao::getError())); + die(js::locate($this->createLink('company', 'browse'), 'parent')); + } + $groups = $this->dao->select('id, name, role')->from(TABLE_GROUP)->fetchAll(); + $groupList = array('' => ''); + $roleGroup = array(); + foreach($groups as $group) + { + $groupList[$group->id] = $group->name; + if($group->role) $roleGroup[$group->role] = $group->id; + } + + $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->groupList = $groupList; + $this->view->roleGroup = $roleGroup; + $this->view->deptID = $deptID; + + $this->display(); + } + + + /** + * Batch create users. + * + * @param int $deptID + * @access public + * @return void + */ + public function batchCreate($deptID = 0) + { + $groups = $this->dao->select('id, name, role')->from(TABLE_GROUP)->fetchAll(); + $groupList = array('' => ''); + $roleGroup = array(); + foreach($groups as $group) + { + $groupList[$group->id] = $group->name; + if($group->role) $roleGroup[$group->role] = $group->id; + } + + $this->lang->set('menugroup.user', 'company'); + $this->lang->user->menu = $this->lang->company->menu; + $this->lang->user->menuOrder = $this->lang->company->menuOrder; + + if(!empty($_POST)) + { + $this->user->batchCreate(); + die(js::locate($this->createLink('company', 'browse'), 'parent')); + } + + $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->batchCreate; + $position[] = $this->lang->user->batchCreate; + $this->view->header = $header; + $this->view->position = $position; + $this->view->depts = $this->dept->getOptionMenu(); + $this->view->deptID = $deptID; + $this->view->groupList = $groupList; + $this->view->roleGroup = $roleGroup; + + $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; + $this->lang->user->menuOrder = $this->lang->company->menuOrder; + 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(); + } + + /** + * Batch edit user. + * + * @param int $deptID + * @access public + * @return void + */ + public function batchEdit($deptID = 0) + { + if(isset($_POST['users'])) + { + $this->view->users = $this->dao->select('*')->from(TABLE_USER)->where('account')->in($this->post->users)->orderBy('id')->fetchAll('id'); + } + elseif($_POST) + { + $this->user->batchEdit(); + die(js::locate($this->createLink('company', 'browse', "deptID=$deptID"), 'parent')); + } + $this->lang->set('menugroup.user', 'company'); + $this->lang->user->menu = $this->lang->company->menu; + $this->lang->user->menuOrder = $this->lang->company->menuOrder; + + $header['title'] = $this->lang->company->common . $this->lang->colon . $this->lang->user->batchEdit; + $position[] = $this->lang->user->edit; + $this->view->header = $header; + $this->view->position = $position; + $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')); + } + } + + /** + * Unlock a user. + * + * @param int $account + * @param string $confirm + * @access public + * @return void + */ + public function unlock($account, $confirm = 'no') + { + if($confirm == 'no') + { + die(js::confirm($this->lang->user->confirmUnlock, $this->createLink('user', 'unlock', "account=$account&confirm=yes"))); + } + else + { + $this->user->cleanLocked($account); + 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; + + if($this->user->checkLocked($account)) die(js::error(sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes))); + + $user = $this->user->identify($account, $password); + + if($user) + { + $this->user->cleanLocked($account); + /* Authorize him and save to session. */ + $user->rights = $this->user->authorize($account); + $user->groups = $this->user->getGroups($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'))); + $fails = $this->user->failPlus($account); + $remainTimes = $this->config->user->failTimes - $fails; + if($remainTimes <= 0) + { + die(js::error(sprintf($this->lang->user->loginLocked, $this->config->user->lockMinutes))); + } + else if($remainTimes <= 3) + { + die(js::error(sprintf($this->lang->user->lockWarning, $remainTimes))); + } + die(js::error($this->lang->user->loginFailed)); + } + } + else + { + if(!empty($this->config->global->showDemoUsers)) + { + $demoUsers = $this->user->getPairs('nodeleted, noletter, noempty, noclosed'); + $this->view->demoUsers = $demoUsers; + } + + $header['title'] = $this->lang->user->login; + $this->view->header = $header; + $this->view->referer = $this->referer; + $this->view->s = $this->config->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) + { + if(isset($this->app->user->id)) $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); + $this->view->userList = $this->user->setUserList($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->user = $this->dao->findByAccount($account)->from(TABLE_USER)->fetch(); + $this->view->actions = $this->loadModel('action')->getDynamic($account, $period, $orderBy, $pager); + $this->display(); + } + + /** + * Manage contacts. + * + * @param int $listID + * @access public + * @return void + */ + public function manageContacts($listID = 0) + { + $lists = $this->user->getContactLists($this->app->user->account); + + /* If set $mode, need to update database. */ + if($this->post->mode) + { + /* The mode is new: append or new a list. */ + if($this->post->mode == 'new') + { + if($this->post->list2Append) + { + $this->user->append2ContactList($this->post->list2Append, $this->post->users); + die(js::locate(inlink('manageContacts', "listID={$this->post->list2Append}"), 'parent')); + } + elseif($this->post->newList) + { + $listID = $this->user->createContactList($this->post->newList, $this->post->users); + die(js::locate(inlink('manageContacts', "listID=$listID"), 'parent')); + } + } + elseif($this->post->mode == 'edit') + { + $this->user->updateContactList($this->post->listID, $this->post->listName, $this->post->users); + die(js::locate(inlink('manageContacts', "listID={$this->post->listID}"), 'parent')); + } + } + if($this->post->users) + { + $mode = 'new'; + $users = $this->user->getContactUserPairs($this->post->users); + } + else + { + $mode = 'edit'; + $listID= $listID ? $listID : key($lists); + if(!$listID) die(js::alert($this->lang->user->contacts->noListYet) . js::locate($this->createLink('company', 'browse'), 'parent')); + + $list = $this->user->getContactListByID($listID); + $users = explode(',', $list->userList); + $users = $this->user->getContactUserPairs($users); + $this->view->list = $list; + } + + $this->view->lists = $this->user->getContactLists($this->app->user->account); + $this->view->users = $users; + $this->view->mode = $mode; + $this->display(); + } + + /** + * Delete a contact list. + * + * @param int $listID + * @param string $confirm + * @access public + * @return void + */ + public function deleteContacts($listID, $confirm = 'no') + { + if($confirm == 'no') + { + echo js::confirm($this->lang->user->contacts->confirmDelete, inlink('deleteContacts', "listID=$listID&confirm=yes")); + exit; + } + else + { + $this->user->deleteContactList($listID); + echo js::locate(inlink('manageContacts'), 'parent'); + exit; + } + } + + /** + * 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; + } + + /** + * AJAX: get users from a contact list. + * + * @param int $contactListID + * @access public + * @return string + */ + public function ajaxGetContactUsers($contactListID) + { + $list = $this->user->getContactListByID($contactListID); + if($list) + { + $users = str_replace(',', ', ', $list->userList) . ', '; + echo $users; + } + die(); + } +} diff --git a/module/user/lang/en.php b/module/user/lang/en.php index 76ae44ca8d..8f2d2d1a8e 100644 --- a/module/user/lang/en.php +++ b/module/user/lang/en.php @@ -1,135 +1,135 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->user->common = 'User'; -$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->role = 'Role'; -$lang->user->group = 'Group'; -$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'; -$lang->user->ditto = 'Ditto'; - -$lang->user->index = "Index"; -$lang->user->view = "Info"; -$lang->user->create = "Add"; -$lang->user->batchCreate = "Batch add user"; -$lang->user->read = "Info"; -$lang->user->edit = "Edit"; -$lang->user->batchEdit = "Batch Edit"; -$lang->user->unlock = "Unlock"; -$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->manageContacts = 'Manage contacts'; -$lang->user->deleteContacts = 'Delete contacts'; -$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->confirmUnlock = "Are you sure to unlock 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->lockWarning = "You only have %s times to try."; -$lang->user->loginLocked = "You try the password too many times, please contact the administrator or try again after %s minutes."; - -$lang->user->roleList[''] = ''; -$lang->user->roleList['dev'] = 'Developer'; -$lang->user->roleList['qa'] = 'Tester'; -$lang->user->roleList['pm'] = 'Project manager'; -$lang->user->roleList['po'] = 'Product owner'; -$lang->user->roleList['td'] = 'Technical director'; -$lang->user->roleList['pd'] = 'Product director'; -$lang->user->roleList['qd'] = 'Quality Director'; -$lang->user->roleList['top'] = 'Top manager'; -$lang->user->roleList['others'] = 'Others'; - -$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->loginWithDemoUser = 'Login with demo user:'; - -$lang->user->placeholder = new stdclass(); -$lang->user->placeholder->account = 'Letters/underline/numbers, three above'; -$lang->user->placeholder->password1 = 'Six above'; -$lang->user->placeholder->join = 'The date the employee joined the company'; -$lang->user->placeholder->commiter = 'The account in version control systems'; - -$lang->user->error = new stdclass(); -$lang->user->error->account = "ID %s,account must be three letters at least"; -$lang->user->error->accountDupl = "ID %s,this account has been exist"; -$lang->user->error->realname = "ID %s,please input realname"; -$lang->user->error->password = "ID %s,password must be six letters at least"; -$lang->user->error->mail = "ID %s,please input correct email address"; -$lang->user->error->role = "ID %s,please input role"; - -$lang->user->contacts = new stdclass(); -$lang->user->contacts->common = 'Contacts'; -$lang->user->contacts->listName = 'List name'; -$lang->user->contacts->userList = 'User list'; - -$lang->user->contacts->manage = 'Manage List'; -$lang->user->contacts->contactsList = 'List'; -$lang->user->contacts->selectedUsers= 'Users'; -$lang->user->contacts->selectList = 'List'; -$lang->user->contacts->appendToList = 'Append to a list'; -$lang->user->contacts->createList = 'Createa a list'; -$lang->user->contacts->noListYet = 'No contacts list yet.'; -$lang->user->contacts->confirmDelete= 'Are you sure to delete this list?'; -$lang->user->contacts->or = ' or '; + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->user->common = 'User'; +$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->role = 'Role'; +$lang->user->group = 'Group'; +$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'; +$lang->user->ditto = 'Ditto'; + +$lang->user->index = "Index"; +$lang->user->view = "Info"; +$lang->user->create = "Add"; +$lang->user->batchCreate = "Batch add user"; +$lang->user->read = "Info"; +$lang->user->edit = "Edit"; +$lang->user->batchEdit = "Batch Edit"; +$lang->user->unlock = "Unlock"; +$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->manageContacts = 'Manage contacts'; +$lang->user->deleteContacts = 'Delete contacts'; +$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->confirmUnlock = "Are you sure to unlock 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->lockWarning = "You only have %s times to try."; +$lang->user->loginLocked = "You try the password too many times, please contact the administrator or try again after %s minutes."; + +$lang->user->roleList[''] = ''; +$lang->user->roleList['dev'] = 'Developer'; +$lang->user->roleList['qa'] = 'Tester'; +$lang->user->roleList['pm'] = 'Project manager'; +$lang->user->roleList['po'] = 'Product owner'; +$lang->user->roleList['td'] = 'Technical director'; +$lang->user->roleList['pd'] = 'Product director'; +$lang->user->roleList['qd'] = 'Quality Director'; +$lang->user->roleList['top'] = 'Top manager'; +$lang->user->roleList['others'] = 'Others'; + +$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->loginWithDemoUser = 'Login with demo user:'; + +$lang->user->placeholder = new stdclass(); +$lang->user->placeholder->account = 'Letters/underline/numbers, three above'; +$lang->user->placeholder->password1 = 'Six above'; +$lang->user->placeholder->join = 'The date the employee joined the company'; +$lang->user->placeholder->commiter = 'The account in version control systems'; + +$lang->user->error = new stdclass(); +$lang->user->error->account = "ID %s,account must be three letters at least"; +$lang->user->error->accountDupl = "ID %s,this account has been exist"; +$lang->user->error->realname = "ID %s,please input realname"; +$lang->user->error->password = "ID %s,password must be six letters at least"; +$lang->user->error->mail = "ID %s,please input correct email address"; +$lang->user->error->role = "ID %s,please input role"; + +$lang->user->contacts = new stdclass(); +$lang->user->contacts->common = 'Contacts'; +$lang->user->contacts->listName = 'List name'; +$lang->user->contacts->userList = 'User list'; + +$lang->user->contacts->manage = 'Manage List'; +$lang->user->contacts->contactsList = 'List'; +$lang->user->contacts->selectedUsers= 'Users'; +$lang->user->contacts->selectList = 'List'; +$lang->user->contacts->appendToList = 'Append to a list'; +$lang->user->contacts->createList = 'Createa a list'; +$lang->user->contacts->noListYet = 'No contacts list yet.'; +$lang->user->contacts->confirmDelete= 'Are you sure to delete this list?'; +$lang->user->contacts->or = ' or '; diff --git a/module/user/lang/zh-cn.php b/module/user/lang/zh-cn.php index b152d3724b..c3cee076f3 100644 --- a/module/user/lang/zh-cn.php +++ b/module/user/lang/zh-cn.php @@ -1,135 +1,135 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->user->common = '用户'; -$lang->user->id = '用户编号'; -$lang->user->company = '所属公司'; -$lang->user->dept = '所属部门'; -$lang->user->account = '用户名'; -$lang->user->password = '密码'; -$lang->user->password2 = '请重复密码'; -$lang->user->role = '角色'; -$lang->user->group = '分组'; -$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 = '状态'; -$lang->user->ditto = '同上'; - -$lang->user->index = "用户视图首页"; -$lang->user->view = "用户详情"; -$lang->user->create = "添加用户"; -$lang->user->batchCreate = "批量添加用户"; -$lang->user->read = "查看用户"; -$lang->user->edit = "编辑用户"; -$lang->user->batchEdit = "批量编辑"; -$lang->user->unlock = "解锁用户"; -$lang->user->update = "编辑用户"; -$lang->user->delete = "删除用户"; -$lang->user->browse = "浏览用户"; -$lang->user->login = "用户登录"; -$lang->user->userView = "人员视图"; -$lang->user->editProfile = "修改个人信息"; -$lang->user->editPassword = "修改密码"; -$lang->user->manageContacts = '维护联系人'; -$lang->user->deleteContacts = '删除联系人'; -$lang->user->deny = "访问受限"; -$lang->user->confirmDelete = "您确定删除该用户吗?"; -$lang->user->confirmActivate = "您确定激活该用户吗?"; -$lang->user->confirmUnlock = "您确定解除该用户的锁定状态吗?"; -$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 = '缺陷'; -$lang->user->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->lockWarning = "您还有%s次尝试机会。"; -$lang->user->loginLocked = "密码尝试次数太多,请联系管理员解锁,或%s分钟后重试。"; - -$lang->user->roleList[''] = ''; -$lang->user->roleList['dev'] = '研发'; -$lang->user->roleList['qa'] = '测试'; -$lang->user->roleList['pm'] = '项目经理'; -$lang->user->roleList['po'] = '产品经理'; -$lang->user->roleList['td'] = '研发主管'; -$lang->user->roleList['pd'] = '产品主管'; -$lang->user->roleList['qd'] = '测试主管'; -$lang->user->roleList['top'] = '高层管理'; -$lang->user->roleList['others'] = '其他'; - -$lang->user->genderList['m'] = '男'; -$lang->user->genderList['f'] = '女'; - -$lang->user->statusList['active'] = '正常'; -$lang->user->statusList['delete'] = '删除'; - -$lang->user->keepLogin['on'] = '保持登录'; -$lang->user->loginWithDemoUser = '使用demo账号登录:'; - -$lang->user->placeholder = new stdclass(); -$lang->user->placeholder->account = '英文、数字和下划线的组合,三位以上'; -$lang->user->placeholder->password1 = '六位以上'; -$lang->user->placeholder->join = '入职日期'; -$lang->user->placeholder->commiter = '版本控制系统(subversion)中的帐号'; - -$lang->user->error = new stdclass(); -$lang->user->error->account = "ID %s,用户名必须三位以上"; -$lang->user->error->accountDupl = "ID %s,该用户名已经存在"; -$lang->user->error->realname = "ID %s,必须填写真实姓名"; -$lang->user->error->password = "ID %s,密码必须六位以上"; -$lang->user->error->mail = "ID %s,请填写正确的邮箱地址"; -$lang->user->error->role = "ID %s,角色不能为空"; - -$lang->user->contacts = new stdclass(); -$lang->user->contacts->common = '联系人'; -$lang->user->contacts->listName = '列表名称'; -$lang->user->contacts->userList = '联系人列表'; - -$lang->user->contacts->manage = '维护列表'; -$lang->user->contacts->contactsList = '已有列表'; -$lang->user->contacts->selectedUsers= '选择用户'; -$lang->user->contacts->selectList = '选择列表'; -$lang->user->contacts->appendToList = '追加至已有列表:'; -$lang->user->contacts->createList = '创建新列表:'; -$lang->user->contacts->noListYet = '还没有创建任何列表。'; -$lang->user->contacts->confirmDelete= '您确定要删除这个列表吗?'; -$lang->user->contacts->or = ' 或者 '; + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->user->common = '用户'; +$lang->user->id = '用户编号'; +$lang->user->company = '所属公司'; +$lang->user->dept = '所属部门'; +$lang->user->account = '用户名'; +$lang->user->password = '密码'; +$lang->user->password2 = '请重复密码'; +$lang->user->role = '角色'; +$lang->user->group = '分组'; +$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 = '状态'; +$lang->user->ditto = '同上'; + +$lang->user->index = "用户视图首页"; +$lang->user->view = "用户详情"; +$lang->user->create = "添加用户"; +$lang->user->batchCreate = "批量添加用户"; +$lang->user->read = "查看用户"; +$lang->user->edit = "编辑用户"; +$lang->user->batchEdit = "批量编辑"; +$lang->user->unlock = "解锁用户"; +$lang->user->update = "编辑用户"; +$lang->user->delete = "删除用户"; +$lang->user->browse = "浏览用户"; +$lang->user->login = "用户登录"; +$lang->user->userView = "人员视图"; +$lang->user->editProfile = "修改个人信息"; +$lang->user->editPassword = "修改密码"; +$lang->user->manageContacts = '维护联系人'; +$lang->user->deleteContacts = '删除联系人'; +$lang->user->deny = "访问受限"; +$lang->user->confirmDelete = "您确定删除该用户吗?"; +$lang->user->confirmActivate = "您确定激活该用户吗?"; +$lang->user->confirmUnlock = "您确定解除该用户的锁定状态吗?"; +$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 = '缺陷'; +$lang->user->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->lockWarning = "您还有%s次尝试机会。"; +$lang->user->loginLocked = "密码尝试次数太多,请联系管理员解锁,或%s分钟后重试。"; + +$lang->user->roleList[''] = ''; +$lang->user->roleList['dev'] = '研发'; +$lang->user->roleList['qa'] = '测试'; +$lang->user->roleList['pm'] = '项目经理'; +$lang->user->roleList['po'] = '产品经理'; +$lang->user->roleList['td'] = '研发主管'; +$lang->user->roleList['pd'] = '产品主管'; +$lang->user->roleList['qd'] = '测试主管'; +$lang->user->roleList['top'] = '高层管理'; +$lang->user->roleList['others'] = '其他'; + +$lang->user->genderList['m'] = '男'; +$lang->user->genderList['f'] = '女'; + +$lang->user->statusList['active'] = '正常'; +$lang->user->statusList['delete'] = '删除'; + +$lang->user->keepLogin['on'] = '保持登录'; +$lang->user->loginWithDemoUser = '使用demo账号登录:'; + +$lang->user->placeholder = new stdclass(); +$lang->user->placeholder->account = '英文、数字和下划线的组合,三位以上'; +$lang->user->placeholder->password1 = '六位以上'; +$lang->user->placeholder->join = '入职日期'; +$lang->user->placeholder->commiter = '版本控制系统(subversion)中的帐号'; + +$lang->user->error = new stdclass(); +$lang->user->error->account = "ID %s,用户名必须三位以上"; +$lang->user->error->accountDupl = "ID %s,该用户名已经存在"; +$lang->user->error->realname = "ID %s,必须填写真实姓名"; +$lang->user->error->password = "ID %s,密码必须六位以上"; +$lang->user->error->mail = "ID %s,请填写正确的邮箱地址"; +$lang->user->error->role = "ID %s,角色不能为空"; + +$lang->user->contacts = new stdclass(); +$lang->user->contacts->common = '联系人'; +$lang->user->contacts->listName = '列表名称'; +$lang->user->contacts->userList = '联系人列表'; + +$lang->user->contacts->manage = '维护列表'; +$lang->user->contacts->contactsList = '已有列表'; +$lang->user->contacts->selectedUsers= '选择用户'; +$lang->user->contacts->selectList = '选择列表'; +$lang->user->contacts->appendToList = '追加至已有列表:'; +$lang->user->contacts->createList = '创建新列表:'; +$lang->user->contacts->noListYet = '还没有创建任何列表。'; +$lang->user->contacts->confirmDelete= '您确定要删除这个列表吗?'; +$lang->user->contacts->or = ' 或者 '; diff --git a/module/user/lang/zh-tw.php b/module/user/lang/zh-tw.php index 6f1271a666..ac11b9d5f4 100644 --- a/module/user/lang/zh-tw.php +++ b/module/user/lang/zh-tw.php @@ -1,134 +1,134 @@ - - * @package user - * @version $Id: zh-tw.php 3889 2012-12-24 10:17:18Z wwccss $ - * @link http://www.zentao.net - */ -$lang->user->common = '用戶'; -$lang->user->id = '用戶編號'; -$lang->user->company = '所屬公司'; -$lang->user->dept = '所屬部門'; -$lang->user->account = '用戶名'; -$lang->user->password = '密碼'; -$lang->user->password2 = '請重複密碼'; -$lang->user->role = '角色'; -$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 = '狀態'; -$lang->user->ditto = '同上'; - -$lang->user->index = "用戶視圖首頁"; -$lang->user->view = "用戶詳情"; -$lang->user->create = "添加用戶"; -$lang->user->batchCreate = "批量添加用戶"; -$lang->user->read = "查看用戶"; -$lang->user->edit = "編輯用戶"; -$lang->user->batchEdit = "批量編輯"; -$lang->user->unlock = "解鎖用戶"; -$lang->user->update = "編輯用戶"; -$lang->user->delete = "刪除用戶"; -$lang->user->browse = "瀏覽用戶"; -$lang->user->login = "用戶登錄"; -$lang->user->userView = "人員視圖"; -$lang->user->editProfile = "修改個人信息"; -$lang->user->editPassword = "修改密碼"; -$lang->user->manageContacts = '維護聯繫人'; -$lang->user->deleteContacts = '刪除聯繫人'; -$lang->user->deny = "訪問受限"; -$lang->user->confirmDelete = "您確定刪除該用戶嗎?"; -$lang->user->confirmActivate = "您確定激活該用戶嗎?"; -$lang->user->confirmUnlock = "您確定解除該用戶的鎖定狀態嗎?"; -$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 = '缺陷'; -$lang->user->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->lockWarning = "您還有%s次嘗試機會。"; -$lang->user->loginLocked = "密碼嘗試次數太多,請聯繫管理員解鎖,或%s分鐘後重試。"; - -$lang->user->roleList[''] = ''; -$lang->user->roleList['dev'] = '研發'; -$lang->user->roleList['qa'] = '測試'; -$lang->user->roleList['pm'] = '項目經理'; -$lang->user->roleList['po'] = '產品經理'; -$lang->user->roleList['td'] = '研發主管'; -$lang->user->roleList['pd'] = '產品主管'; -$lang->user->roleList['qd'] = '測試主管'; -$lang->user->roleList['top'] = '高層管理'; -$lang->user->roleList['others'] = '其他'; - -$lang->user->genderList['m'] = '男'; -$lang->user->genderList['f'] = '女'; - -$lang->user->statusList['active'] = '正常'; -$lang->user->statusList['delete'] = '刪除'; - -$lang->user->keepLogin['on'] = '保持登錄'; -$lang->user->loginWithDemoUser = '使用demo賬號登錄:'; - -$lang->user->placeholder = new stdclass(); -$lang->user->placeholder->account = '英文、數字和下劃線的組合,三位以上'; -$lang->user->placeholder->password1 = '六位以上'; -$lang->user->placeholder->join = '入職日期'; -$lang->user->placeholder->commiter = '版本控制系統(subversion)中的帳號'; - -$lang->user->error = new stdclass(); -$lang->user->error->account = "ID %s,用戶名必須三位以上"; -$lang->user->error->accountDupl = "ID %s,該用戶名已經存在"; -$lang->user->error->realname = "ID %s,必須填寫真實姓名"; -$lang->user->error->password = "ID %s,密碼必須六位以上"; -$lang->user->error->mail = "ID %s,請填寫正確的郵箱地址"; -$lang->user->error->role = "ID %s,角色不能為空"; - -$lang->user->contacts = new stdclass(); -$lang->user->contacts->common = '聯繫人'; -$lang->user->contacts->listName = '列表名稱'; -$lang->user->contacts->userList = '聯繫人列表'; - -$lang->user->contacts->manage = '維護列表'; -$lang->user->contacts->contactsList = '已有列表'; -$lang->user->contacts->selectedUsers= '選擇用戶'; -$lang->user->contacts->selectList = '選擇列表'; -$lang->user->contacts->appendToList = '追加至已有列表:'; -$lang->user->contacts->createList = '創建新列表:'; -$lang->user->contacts->noListYet = '還沒有創建任何列表。'; -$lang->user->contacts->confirmDelete= '您確定要刪除這個列表嗎?'; -$lang->user->contacts->or = ' 或者 '; + + * @package user + * @version $Id: zh-tw.php 3889 2012-12-24 10:17:18Z wwccss $ + * @link http://www.zentao.net + */ +$lang->user->common = '用戶'; +$lang->user->id = '用戶編號'; +$lang->user->company = '所屬公司'; +$lang->user->dept = '所屬部門'; +$lang->user->account = '用戶名'; +$lang->user->password = '密碼'; +$lang->user->password2 = '請重複密碼'; +$lang->user->role = '角色'; +$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 = '狀態'; +$lang->user->ditto = '同上'; + +$lang->user->index = "用戶視圖首頁"; +$lang->user->view = "用戶詳情"; +$lang->user->create = "添加用戶"; +$lang->user->batchCreate = "批量添加用戶"; +$lang->user->read = "查看用戶"; +$lang->user->edit = "編輯用戶"; +$lang->user->batchEdit = "批量編輯"; +$lang->user->unlock = "解鎖用戶"; +$lang->user->update = "編輯用戶"; +$lang->user->delete = "刪除用戶"; +$lang->user->browse = "瀏覽用戶"; +$lang->user->login = "用戶登錄"; +$lang->user->userView = "人員視圖"; +$lang->user->editProfile = "修改個人信息"; +$lang->user->editPassword = "修改密碼"; +$lang->user->manageContacts = '維護聯繫人'; +$lang->user->deleteContacts = '刪除聯繫人'; +$lang->user->deny = "訪問受限"; +$lang->user->confirmDelete = "您確定刪除該用戶嗎?"; +$lang->user->confirmActivate = "您確定激活該用戶嗎?"; +$lang->user->confirmUnlock = "您確定解除該用戶的鎖定狀態嗎?"; +$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 = '缺陷'; +$lang->user->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->lockWarning = "您還有%s次嘗試機會。"; +$lang->user->loginLocked = "密碼嘗試次數太多,請聯繫管理員解鎖,或%s分鐘後重試。"; + +$lang->user->roleList[''] = ''; +$lang->user->roleList['dev'] = '研發'; +$lang->user->roleList['qa'] = '測試'; +$lang->user->roleList['pm'] = '項目經理'; +$lang->user->roleList['po'] = '產品經理'; +$lang->user->roleList['td'] = '研發主管'; +$lang->user->roleList['pd'] = '產品主管'; +$lang->user->roleList['qd'] = '測試主管'; +$lang->user->roleList['top'] = '高層管理'; +$lang->user->roleList['others'] = '其他'; + +$lang->user->genderList['m'] = '男'; +$lang->user->genderList['f'] = '女'; + +$lang->user->statusList['active'] = '正常'; +$lang->user->statusList['delete'] = '刪除'; + +$lang->user->keepLogin['on'] = '保持登錄'; +$lang->user->loginWithDemoUser = '使用demo賬號登錄:'; + +$lang->user->placeholder = new stdclass(); +$lang->user->placeholder->account = '英文、數字和下劃線的組合,三位以上'; +$lang->user->placeholder->password1 = '六位以上'; +$lang->user->placeholder->join = '入職日期'; +$lang->user->placeholder->commiter = '版本控制系統(subversion)中的帳號'; + +$lang->user->error = new stdclass(); +$lang->user->error->account = "ID %s,用戶名必須三位以上"; +$lang->user->error->accountDupl = "ID %s,該用戶名已經存在"; +$lang->user->error->realname = "ID %s,必須填寫真實姓名"; +$lang->user->error->password = "ID %s,密碼必須六位以上"; +$lang->user->error->mail = "ID %s,請填寫正確的郵箱地址"; +$lang->user->error->role = "ID %s,角色不能為空"; + +$lang->user->contacts = new stdclass(); +$lang->user->contacts->common = '聯繫人'; +$lang->user->contacts->listName = '列表名稱'; +$lang->user->contacts->userList = '聯繫人列表'; + +$lang->user->contacts->manage = '維護列表'; +$lang->user->contacts->contactsList = '已有列表'; +$lang->user->contacts->selectedUsers= '選擇用戶'; +$lang->user->contacts->selectList = '選擇列表'; +$lang->user->contacts->appendToList = '追加至已有列表:'; +$lang->user->contacts->createList = '創建新列表:'; +$lang->user->contacts->noListYet = '還沒有創建任何列表。'; +$lang->user->contacts->confirmDelete= '您確定要刪除這個列表嗎?'; +$lang->user->contacts->or = ' 或者 '; diff --git a/module/user/model.php b/module/user/model.php index 4df999afbf..c8ac5f5ee6 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1,797 +1,797 @@ - - * @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); - } - } - - /** - * Set users list. - * - * @param array $users - * @param string $account - * @access public - * @return html - */ - public function setUserList($users, $account) - { - return html::select('account', $users, $account, "onchange=\"switchAccount(this.value, '{$this->app->getMethodName()}')\""); - } - - /** - * 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|pofirst|devfirst|qafirst|pmfirst, can be sets of theme - * @access public - * @return array - */ - public function getPairs($params = '') - { - /* Set the query fields and orderBy condition. - * - * If there's xxfirst in the params, use INSTR function to get the position of role fields in a order string, - * thus to make sure users of this role at first. - */ - $fields = 'account, realname'; - if(strpos($params, 'pofirst') !== false) $fields .= ", INSTR(',pd,po,', role) AS roleOrder"; - if(strpos($params, 'pdfirst') !== false) $fields .= ", INSTR(',po,pd,', role) AS roleOrder"; - if(strpos($params, 'qafirst') !== false) $fields .= ", INSTR(',qd,qa,', role) AS roleOrder"; - if(strpos($params, 'qdfirst') !== false) $fields .= ", INSTR(',qa,qd,', role) AS roleOrder"; - if(strpos($params, 'pmfirst') !== false) $fields .= ", INSTR(',td,pm,', role) AS roleOrder"; - if(strpos($params, 'devfirst')!== false) $fields .= ", INSTR(',td,pm,qd,qa,dev,', role) AS roleOrder"; - $orderBy = strpos($params, 'first') !== false ? 'roleOrder DESC, account' : 'account'; - - /* Get raw records. */ - $users = $this->dao->select($fields)->from(TABLE_USER) - ->beginIF(strpos($params, 'nodeleted') !== false)->where('deleted')->eq(0)->fi() - ->orderBy($orderBy) - ->fetchAll('account'); - - /* Cycle the user records to append the first letter of his account. */ - foreach($users as $account => $user) - { - $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; - if(strpos($params, 'noletter') !== false) $firstLetter = ''; - $users[$account] = $firstLetter . ($user->realname ? $user->realname : $account); - } - - /* Append empty, closed, and guest users. */ - 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; - } - 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 roles for some users. - * - * @param string $users - * @access public - * @return array - */ - public function getUserRoles($users) - { - $users = $this->dao->select('account, role')->from(TABLE_USER)->where('account')->in($users)->fetchPairs(); - if(!$users) return array(); - - foreach($users as $account => $role) $users[$account] = zget($this->lang->user->roleList, $role, $role); - 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; - } - - /** - * Get users by sql. - * - * @param int $query - * @param int $pager - * @access public - * @return void - */ - public function getByQuery($query, $pager = null, $orderBy = 'id') - { - return $this->dao->select('*')->from(TABLE_USER) - ->where($query) - ->andWhere('deleted')->eq(0) - ->orderBy($orderBy) - ->page($pager) - ->fetchAll(); - } - - /** - * 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('group, 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(); - if($this->post->group) - { - $data = new stdClass(); - $data->account = $this->post->account; - $data->group = $this->post->group; - $this->dao->insert(TABLE_USERGROUP)->data($data)->exec(); - } - } - - /** - * Batch create users. - * - * @param int $users - * @access public - * @return void - */ - public function batchCreate() - { - $users = fixer::input('post')->get(); - $data = array(); - $accounts = array(); - for($i = 0; $i < $this->config->user->batchCreate; $i++) - { - if($users->account[$i] != '') - { - $account = $this->dao->select('account')->from(TABLE_USER)->where('account')->eq($users->account[$i])->fetch(); - if($account) die(js::error(sprintf($this->lang->user->error->accountDupl, $i+1))); - if(in_array($users->account[$i], $accounts)) die(js::error(sprintf($this->lang->user->error->accountDupl, $i+1))); - if(!validater::checkReg($users->account[$i], '|(.){3,}|')) die(js::error(sprintf($this->lang->user->error->account, $i+1))); - if($users->realname[$i] == '') die(js::error(sprintf($this->lang->user->error->realname, $i+1))); - if($users->email[$i] and !validater::checkEmail($users->email[$i])) die(js::error(sprintf($this->lang->user->error->mail, $i+1))); - $users->password[$i] = (isset($prev['password']) and $users->ditto[$i] == 'on' and empty($users->password[$i])) ? $prev['password'] : $users->password[$i]; - if(!validater::checkReg($users->password[$i], '|(.){6,}|')) die(js::error(sprintf($this->lang->user->error->password, $i+1))); - if(empty($users->role[$i])) die(js::error(sprintf($this->lang->user->error->role, $id))); - - $data[$i] = new stdclass(); - $data[$i]->dept = $users->dept[$i] == 'ditto' ? (isset($prev['dept']) ? $prev['dept'] : 0) : $users->dept[$i]; - $data[$i]->account = $users->account[$i]; - $data[$i]->realname = $users->realname[$i]; - $data[$i]->role = $users->role[$i] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : '') : $users->role[$i]; - $data[$i]->group = $users->group[$i] == 'ditto' ? (isset($prev['group']) ? $prev['group'] : '') : $users->group[$i]; - $data[$i]->email = $users->email[$i]; - $data[$i]->gender = $users->gender[$i]; - $data[$i]->password = md5($users->password[$i]); - - $accounts[$i] = $data[$i]->account; - $prev['dept'] = $data[$i]->dept; - $prev['role'] = $data[$i]->role; - $prev['group'] = $data[$i]->group; - $prev['password'] = $users->password[$i]; - } - } - - foreach($data as $user) - { - if($user->group) - { - $group = new stdClass(); - $group->account = $user->account; - $group->group = $user->group; - } - unset($user->group); - $this->dao->insert(TABLE_USERGROUP)->data($group)->exec(); - $this->dao->insert(TABLE_USER)->data($user)->autoCheck()->exec(); - if(dao::isError()) - { - echo js::error(dao::getError()); - die(js::reload('parent')); - } - } - } - - /** - * 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 = str_replace(',' . $oldUser->account . ',', ',' . $this->post->account . ',', $this->app->company->admins); - $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); - if(!dao::isError()) $this->app->user->account = $this->post->account; - } - } - } - - /** - * Batch edit user. - * - * @access public - * @return void - */ - public function batchEdit() - { - $oldUsers = $this->dao->select('id, account')->from(TABLE_USER)->where('id')->in(array_keys($this->post->account))->fetchPairs('id', 'account'); - $accountGroup = $this->dao->select('id, account')->from(TABLE_USER)->where('account')->in($this->post->account)->fetchGroup('account', 'id'); - - $accounts = array(); - foreach($this->post->account as $id => $account) - { - $users[$id]['account'] = $account; - $users[$id]['realname'] = $this->post->realname[$id]; - $users[$id]['commiter'] = $this->post->commiter[$id]; - $users[$id]['email'] = $this->post->email[$id]; - $users[$id]['join'] = $this->post->join[$id]; - $users[$id]['dept'] = $this->post->dept[$id] == 'ditto' ? (isset($prev['dept']) ? $prev['dept'] : 0) : $this->post->dept[$id]; - $users[$id]['role'] = $this->post->role[$id] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : 0) : $this->post->role[$id]; - - if(isset($accountGroup[$account]) and count($accountGroup[$account]) > 1) die(js::error(sprintf($this->lang->user->error->accountDupl, $id))); - if(in_array($account, $accounts)) die(js::error(sprintf($this->lang->user->error->accountDupl, $id))); - if(!validater::checkReg($users[$id]['account'], '|(.){3,}|')) die(js::error(sprintf($this->lang->user->error->account, $id))); - if($users[$id]['realname'] == '') die(js::error(sprintf($this->lang->user->error->realname, $id))); - if($users[$id]['email'] and !validater::checkEmail($users[$id]['email'])) die(js::error(sprintf($this->lang->user->error->mail, $id))); - if(empty($users[$id]['role'])) die(js::error(sprintf($this->lang->user->error->role, $id))); - - $accounts[$id] = $account; - $prev['dept'] = $users[$id]['dept']; - $prev['role'] = $users[$id]['role']; - } - - foreach($users as $id => $user) - { - $this->dao->update(TABLE_USER)->data($user)->where('id')->eq((int)$id)->exec(); - if($user['account'] != $oldUsers[$id]) - { - $oldAccount = $oldUsers[$id]; - $this->dao->update(TABLE_USERGROUP)->set('account')->eq($user['account'])->where('account')->eq($oldAccount)->exec(); - if(strpos($this->app->company->admins, ',' . $oldAccount . ',') !== false) - { - $admins = str_replace(',' . $oldAccount . ',', ',' . $user['account'] . ',', $this->app->company->admins); - $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); - } - if(!dao::isError() and $this->app->user->account == $oldAccount) $this->app->user->account = $users['account']; - } - } - } - - /** - * Update password - * - * @param string $userID - * @access public - * @return void - */ - public function updatePassword($userID) - { - if(!$this->checkPassword()) return; - - $user = fixer::input('post') - ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) - ->remove('account, password1, password2') - ->get(); - - $this->dao->update(TABLE_USER)->data($user)->autoCheck()->where('id')->eq((int)$userID)->exec(); - } - - /** - * 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. */ - $record = $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. */ - $user = false; - if($record) - { - $passwordLength = strlen($password); - if($passwordLength < 32) - { - $user = $record; - } - elseif($passwordLength == 32) - { - $hash = $this->session->rand ? md5($record->password . $this->session->rand) : $record->password; - $user = $password == $hash ? $record : ''; - } - elseif($passwordLength == 40) - { - $hash = sha1($record->account . $record->password . $record->last); - $user = $password == $hash ? $record : ''; - } - } - - 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); - $user->groups = $this->getGroups($account); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - $this->loadModel('action')->create('user', $user->id, 'login'); - $this->loadModel('common')->loadConfigFromDB(); - } - - /** - * 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); - $user->groups = $this->getGroups($account); - $this->session->set('user', $user); - $this->app->user = $this->session->user; - $this->loadModel('action')->create('user', $user->id, 'login'); - $this->loadModel('common')->loadConfigFromDB(); - - $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.role')->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 - * @param object $pager - * @access public - * @return array - */ - public function getBugs($account, $pager = null) - { - 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) - ->orderBy('id desc') - ->page($pager) - ->fetchAll(); - } - - /** - * Plus the fail times. - * - * @param int $account - * @access public - * @return void - */ - public function failPlus($account) - { - $user = $this->dao->select('fails')->from(TABLE_USER)->where('account')->eq($account)->fetch(); - $fails = $user->fails; - $fails ++; - if($fails < $this->config->user->failTimes) - { - $locked = '0000-00-00 00:00:00'; - $failTimes = $fails; - } - else - { - $locked = date('Y-m-d H:i:s', mktime()); - $failTimes = 0; - } - $this->dao->update(TABLE_USER)->set('fails')->eq($failTimes)->set('locked')->eq($locked)->where('account')->eq($account)->exec(false); - return $fails; - } - - /** - * Check whether the user is locked. - * - * @param int $account - * @access public - * @return void - */ - public function checkLocked($account) - { - $user = $this->dao->select('locked')->from(TABLE_USER)->where('account')->eq($account)->fetch(); - if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) > $this->config->user->lockMinutes * 60) return false; - return true; - } - - /** - * Unlock the locked user. - * - * @param int $account - * @access public - * @return void - */ - public function cleanLocked($account) - { - $this->dao->update(TABLE_USER)->set('fails')->eq(0)->set('locked')->eq('0000-00-00 00:00:00')->where('account')->eq($account)->exec(false); - } - - /** - * Get contact list of a user. - * - * @param string $account - * @param string $params withempty|withnote - * @access public - * @return object - */ - public function getContactLists($account, $params= '') - { - $contacts = $this->dao->select('id, listName')->from(TABLE_USERCONTACT)->where('account')->eq($account)->fetchPairs(); - if(!$contacts) return array(); - - if(strpos($params, 'withempty') !== false) $contacts = array('' => '') + $contacts; - if(strpos($params, 'withnote') !== false) $contacts = array('' => $this->lang->user->contacts->common) + $contacts; - - return $contacts; - } - - /** - * Get a contact list by id. - * - * @param int $listID - * @access public - * @return object - */ - public function getContactListByID($listID) - { - return $this->dao->select('*')->from(TABLE_USERCONTACT)->where('id')->eq($listID)->fetch(); - } - - /** - * Get user account and realname pairs from a contact list. - * - * @param string $accountList - * @access public - * @return array - */ - public function getContactUserPairs($accountList) - { - return $this->dao->select('account, realname')->from(TABLE_USER)->where('account')->in($accountList)->fetchPairs(); - } - - /** - * Create a contact list. - * - * @param string $listName - * @param string $userList - * @access public - * @return int - */ - public function createContactList($listName, $userList) - { - $data = new stdclass(); - $data->listName = $listName; - $data->userList = join(',', $userList); - $data->account = $this->app->user->account; - - $this->dao->insert(TABLE_USERCONTACT)->data($data)->exec(); - return $this->dao->lastInsertID(); - } - - /** - * Append some users to a contact list. - * - * @param int $listID - * @param string $userList - * @access public - * @return void - */ - public function append2ContactList($listID, $userList) - { - $list = $this->getContactListByID($listID); - if($list->userList) $userList = array_merge($userList, explode(',', $list->userList)); - - $userList = array_unique($userList); - sort($userList); - $userList = join(',', $userList); - - $this->dao->update(TABLE_USERCONTACT)->set('userList')->eq($userList)->where('id')->eq($listID)->exec(); - } - - /** - * Update a contact list. - * - * @param int $listID - * @param string $listName - * @param string $userList - * @access public - * @return void - */ - public function updateContactList($listID, $listName, $userList) - { - $data = new stdclass(); - $data->listName = $listName; - $data->userList = join(',', $userList); - - $this->dao->update(TABLE_USERCONTACT)->data($data)->where('id')->eq($listID)->exec(); - } - - /** - * Delete a contact list. - * - * @param int $listID - * @access public - * @return void - */ - public function deleteContactList($listID) - { - return $this->dao->delete()->from(TABLE_USERCONTACT)->where('id')->eq($listID)->exec(); - } -} + + * @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); + } + } + + /** + * Set users list. + * + * @param array $users + * @param string $account + * @access public + * @return html + */ + public function setUserList($users, $account) + { + return html::select('account', $users, $account, "onchange=\"switchAccount(this.value, '{$this->app->getMethodName()}')\""); + } + + /** + * 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|pofirst|devfirst|qafirst|pmfirst, can be sets of theme + * @access public + * @return array + */ + public function getPairs($params = '') + { + /* Set the query fields and orderBy condition. + * + * If there's xxfirst in the params, use INSTR function to get the position of role fields in a order string, + * thus to make sure users of this role at first. + */ + $fields = 'account, realname'; + if(strpos($params, 'pofirst') !== false) $fields .= ", INSTR(',pd,po,', role) AS roleOrder"; + if(strpos($params, 'pdfirst') !== false) $fields .= ", INSTR(',po,pd,', role) AS roleOrder"; + if(strpos($params, 'qafirst') !== false) $fields .= ", INSTR(',qd,qa,', role) AS roleOrder"; + if(strpos($params, 'qdfirst') !== false) $fields .= ", INSTR(',qa,qd,', role) AS roleOrder"; + if(strpos($params, 'pmfirst') !== false) $fields .= ", INSTR(',td,pm,', role) AS roleOrder"; + if(strpos($params, 'devfirst')!== false) $fields .= ", INSTR(',td,pm,qd,qa,dev,', role) AS roleOrder"; + $orderBy = strpos($params, 'first') !== false ? 'roleOrder DESC, account' : 'account'; + + /* Get raw records. */ + $users = $this->dao->select($fields)->from(TABLE_USER) + ->beginIF(strpos($params, 'nodeleted') !== false)->where('deleted')->eq(0)->fi() + ->orderBy($orderBy) + ->fetchAll('account'); + + /* Cycle the user records to append the first letter of his account. */ + foreach($users as $account => $user) + { + $firstLetter = ucfirst(substr($account, 0, 1)) . ':'; + if(strpos($params, 'noletter') !== false) $firstLetter = ''; + $users[$account] = $firstLetter . ($user->realname ? $user->realname : $account); + } + + /* Append empty, closed, and guest users. */ + 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; + } + 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 roles for some users. + * + * @param string $users + * @access public + * @return array + */ + public function getUserRoles($users) + { + $users = $this->dao->select('account, role')->from(TABLE_USER)->where('account')->in($users)->fetchPairs(); + if(!$users) return array(); + + foreach($users as $account => $role) $users[$account] = zget($this->lang->user->roleList, $role, $role); + 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; + } + + /** + * Get users by sql. + * + * @param int $query + * @param int $pager + * @access public + * @return void + */ + public function getByQuery($query, $pager = null, $orderBy = 'id') + { + return $this->dao->select('*')->from(TABLE_USER) + ->where($query) + ->andWhere('deleted')->eq(0) + ->orderBy($orderBy) + ->page($pager) + ->fetchAll(); + } + + /** + * 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('group, 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(); + if($this->post->group) + { + $data = new stdClass(); + $data->account = $this->post->account; + $data->group = $this->post->group; + $this->dao->insert(TABLE_USERGROUP)->data($data)->exec(); + } + } + + /** + * Batch create users. + * + * @param int $users + * @access public + * @return void + */ + public function batchCreate() + { + $users = fixer::input('post')->get(); + $data = array(); + $accounts = array(); + for($i = 0; $i < $this->config->user->batchCreate; $i++) + { + if($users->account[$i] != '') + { + $account = $this->dao->select('account')->from(TABLE_USER)->where('account')->eq($users->account[$i])->fetch(); + if($account) die(js::error(sprintf($this->lang->user->error->accountDupl, $i+1))); + if(in_array($users->account[$i], $accounts)) die(js::error(sprintf($this->lang->user->error->accountDupl, $i+1))); + if(!validater::checkReg($users->account[$i], '|(.){3,}|')) die(js::error(sprintf($this->lang->user->error->account, $i+1))); + if($users->realname[$i] == '') die(js::error(sprintf($this->lang->user->error->realname, $i+1))); + if($users->email[$i] and !validater::checkEmail($users->email[$i])) die(js::error(sprintf($this->lang->user->error->mail, $i+1))); + $users->password[$i] = (isset($prev['password']) and $users->ditto[$i] == 'on' and empty($users->password[$i])) ? $prev['password'] : $users->password[$i]; + if(!validater::checkReg($users->password[$i], '|(.){6,}|')) die(js::error(sprintf($this->lang->user->error->password, $i+1))); + if(empty($users->role[$i])) die(js::error(sprintf($this->lang->user->error->role, $id))); + + $data[$i] = new stdclass(); + $data[$i]->dept = $users->dept[$i] == 'ditto' ? (isset($prev['dept']) ? $prev['dept'] : 0) : $users->dept[$i]; + $data[$i]->account = $users->account[$i]; + $data[$i]->realname = $users->realname[$i]; + $data[$i]->role = $users->role[$i] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : '') : $users->role[$i]; + $data[$i]->group = $users->group[$i] == 'ditto' ? (isset($prev['group']) ? $prev['group'] : '') : $users->group[$i]; + $data[$i]->email = $users->email[$i]; + $data[$i]->gender = $users->gender[$i]; + $data[$i]->password = md5($users->password[$i]); + + $accounts[$i] = $data[$i]->account; + $prev['dept'] = $data[$i]->dept; + $prev['role'] = $data[$i]->role; + $prev['group'] = $data[$i]->group; + $prev['password'] = $users->password[$i]; + } + } + + foreach($data as $user) + { + if($user->group) + { + $group = new stdClass(); + $group->account = $user->account; + $group->group = $user->group; + } + unset($user->group); + $this->dao->insert(TABLE_USERGROUP)->data($group)->exec(); + $this->dao->insert(TABLE_USER)->data($user)->autoCheck()->exec(); + if(dao::isError()) + { + echo js::error(dao::getError()); + die(js::reload('parent')); + } + } + } + + /** + * 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 = str_replace(',' . $oldUser->account . ',', ',' . $this->post->account . ',', $this->app->company->admins); + $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); + if(!dao::isError()) $this->app->user->account = $this->post->account; + } + } + } + + /** + * Batch edit user. + * + * @access public + * @return void + */ + public function batchEdit() + { + $oldUsers = $this->dao->select('id, account')->from(TABLE_USER)->where('id')->in(array_keys($this->post->account))->fetchPairs('id', 'account'); + $accountGroup = $this->dao->select('id, account')->from(TABLE_USER)->where('account')->in($this->post->account)->fetchGroup('account', 'id'); + + $accounts = array(); + foreach($this->post->account as $id => $account) + { + $users[$id]['account'] = $account; + $users[$id]['realname'] = $this->post->realname[$id]; + $users[$id]['commiter'] = $this->post->commiter[$id]; + $users[$id]['email'] = $this->post->email[$id]; + $users[$id]['join'] = $this->post->join[$id]; + $users[$id]['dept'] = $this->post->dept[$id] == 'ditto' ? (isset($prev['dept']) ? $prev['dept'] : 0) : $this->post->dept[$id]; + $users[$id]['role'] = $this->post->role[$id] == 'ditto' ? (isset($prev['role']) ? $prev['role'] : 0) : $this->post->role[$id]; + + if(isset($accountGroup[$account]) and count($accountGroup[$account]) > 1) die(js::error(sprintf($this->lang->user->error->accountDupl, $id))); + if(in_array($account, $accounts)) die(js::error(sprintf($this->lang->user->error->accountDupl, $id))); + if(!validater::checkReg($users[$id]['account'], '|(.){3,}|')) die(js::error(sprintf($this->lang->user->error->account, $id))); + if($users[$id]['realname'] == '') die(js::error(sprintf($this->lang->user->error->realname, $id))); + if($users[$id]['email'] and !validater::checkEmail($users[$id]['email'])) die(js::error(sprintf($this->lang->user->error->mail, $id))); + if(empty($users[$id]['role'])) die(js::error(sprintf($this->lang->user->error->role, $id))); + + $accounts[$id] = $account; + $prev['dept'] = $users[$id]['dept']; + $prev['role'] = $users[$id]['role']; + } + + foreach($users as $id => $user) + { + $this->dao->update(TABLE_USER)->data($user)->where('id')->eq((int)$id)->exec(); + if($user['account'] != $oldUsers[$id]) + { + $oldAccount = $oldUsers[$id]; + $this->dao->update(TABLE_USERGROUP)->set('account')->eq($user['account'])->where('account')->eq($oldAccount)->exec(); + if(strpos($this->app->company->admins, ',' . $oldAccount . ',') !== false) + { + $admins = str_replace(',' . $oldAccount . ',', ',' . $user['account'] . ',', $this->app->company->admins); + $this->dao->update(TABLE_COMPANY)->set('admins')->eq($admins)->where('id')->eq($this->app->company->id)->exec(false); + } + if(!dao::isError() and $this->app->user->account == $oldAccount) $this->app->user->account = $users['account']; + } + } + } + + /** + * Update password + * + * @param string $userID + * @access public + * @return void + */ + public function updatePassword($userID) + { + if(!$this->checkPassword()) return; + + $user = fixer::input('post') + ->setIF($this->post->password1 != false, 'password', md5($this->post->password1)) + ->remove('account, password1, password2') + ->get(); + + $this->dao->update(TABLE_USER)->data($user)->autoCheck()->where('id')->eq((int)$userID)->exec(); + } + + /** + * 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. */ + $record = $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. */ + $user = false; + if($record) + { + $passwordLength = strlen($password); + if($passwordLength < 32) + { + $user = $record; + } + elseif($passwordLength == 32) + { + $hash = $this->session->rand ? md5($record->password . $this->session->rand) : $record->password; + $user = $password == $hash ? $record : ''; + } + elseif($passwordLength == 40) + { + $hash = sha1($record->account . $record->password . $record->last); + $user = $password == $hash ? $record : ''; + } + } + + 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); + $user->groups = $this->getGroups($account); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + $this->loadModel('action')->create('user', $user->id, 'login'); + $this->loadModel('common')->loadConfigFromDB(); + } + + /** + * 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); + $user->groups = $this->getGroups($account); + $this->session->set('user', $user); + $this->app->user = $this->session->user; + $this->loadModel('action')->create('user', $user->id, 'login'); + $this->loadModel('common')->loadConfigFromDB(); + + $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.role')->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 + * @param object $pager + * @access public + * @return array + */ + public function getBugs($account, $pager = null) + { + 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) + ->orderBy('id desc') + ->page($pager) + ->fetchAll(); + } + + /** + * Plus the fail times. + * + * @param int $account + * @access public + * @return void + */ + public function failPlus($account) + { + $user = $this->dao->select('fails')->from(TABLE_USER)->where('account')->eq($account)->fetch(); + $fails = $user->fails; + $fails ++; + if($fails < $this->config->user->failTimes) + { + $locked = '0000-00-00 00:00:00'; + $failTimes = $fails; + } + else + { + $locked = date('Y-m-d H:i:s', mktime()); + $failTimes = 0; + } + $this->dao->update(TABLE_USER)->set('fails')->eq($failTimes)->set('locked')->eq($locked)->where('account')->eq($account)->exec(false); + return $fails; + } + + /** + * Check whether the user is locked. + * + * @param int $account + * @access public + * @return void + */ + public function checkLocked($account) + { + $user = $this->dao->select('locked')->from(TABLE_USER)->where('account')->eq($account)->fetch(); + if((strtotime(date('Y-m-d H:i:s')) - strtotime($user->locked)) > $this->config->user->lockMinutes * 60) return false; + return true; + } + + /** + * Unlock the locked user. + * + * @param int $account + * @access public + * @return void + */ + public function cleanLocked($account) + { + $this->dao->update(TABLE_USER)->set('fails')->eq(0)->set('locked')->eq('0000-00-00 00:00:00')->where('account')->eq($account)->exec(false); + } + + /** + * Get contact list of a user. + * + * @param string $account + * @param string $params withempty|withnote + * @access public + * @return object + */ + public function getContactLists($account, $params= '') + { + $contacts = $this->dao->select('id, listName')->from(TABLE_USERCONTACT)->where('account')->eq($account)->fetchPairs(); + if(!$contacts) return array(); + + if(strpos($params, 'withempty') !== false) $contacts = array('' => '') + $contacts; + if(strpos($params, 'withnote') !== false) $contacts = array('' => $this->lang->user->contacts->common) + $contacts; + + return $contacts; + } + + /** + * Get a contact list by id. + * + * @param int $listID + * @access public + * @return object + */ + public function getContactListByID($listID) + { + return $this->dao->select('*')->from(TABLE_USERCONTACT)->where('id')->eq($listID)->fetch(); + } + + /** + * Get user account and realname pairs from a contact list. + * + * @param string $accountList + * @access public + * @return array + */ + public function getContactUserPairs($accountList) + { + return $this->dao->select('account, realname')->from(TABLE_USER)->where('account')->in($accountList)->fetchPairs(); + } + + /** + * Create a contact list. + * + * @param string $listName + * @param string $userList + * @access public + * @return int + */ + public function createContactList($listName, $userList) + { + $data = new stdclass(); + $data->listName = $listName; + $data->userList = join(',', $userList); + $data->account = $this->app->user->account; + + $this->dao->insert(TABLE_USERCONTACT)->data($data)->exec(); + return $this->dao->lastInsertID(); + } + + /** + * Append some users to a contact list. + * + * @param int $listID + * @param string $userList + * @access public + * @return void + */ + public function append2ContactList($listID, $userList) + { + $list = $this->getContactListByID($listID); + if($list->userList) $userList = array_merge($userList, explode(',', $list->userList)); + + $userList = array_unique($userList); + sort($userList); + $userList = join(',', $userList); + + $this->dao->update(TABLE_USERCONTACT)->set('userList')->eq($userList)->where('id')->eq($listID)->exec(); + } + + /** + * Update a contact list. + * + * @param int $listID + * @param string $listName + * @param string $userList + * @access public + * @return void + */ + public function updateContactList($listID, $listName, $userList) + { + $data = new stdclass(); + $data->listName = $listName; + $data->userList = join(',', $userList); + + $this->dao->update(TABLE_USERCONTACT)->data($data)->where('id')->eq($listID)->exec(); + } + + /** + * Delete a contact list. + * + * @param int $listID + * @access public + * @return void + */ + public function deleteContactList($listID) + { + return $this->dao->delete()->from(TABLE_USERCONTACT)->where('id')->eq($listID)->exec(); + } +} diff --git a/module/user/view/batchcreate.html.php b/module/user/view/batchcreate.html.php index bb3347836b..689a55f0b8 100644 --- a/module/user/view/batchcreate.html.php +++ b/module/user/view/batchcreate.html.php @@ -1,54 +1,54 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
              - - - - - - - - - - - - - - $lang->user->ditto)?> - user->roleList = $lang->user->roleList + array('ditto' => $lang->user->ditto)?> - $lang->user->ditto)?> - user->batchCreate; $i++):?> - - - - - - - - - - - - -
              user->batchCreate;?>
              idAB;?>user->dept;?>user->account;?>user->realname;?>user->role;?>user->group;?>user->email;?>user->gender;?>user->password;?>
              0 ? 'ditto' : $deptID, "class='select-1'");?> - user->roleList, $i > 0 ? 'ditto' : '', "class='select-1' onchange='changeGroup(this.value, $i)'");?> 0 ? 'ditto' : '', "class='select-1'");?>user->genderList, 'm');?> - 0 ? "checked" : '') . " /> {$lang->user->ditto}"; - ?> -
              -
              - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
              + + + + + + + + + + + + + + $lang->user->ditto)?> + user->roleList = $lang->user->roleList + array('ditto' => $lang->user->ditto)?> + $lang->user->ditto)?> + user->batchCreate; $i++):?> + + + + + + + + + + + + +
              user->batchCreate;?>
              idAB;?>user->dept;?>user->account;?>user->realname;?>user->role;?>user->group;?>user->email;?>user->gender;?>user->password;?>
              0 ? 'ditto' : $deptID, "class='select-1'");?> + user->roleList, $i > 0 ? 'ditto' : '', "class='select-1' onchange='changeGroup(this.value, $i)'");?> 0 ? 'ditto' : '', "class='select-1'");?>user->genderList, 'm');?> + 0 ? "checked" : '') . " /> {$lang->user->ditto}"; + ?> +
              +
              + diff --git a/module/user/view/batchedit.html.php b/module/user/view/batchedit.html.php index 40f6274228..91c7392333 100644 --- a/module/user/view/batchedit.html.php +++ b/module/user/view/batchedit.html.php @@ -1,46 +1,46 @@ - - * @package story - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - -
              - - - - - - - - - - - - - $lang->user->ditto)?> - user->roleList = $lang->user->roleList + array('ditto' => $lang->user->ditto)?> - - - - - - - - - - - -
              user->batchEdit;?>
              idAB;?>user->dept;?>user->account;?>user->realname;?>user->role;?>user->commiter;?>user->email;?>user->join;?>
              id;?>id]", $depts, empty($user->dept) ? 'ditto' : $user->dept, "class='select-1'");?> - id]", $user->account, "class='text-1' autocomplete='off'");?>id]", $user->realname, "class='text-1'");?>id]", $lang->user->roleList, empty($user->role) ? 'ditto' : $user->role, "class='select-1'");?> - id]", $user->commiter, "class='text-1'");?>id]", $user->email, "class='text-1'");?>id]", $user->join, "class='w-p70 date'");?>
              -
              - + + * @package story + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + +
              + + + + + + + + + + + + + $lang->user->ditto)?> + user->roleList = $lang->user->roleList + array('ditto' => $lang->user->ditto)?> + + + + + + + + + + + +
              user->batchEdit;?>
              idAB;?>user->dept;?>user->account;?>user->realname;?>user->role;?>user->commiter;?>user->email;?>user->join;?>
              id;?>id]", $depts, empty($user->dept) ? 'ditto' : $user->dept, "class='select-1'");?> + id]", $user->account, "class='text-1' autocomplete='off'");?>id]", $user->realname, "class='text-1'");?>id]", $lang->user->roleList, empty($user->role) ? 'ditto' : $user->role, "class='select-1'");?> + id]", $user->commiter, "class='text-1'");?>id]", $user->email, "class='text-1'");?>id]", $user->join, "class='w-p70 date'");?>
              +
              + diff --git a/module/user/view/bug.html.php b/module/user/view/bug.html.php index 02cf648045..e802628313 100644 --- a/module/user/view/bug.html.php +++ b/module/user/view/bug.html.php @@ -1,45 +1,45 @@ - - * @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->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>
              show();?>
              - + + * @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->priList[$bug->pri]?>bug->typeList[$bug->type]?>createLink('bug', 'view', "bugID=$bug->id"), $bug->title);?>openedBy];?>resolvedBy];?>bug->resolutionList[$bug->resolution];?>
              show();?>
              + diff --git a/module/user/view/create.html.php b/module/user/view/create.html.php index 56ba64b134..f27265304b 100644 --- a/module/user/view/create.html.php +++ b/module/user/view/create.html.php @@ -1,68 +1,68 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -user->placeholder, 'json');?> - -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              user->create;?>
              user->dept;?> -
              user->account;?>
              user->realname;?>
              user->password;?>
              user->password2;?>
              user->role;?>user->roleList, '', "class='select-3' onchange='changeGroup(this.value)'");?>
              user->group;?>
              user->email;?>
              user->commiter;?>
              user->join;?>
              user->gender;?>user->genderList, 'm');?>
              -
              - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +user->placeholder, 'json');?> + +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              user->create;?>
              user->dept;?> +
              user->account;?>
              user->realname;?>
              user->password;?>
              user->password2;?>
              user->role;?>user->roleList, '', "class='select-3' onchange='changeGroup(this.value)'");?>
              user->group;?>
              user->email;?>
              user->commiter;?>
              user->join;?>
              user->gender;?>user->genderList, 'm');?>
              +
              + diff --git a/module/user/view/deny.html.php b/module/user/view/deny.html.php index 4cd87cd538..c79bbf1e96 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 fa1d25245e..9c6aa406b3 100644 --- a/module/user/view/dynamic.html.php +++ b/module/user/view/dynamic.html.php @@ -1,64 +1,64 @@ -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 - */ -?> - - - - - - - - - -
              -
              user->dynamic;?>
              -
              - action->dynamic->today) . '
              '; - echo html::a(inLink('dynamic', "period=yesterday&account=$account"), $lang->action->dynamic->yesterday) . '
              '; - echo html::a(inLink('dynamic', "period=twodaysago&account=$account"), $lang->action->dynamic->twoDaysAgo) . '
              '; - echo html::a(inLink('dynamic', "period=thisweek&account=$account"), $lang->action->dynamic->thisWeek) . '
              '; - echo html::a(inLink('dynamic', "period=lastweek&account=$account"), $lang->action->dynamic->lastWeek) . '
              '; - echo html::a(inLink('dynamic', "period=thismonth&account=$account"), $lang->action->dynamic->thisMonth) . '
              '; - echo html::a(inLink('dynamic', "period=lastmonth&account=$account"), $lang->action->dynamic->lastMonth) . '
              '; - echo html::a(inLink('dynamic', "period=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-2013 青岛易软天创网络科技有限公司 (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 + */ +?> + + + + + + + + + +
              +
              user->dynamic;?>
              +
              + action->dynamic->today) . '
              '; + echo html::a(inLink('dynamic', "period=yesterday&account=$account"), $lang->action->dynamic->yesterday) . '
              '; + echo html::a(inLink('dynamic', "period=twodaysago&account=$account"), $lang->action->dynamic->twoDaysAgo) . '
              '; + echo html::a(inLink('dynamic', "period=thisweek&account=$account"), $lang->action->dynamic->thisWeek) . '
              '; + echo html::a(inLink('dynamic', "period=lastweek&account=$account"), $lang->action->dynamic->lastWeek) . '
              '; + echo html::a(inLink('dynamic', "period=thismonth&account=$account"), $lang->action->dynamic->thisMonth) . '
              '; + echo html::a(inLink('dynamic', "period=lastmonth&account=$account"), $lang->action->dynamic->lastMonth) . '
              '; + echo html::a(inLink('dynamic', "period=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 011f1850d7..ef11817fe3 100644 --- a/module/user/view/edit.html.php +++ b/module/user/view/edit.html.php @@ -1,97 +1,97 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - -
              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              user->edit;?>
              user->dept;?>dept, "class='select-3'");?> -
              user->account;?>account, "class='text-3' autocomplete='off'");?>
              user->realname;?>realname, "class='text-3'");?>
              user->role;?>user->roleList, $user->role, "class='select-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' autocomplete='off'");?>
              user->realname;?>realname, "class='text-3'");?>
              user->role;?>user->roleList, $user->role, "class='select-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 01fe052528..b7c937359c 100644 --- a/module/user/view/login.html.php +++ b/module/user/view/login.html.php @@ -1,63 +1,63 @@ - - * @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); - ?> -
              - - -
              - " . $lang->user->loginWithDemoUser . ""; - $sign = $config->requestType == 'GET' ? '&' : '?'; - if(isset($demoUsers['productManager'])) echo html::a(inlink('login') . $sign . "account=productManager&password=123456", $demoUsers['productManager'], 'hiddenwin'); - if(isset($demoUsers['projectManager'])) echo html::a(inlink('login') . $sign . "account=projectManager&password=123456", $demoUsers['projectManager'], 'hiddenwin'); - if(isset($demoUsers['testManager'])) echo html::a(inlink('login') . $sign . "account=testManager&password=123456", $demoUsers['testManager'], 'hiddenwin'); - if(isset($demoUsers['dev1'])) echo html::a(inlink('login') . $sign . "account=dev1&password=123456", $demoUsers['dev1'], 'hiddenwin'); - if(isset($demoUsers['tester1'])) echo html::a(inlink('login') . $sign . "account=tester1&password=123456", $demoUsers['tester1'], 'hiddenwin'); - ?> -
              - - -
              - 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); + ?> +
              + + +
              + " . $lang->user->loginWithDemoUser . ""; + $sign = $config->requestType == 'GET' ? '&' : '?'; + if(isset($demoUsers['productManager'])) echo html::a(inlink('login') . $sign . "account=productManager&password=123456", $demoUsers['productManager'], 'hiddenwin'); + if(isset($demoUsers['projectManager'])) echo html::a(inlink('login') . $sign . "account=projectManager&password=123456", $demoUsers['projectManager'], 'hiddenwin'); + if(isset($demoUsers['testManager'])) echo html::a(inlink('login') . $sign . "account=testManager&password=123456", $demoUsers['testManager'], 'hiddenwin'); + if(isset($demoUsers['dev1'])) echo html::a(inlink('login') . $sign . "account=dev1&password=123456", $demoUsers['dev1'], 'hiddenwin'); + if(isset($demoUsers['tester1'])) echo html::a(inlink('login') . $sign . "account=tester1&password=123456", $demoUsers['tester1'], 'hiddenwin'); + ?> +
              + + +
              + powered by ZenTaoPMS(version;?>) + donate;?> +
              + +
              + +
              + diff --git a/module/user/view/managecontacts.html.php b/module/user/view/managecontacts.html.php index d1faec30c9..af0572d207 100644 --- a/module/user/view/managecontacts.html.php +++ b/module/user/view/managecontacts.html.php @@ -1,71 +1,71 @@ - - * @package user - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - -
              -
              user->contacts->contactsList;?>
              -
              - $listName) echo html::a(inlink('managecontacts', "listID=$listID"), $listName) . '
              '; - ?> -
              -
              -
              -
              -
              user->contacts->manage;?>
              -
              delete, 'hiddenwin');?>
              -
              - - - - - - - - - - -
              user->contacts->selectedUsers;?> - view->users as $account => $realname) - { - echo "$realname"; - } - ?> -
              user->contacts->selectList) : print($lang->user->contacts->listName);?> - user->contacts->appendToList; - echo html::select('list2Append', array('' => '') + $lists, '', "class='select-2'") . $lang->user->contacts->or; - } - echo $lang->user->contacts->createList; - echo html::input('newList', '', "class='text-2'"); - } - else - { - echo html::input('listName', $list->listName, "class='text-2'"); - echo html::hidden('listID', $list->id); - } - ?> -
              -
              -
              - + + * @package user + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + +
              +
              user->contacts->contactsList;?>
              +
              + $listName) echo html::a(inlink('managecontacts', "listID=$listID"), $listName) . '
              '; + ?> +
              +
              +
              +
              +
              user->contacts->manage;?>
              +
              delete, 'hiddenwin');?>
              +
              + + + + + + + + + + +
              user->contacts->selectedUsers;?> + view->users as $account => $realname) + { + echo "$realname"; + } + ?> +
              user->contacts->selectList) : print($lang->user->contacts->listName);?> + user->contacts->appendToList; + echo html::select('list2Append', array('' => '') + $lists, '', "class='select-2'") . $lang->user->contacts->or; + } + echo $lang->user->contacts->createList; + echo html::input('newList', '', "class='text-2'"); + } + else + { + echo html::input('listName', $list->listName, "class='text-2'"); + echo html::hidden('listID', $list->id); + } + ?> +
              +
              +
              + diff --git a/module/user/view/profile.html.php b/module/user/view/profile.html.php index 34ea01f73d..dee0eaff5b 100644 --- a/module/user/view/profile.html.php +++ b/module/user/view/profile.html.php @@ -1,124 +1,124 @@ - - * @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->role;?>user->roleList[$user->role];?>
              user->commiter;?>commiter;?>
              user->email;?>email;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              user->msn;?>msn;?>
              user->qq;?>qq) echo html::a("tencent://message/?uin=$user->qq", $user->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->role;?>user->roleList[$user->role];?>
              user->commiter;?>commiter;?>
              user->email;?>email;?>
              user->join;?>join;?>
              user->visits;?>visits;?>
              user->ip;?>ip;?>
              user->last;?>last;?>
              user->msn;?>msn;?>
              user->qq;?>qq) echo html::a("tencent://message/?uin=$user->qq", $user->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 63d165f45d..af29fba7e8 100644 --- a/module/user/view/project.html.php +++ b/module/user/view/project.html.php @@ -1,47 +1,47 @@ - - * @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 4b6aa4c632..41ad0395aa 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 6e2bcd814f..b6cb68598d 100644 --- a/module/user/view/task.html.php +++ b/module/user/view/task.html.php @@ -1,46 +1,46 @@ - - * @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];?>'>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];?>
              show();?>
              - + + * @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];?>'>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];?>
              show();?>
              + diff --git a/module/user/view/team.html.php b/module/user/view/team.html.php index 95c5ad5ce6..a90904d650 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 59a0c562d5..e873bc43c2 100644 --- a/module/user/view/todo.html.php +++ b/module/user/view/todo.html.php @@ -1,72 +1,72 @@ - - * @package dashboard - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - -requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes';?> - - - - - - - -
              -
              user->todo; ?>
              -
              - todo->todayTodos) . '
              '; - echo html::a(inLink('todo', "account=$account&type=thisweek"), $lang->todo->thisWeekTodos) . '
              '; - echo html::a(inLink('todo', "account=$account&type=lastweek"), $lang->todo->lastWeekTodos) . '
              '; - echo html::a(inLink('todo', "account=$account&type=future"), $lang->todo->futureTodos) . '
              '; - echo html::a(inLink('todo', "account=$account&type=all"), $lang->todo->allDaysTodos) . '
              '; - echo html::a(inLink('todo', "account=$account&type=before"), $lang->todo->allUndone) . '
              '; - echo html::input('date', $date, "class='w-date todo-date' onchange=changeDate(this.value)"); - ?> -
              -
              -
              ' id='todoform'> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
              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;?>'>pri?>createLink('todo', 'view', "id=$todo->id") . $onlybody, $todo->name, '', "class='colorbox'");?>begin;?>end;?>todo->statusList[$todo->status];?>
              show();?>
              -
              -
              - + + * @package dashboard + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + +requestType == 'GET' ? '&onlybody=yes' : '?onlybody=yes';?> + + + + + + + +
              +
              user->todo; ?>
              +
              + todo->todayTodos) . '
              '; + echo html::a(inLink('todo', "account=$account&type=thisweek"), $lang->todo->thisWeekTodos) . '
              '; + echo html::a(inLink('todo', "account=$account&type=lastweek"), $lang->todo->lastWeekTodos) . '
              '; + echo html::a(inLink('todo', "account=$account&type=future"), $lang->todo->futureTodos) . '
              '; + echo html::a(inLink('todo', "account=$account&type=all"), $lang->todo->allDaysTodos) . '
              '; + echo html::a(inLink('todo', "account=$account&type=before"), $lang->todo->allUndone) . '
              '; + echo html::input('date', $date, "class='w-date todo-date' onchange=changeDate(this.value)"); + ?> +
              +
              +
              ' id='todoform'> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              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;?>'>pri?>createLink('todo', 'view', "id=$todo->id") . $onlybody, $todo->name, '', "class='colorbox'");?>begin;?>end;?>todo->statusList[$todo->status];?>
              show();?>
              +
              +
              + diff --git a/module/webapp/lang/en.php b/module/webapp/lang/en.php index 1d95aa29f1..f704f840f1 100644 --- a/module/webapp/lang/en.php +++ b/module/webapp/lang/en.php @@ -1,68 +1,68 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->webapp->common = 'Web App'; -$lang->webapp->index = 'Added App'; -$lang->webapp->obtain = 'Obtain App'; - -$lang->webapp->install = 'Install App'; -$lang->webapp->uninstall = 'Uninstall App'; -$lang->webapp->useapp = 'Use App'; -$lang->webapp->installed = 'Installed'; -$lang->webapp->edit = 'Edit App'; -$lang->webapp->create = 'Create App'; -$lang->webapp->manageTree = 'Manage Tree'; - -$lang->webapp->id = 'ID'; -$lang->webapp->name = 'Name'; -$lang->webapp->url = 'Link Address'; -$lang->webapp->icon = 'Icon'; -$lang->webapp->module = 'App Category'; -$lang->webapp->author = 'Author'; -$lang->webapp->desc = 'Desc'; -$lang->webapp->target = 'Target'; -$lang->webapp->size = 'Size'; -$lang->webapp->height = 'Height'; -$lang->webapp->addedTime = 'Add Time'; -$lang->webapp->updatedTime = 'Update Time'; -$lang->webapp->downloads = 'Downloads'; -$lang->webapp->grade = 'Grade'; -$lang->webapp->addType = 'Add Type'; -$lang->webapp->packup = 'Fold'; - -$lang->webapp->byDownloads = 'Most Downloads'; -$lang->webapp->byAddedTime = 'New Add'; -$lang->webapp->byUpdatedTime = 'New Update'; -$lang->webapp->bySearch = 'Search'; -$lang->webapp->byCategory = 'Category'; - -$lang->webapp->selectModule = 'Select Category:'; -$lang->webapp->allModule = 'All'; -$lang->webapp->noModule = 'Uncategorized'; - -$lang->webapp->targetList[''] = ''; -$lang->webapp->targetList['popup'] = 'Popup'; -$lang->webapp->targetList['iframe'] = 'Iframe'; -$lang->webapp->targetList['blank'] = 'New Window'; - -$lang->webapp->sizeList[''] = ""; -$lang->webapp->sizeList['900x600'] = "900 x 600"; -$lang->webapp->sizeList['700x600'] = "700 x 600"; -$lang->webapp->sizeList['600x500'] = "600 x 500"; - -$lang->webapp->addTypeList['system'] = 'System App'; -$lang->webapp->addTypeList['custom'] = 'Custom App'; - -$lang->webapp->errorOccurs = 'Error:'; -$lang->webapp->errorGetModules = "Get extensions' categories data from the www.zentao.net failed. "; -$lang->webapp->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->webapp->successInstall = 'Success Install App.'; -$lang->webapp->confirmDelete = 'Are you sure delete this app?'; + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->webapp->common = 'Web App'; +$lang->webapp->index = 'Added App'; +$lang->webapp->obtain = 'Obtain App'; + +$lang->webapp->install = 'Install App'; +$lang->webapp->uninstall = 'Uninstall App'; +$lang->webapp->useapp = 'Use App'; +$lang->webapp->installed = 'Installed'; +$lang->webapp->edit = 'Edit App'; +$lang->webapp->create = 'Create App'; +$lang->webapp->manageTree = 'Manage Tree'; + +$lang->webapp->id = 'ID'; +$lang->webapp->name = 'Name'; +$lang->webapp->url = 'Link Address'; +$lang->webapp->icon = 'Icon'; +$lang->webapp->module = 'App Category'; +$lang->webapp->author = 'Author'; +$lang->webapp->desc = 'Desc'; +$lang->webapp->target = 'Target'; +$lang->webapp->size = 'Size'; +$lang->webapp->height = 'Height'; +$lang->webapp->addedTime = 'Add Time'; +$lang->webapp->updatedTime = 'Update Time'; +$lang->webapp->downloads = 'Downloads'; +$lang->webapp->grade = 'Grade'; +$lang->webapp->addType = 'Add Type'; +$lang->webapp->packup = 'Fold'; + +$lang->webapp->byDownloads = 'Most Downloads'; +$lang->webapp->byAddedTime = 'New Add'; +$lang->webapp->byUpdatedTime = 'New Update'; +$lang->webapp->bySearch = 'Search'; +$lang->webapp->byCategory = 'Category'; + +$lang->webapp->selectModule = 'Select Category:'; +$lang->webapp->allModule = 'All'; +$lang->webapp->noModule = 'Uncategorized'; + +$lang->webapp->targetList[''] = ''; +$lang->webapp->targetList['popup'] = 'Popup'; +$lang->webapp->targetList['iframe'] = 'Iframe'; +$lang->webapp->targetList['blank'] = 'New Window'; + +$lang->webapp->sizeList[''] = ""; +$lang->webapp->sizeList['900x600'] = "900 x 600"; +$lang->webapp->sizeList['700x600'] = "700 x 600"; +$lang->webapp->sizeList['600x500'] = "600 x 500"; + +$lang->webapp->addTypeList['system'] = 'System App'; +$lang->webapp->addTypeList['custom'] = 'Custom App'; + +$lang->webapp->errorOccurs = 'Error:'; +$lang->webapp->errorGetModules = "Get extensions' categories data from the www.zentao.net failed. "; +$lang->webapp->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->webapp->successInstall = 'Success Install App.'; +$lang->webapp->confirmDelete = 'Are you sure delete this app?'; diff --git a/module/webapp/lang/zh-cn.php b/module/webapp/lang/zh-cn.php index 2a77126443..d0e216ee26 100644 --- a/module/webapp/lang/zh-cn.php +++ b/module/webapp/lang/zh-cn.php @@ -1,68 +1,68 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->webapp->common = 'WEB应用'; -$lang->webapp->index = '已加应用'; -$lang->webapp->obtain = '获得应用'; - -$lang->webapp->install = '安装应用'; -$lang->webapp->uninstall = '移除应用'; -$lang->webapp->useapp = '使用'; -$lang->webapp->installed = '已添加'; -$lang->webapp->edit = '编辑应用'; -$lang->webapp->create = '创建应用'; -$lang->webapp->manageTree = '维护分类'; - -$lang->webapp->id = '编号'; -$lang->webapp->name = '名称'; -$lang->webapp->url = '链接地址'; -$lang->webapp->icon = '图标'; -$lang->webapp->module = 'WEB分类'; -$lang->webapp->author = '作者'; -$lang->webapp->desc = '简介'; -$lang->webapp->target = '打开方式'; -$lang->webapp->size = '大小'; -$lang->webapp->height = '高度'; -$lang->webapp->addedTime = '添加时间'; -$lang->webapp->updatedTime = '更新时间'; -$lang->webapp->downloads = '下载量'; -$lang->webapp->grade = '评分'; -$lang->webapp->addType = '添加类型'; -$lang->webapp->packup = '收起'; - -$lang->webapp->byDownloads = '最多下载'; -$lang->webapp->byAddedTime = '最新添加'; -$lang->webapp->byUpdatedTime = '最近更新'; -$lang->webapp->bySearch = '搜索'; -$lang->webapp->byCategory = '分类浏览'; - -$lang->webapp->selectModule = '选择分类:'; -$lang->webapp->allModule = '所有'; -$lang->webapp->noModule = '未分类'; - -$lang->webapp->targetList[''] = ''; -$lang->webapp->targetList['popup'] = '弹窗'; -$lang->webapp->targetList['iframe'] = '内嵌'; -$lang->webapp->targetList['blank'] = '新窗口'; - -$lang->webapp->sizeList[''] = ""; -$lang->webapp->sizeList['900x600'] = "900 x 600"; -$lang->webapp->sizeList['700x600'] = "700 x 600"; -$lang->webapp->sizeList['600x500'] = "600 x 500"; - -$lang->webapp->addTypeList['system'] = '系统应用'; -$lang->webapp->addTypeList['custom'] = '自定义应用'; - -$lang->webapp->errorOccurs = '错误:'; -$lang->webapp->errorGetModules = '从www.zentao.net获得插件分类失败。可能是因为网络方面的原因,请检查后重新刷新页面。'; -$lang->webapp->errorGetExtensions = '从www.zentao.net获得插件失败。可能是因为网络方面的原因,您可以到www.zentao.net手工下载插件,然后上传安装。'; -$lang->webapp->successInstall = '成功安装应用!'; -$lang->webapp->confirmDelete = '是否删除该应用?'; + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->webapp->common = 'WEB应用'; +$lang->webapp->index = '已加应用'; +$lang->webapp->obtain = '获得应用'; + +$lang->webapp->install = '安装应用'; +$lang->webapp->uninstall = '移除应用'; +$lang->webapp->useapp = '使用'; +$lang->webapp->installed = '已添加'; +$lang->webapp->edit = '编辑应用'; +$lang->webapp->create = '创建应用'; +$lang->webapp->manageTree = '维护分类'; + +$lang->webapp->id = '编号'; +$lang->webapp->name = '名称'; +$lang->webapp->url = '链接地址'; +$lang->webapp->icon = '图标'; +$lang->webapp->module = 'WEB分类'; +$lang->webapp->author = '作者'; +$lang->webapp->desc = '简介'; +$lang->webapp->target = '打开方式'; +$lang->webapp->size = '大小'; +$lang->webapp->height = '高度'; +$lang->webapp->addedTime = '添加时间'; +$lang->webapp->updatedTime = '更新时间'; +$lang->webapp->downloads = '下载量'; +$lang->webapp->grade = '评分'; +$lang->webapp->addType = '添加类型'; +$lang->webapp->packup = '收起'; + +$lang->webapp->byDownloads = '最多下载'; +$lang->webapp->byAddedTime = '最新添加'; +$lang->webapp->byUpdatedTime = '最近更新'; +$lang->webapp->bySearch = '搜索'; +$lang->webapp->byCategory = '分类浏览'; + +$lang->webapp->selectModule = '选择分类:'; +$lang->webapp->allModule = '所有'; +$lang->webapp->noModule = '未分类'; + +$lang->webapp->targetList[''] = ''; +$lang->webapp->targetList['popup'] = '弹窗'; +$lang->webapp->targetList['iframe'] = '内嵌'; +$lang->webapp->targetList['blank'] = '新窗口'; + +$lang->webapp->sizeList[''] = ""; +$lang->webapp->sizeList['900x600'] = "900 x 600"; +$lang->webapp->sizeList['700x600'] = "700 x 600"; +$lang->webapp->sizeList['600x500'] = "600 x 500"; + +$lang->webapp->addTypeList['system'] = '系统应用'; +$lang->webapp->addTypeList['custom'] = '自定义应用'; + +$lang->webapp->errorOccurs = '错误:'; +$lang->webapp->errorGetModules = '从www.zentao.net获得插件分类失败。可能是因为网络方面的原因,请检查后重新刷新页面。'; +$lang->webapp->errorGetExtensions = '从www.zentao.net获得插件失败。可能是因为网络方面的原因,您可以到www.zentao.net手工下载插件,然后上传安装。'; +$lang->webapp->successInstall = '成功安装应用!'; +$lang->webapp->confirmDelete = '是否删除该应用?'; diff --git a/module/webapp/lang/zh-tw.php b/module/webapp/lang/zh-tw.php index 00af905bf7..752b72a2c8 100644 --- a/module/webapp/lang/zh-tw.php +++ b/module/webapp/lang/zh-tw.php @@ -1,68 +1,68 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -$lang->webapp->common = 'WEB應用'; -$lang->webapp->index = '已加應用'; -$lang->webapp->obtain = '獲得應用'; - -$lang->webapp->install = '安裝應用'; -$lang->webapp->uninstall = '移除應用'; -$lang->webapp->useapp = '使用'; -$lang->webapp->installed = '已添加'; -$lang->webapp->edit = '編輯應用'; -$lang->webapp->create = '創建應用'; -$lang->webapp->manageTree = '維護分類'; - -$lang->webapp->id = '編號'; -$lang->webapp->name = '名稱'; -$lang->webapp->url = '連結地址'; -$lang->webapp->icon = '表徵圖'; -$lang->webapp->module = 'WEB分類'; -$lang->webapp->author = '作者'; -$lang->webapp->desc = '簡介'; -$lang->webapp->target = '打開方式'; -$lang->webapp->size = '大小'; -$lang->webapp->height = '高度'; -$lang->webapp->addedTime = '添加時間'; -$lang->webapp->updatedTime = '更新時間'; -$lang->webapp->downloads = '下載量'; -$lang->webapp->grade = '評分'; -$lang->webapp->addType = '添加類型'; -$lang->webapp->packup = '收起'; - -$lang->webapp->byDownloads = '最多下載'; -$lang->webapp->byAddedTime = '最新添加'; -$lang->webapp->byUpdatedTime = '最近更新'; -$lang->webapp->bySearch = '搜索'; -$lang->webapp->byCategory = '分類瀏覽'; - -$lang->webapp->selectModule = '選擇分類:'; -$lang->webapp->allModule = '所有'; -$lang->webapp->noModule = '未分類'; - -$lang->webapp->targetList[''] = ''; -$lang->webapp->targetList['popup'] = '彈窗'; -$lang->webapp->targetList['iframe'] = '內嵌'; -$lang->webapp->targetList['blank'] = '新窗口'; - -$lang->webapp->sizeList[''] = ""; -$lang->webapp->sizeList['900x600'] = "900 x 600"; -$lang->webapp->sizeList['700x600'] = "700 x 600"; -$lang->webapp->sizeList['600x500'] = "600 x 500"; - -$lang->webapp->addTypeList['system'] = '系統應用'; -$lang->webapp->addTypeList['custom'] = '自定義應用'; - -$lang->webapp->errorOccurs = '錯誤:'; -$lang->webapp->errorGetModules = '從www.zentao.net獲得插件分類失敗。可能是因為網絡方面的原因,請檢查後重新刷新頁面。'; -$lang->webapp->errorGetExtensions = '從www.zentao.net獲得插件失敗。可能是因為網絡方面的原因,您可以到www.zentao.net手工下載插件,然後上傳安裝。'; -$lang->webapp->successInstall = '成功安裝應用!'; -$lang->webapp->confirmDelete = '是否刪除該應用?'; + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +$lang->webapp->common = 'WEB應用'; +$lang->webapp->index = '已加應用'; +$lang->webapp->obtain = '獲得應用'; + +$lang->webapp->install = '安裝應用'; +$lang->webapp->uninstall = '移除應用'; +$lang->webapp->useapp = '使用'; +$lang->webapp->installed = '已添加'; +$lang->webapp->edit = '編輯應用'; +$lang->webapp->create = '創建應用'; +$lang->webapp->manageTree = '維護分類'; + +$lang->webapp->id = '編號'; +$lang->webapp->name = '名稱'; +$lang->webapp->url = '連結地址'; +$lang->webapp->icon = '表徵圖'; +$lang->webapp->module = 'WEB分類'; +$lang->webapp->author = '作者'; +$lang->webapp->desc = '簡介'; +$lang->webapp->target = '打開方式'; +$lang->webapp->size = '大小'; +$lang->webapp->height = '高度'; +$lang->webapp->addedTime = '添加時間'; +$lang->webapp->updatedTime = '更新時間'; +$lang->webapp->downloads = '下載量'; +$lang->webapp->grade = '評分'; +$lang->webapp->addType = '添加類型'; +$lang->webapp->packup = '收起'; + +$lang->webapp->byDownloads = '最多下載'; +$lang->webapp->byAddedTime = '最新添加'; +$lang->webapp->byUpdatedTime = '最近更新'; +$lang->webapp->bySearch = '搜索'; +$lang->webapp->byCategory = '分類瀏覽'; + +$lang->webapp->selectModule = '選擇分類:'; +$lang->webapp->allModule = '所有'; +$lang->webapp->noModule = '未分類'; + +$lang->webapp->targetList[''] = ''; +$lang->webapp->targetList['popup'] = '彈窗'; +$lang->webapp->targetList['iframe'] = '內嵌'; +$lang->webapp->targetList['blank'] = '新窗口'; + +$lang->webapp->sizeList[''] = ""; +$lang->webapp->sizeList['900x600'] = "900 x 600"; +$lang->webapp->sizeList['700x600'] = "700 x 600"; +$lang->webapp->sizeList['600x500'] = "600 x 500"; + +$lang->webapp->addTypeList['system'] = '系統應用'; +$lang->webapp->addTypeList['custom'] = '自定義應用'; + +$lang->webapp->errorOccurs = '錯誤:'; +$lang->webapp->errorGetModules = '從www.zentao.net獲得插件分類失敗。可能是因為網絡方面的原因,請檢查後重新刷新頁面。'; +$lang->webapp->errorGetExtensions = '從www.zentao.net獲得插件失敗。可能是因為網絡方面的原因,您可以到www.zentao.net手工下載插件,然後上傳安裝。'; +$lang->webapp->successInstall = '成功安裝應用!'; +$lang->webapp->confirmDelete = '是否刪除該應用?'; diff --git a/module/webapp/model.php b/module/webapp/model.php index a4fe064b0f..ae2a5b8f86 100644 --- a/module/webapp/model.php +++ b/module/webapp/model.php @@ -1,303 +1,303 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -class webappModel extends model -{ - - /** - * 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->loadModel('tree'); - } - - /** - * Set menu. - * - * @param array $projects - * @param int $projectID - * @param string $extra - * @access public - * @return void - */ - public function setMenu($module = null) - { - $modules = $this->getModules(); - - $moduleName = $this->app->getModuleName(); - $methodName = $this->app->getMethodName(); - foreach($modules as $moduleID => $module) - { - $module = trim($module, '/'); - $this->lang->webapp->menu->$moduleID = array('link' => "$module|webapp|index|module=$moduleID"); - } - $this->lang->webapp->menu->manageTree = array('link' => "{$this->lang->webapp->manageTree}|tree|browse|rootID=0&view=webapp", 'float' => 'right'); - $this->lang->webapp->menu->create = array('link' => "{$this->lang->webapp->create}|webapp|create", 'float' => 'right'); - } - - - /** - * 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->webapp->apiRoot; - } - - /** - * Fetch data from an api. - * - * @param string $url - * @access public - * @return mixed - */ - public function fetchAPI($url) - { - $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 webapp 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 webapps by some condition. - * - * @param string $type - * @param mixed $param - * @access public - * @return array|bool - */ - public function getAppsByAPI($type, $param, $recTotal = 0, $recPerPage = 20, $pageID = 1) - { - $apiURL = $this->apiRoot . "apiGetApps-$type-$param-$recTotal-$recPerPage-$pageID.json"; - $data = $this->fetchAPI($apiURL); - return $data; - } - - /** - * Get a app info by API - * - * @param int $webappID - * @access public - * @return void - */ - public function getAppInfoByAPI($webappID) - { - $apiURL = $this->apiRoot . "apiGetAppInfo-$webappID.json"; - $data = $this->fetchAPI($apiURL); - return $data; - } - - /** - * Get webapps by status. - * - * @param string $status - * @access public - * @return array - */ - public function getLocalApps($key = 'id', $module = 0) - { - $webapps = $this->dao->select('*')->from(TABLE_WEBAPP) - ->beginIF($module != 0)->where('module')->eq($module)->fi() - ->fetchAll($key); - $localIcons = array(); - foreach($webapps as $webapp) - { - if($webapp->addType == 'custom') $localIcons[$webapp->id] = $webapp->icon; - } - - if($localIcons) - { - $files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($localIcons)->fetchAll('id'); - $fileWebPath = $this->loadModel('file')->webPath; - foreach($localIcons as $webappID => $icon) - { - if(isset($files[$icon])) $webapps[$webappID]->icon = $fileWebPath . $files[$icon]->pathname; - } - } - - return $webapps; - } - - /** - * Get webapp info from database. - * - * @param string $webapp - * @access public - * @return object - */ - public function getLocalAppByID($webappID) - { - $webapp = $this->dao->select('*')->from(TABLE_WEBAPP)->where('id')->eq($webappID)->fetch(); - if($webapp and is_numeric($webapp->icon)) $webapp->icon = $this->loadModel('file')->getByID($webapp->icon); - return $webapp; - } - - /** - * Install web app. - * - * @param int $webappID - * @access public - * @return void - */ - public function install($webappID) - { - $data = $this->getAppInfoByAPI($webappID); - $webapp = $data->webapp; - - $installWebapp->appid = $webapp->id; - $installWebapp->module = $this->post->module; - $installWebapp->name = $webapp->name; - $installWebapp->author = $webapp->author; - $installWebapp->url = $webapp->url; - $installWebapp->icon = $webapp->icon ? $this->config->webapp->url . $webapp->icon : ''; - $installWebapp->target = empty($webapp->target) ? 'blank' : $webapp->target; - $installWebapp->size = $webapp->size; - $installWebapp->desc = $webapp->desc; - $installWebapp->addedBy = $this->app->user->account; - $installWebapp->addedDate = helper::now(); - - $this->dao->insert(TABLE_WEBAPP)->data($installWebapp)->autocheck()->exec(); - return $this->dao->lastInsertID(); - } - - /** - * Update app. - * - * @param int $webappID - * @access public - * @return void - */ - public function update($webappID) - { - $webapp = $this->getLocalAppByID($webappID); - $data = fixer::input('post')->remove('files')->get(); - - $this->dao->update(TABLE_WEBAPP)->data($data)->where('id')->eq($webappID)->check('url', 'unique', "id != $webappID", false)->exec(); - - if(!dao::isError()) - { - if($_FILES) - { - $this->loadModel('file'); - if(empty($webapp->icon)) - { - $icon = $this->file->saveUpload('webapp', $webappID); - $this->dao->update(TABLE_WEBAPP)->set('icon')->eq(key($icon))->where('id')->eq($webappID)->exec(); - } - else - { - $this->file->replaceFile($webapp->icon->id, 'files'); - } - } - } - } - - /** - * Create a web app. - * - * @access public - * @return void - */ - public function create() - { - $data = fixer::input('post') - ->add('addedBy', $this->app->user->account) - ->add('addType', 'custom') - ->add('addedDate', helper::now()) - ->add('author', $this->app->user->account) - ->remove('files')->get(); - $this->dao->insert(TABLE_WEBAPP)->data($data) - ->autocheck() - ->batchCheck($this->config->webapp->create->requiredFields, 'notempty') - ->exec(); - if(!dao::isError()) - { - $webappID = $this->dao->lastInsertID(); - if($_FILES) - { - $fileTitle = $this->loadModel('file')->saveUpload('webapp', $webappID); - $this->dao->update(TABLE_WEBAPP)->set('icon')->eq(key($fileTitle))->where('id')->eq($webappID)->exec(); - } - return $webappID; - } - } - - /** - * Get app modules. - * - * @access public - * @return void - */ - public function getModules() - { - $modules = $this->tree->getOptionMenu(0, 'webapp'); - $modules[0] = (count($modules) == 1) ? $this->lang->webapp->noModule : $this->lang->webapp->allModule; - - return $modules; - } -} + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +class webappModel extends model +{ + + /** + * 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->loadModel('tree'); + } + + /** + * Set menu. + * + * @param array $projects + * @param int $projectID + * @param string $extra + * @access public + * @return void + */ + public function setMenu($module = null) + { + $modules = $this->getModules(); + + $moduleName = $this->app->getModuleName(); + $methodName = $this->app->getMethodName(); + foreach($modules as $moduleID => $module) + { + $module = trim($module, '/'); + $this->lang->webapp->menu->$moduleID = array('link' => "$module|webapp|index|module=$moduleID"); + } + $this->lang->webapp->menu->manageTree = array('link' => "{$this->lang->webapp->manageTree}|tree|browse|rootID=0&view=webapp", 'float' => 'right'); + $this->lang->webapp->menu->create = array('link' => "{$this->lang->webapp->create}|webapp|create", 'float' => 'right'); + } + + + /** + * 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->webapp->apiRoot; + } + + /** + * Fetch data from an api. + * + * @param string $url + * @access public + * @return mixed + */ + public function fetchAPI($url) + { + $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 webapp 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 webapps by some condition. + * + * @param string $type + * @param mixed $param + * @access public + * @return array|bool + */ + public function getAppsByAPI($type, $param, $recTotal = 0, $recPerPage = 20, $pageID = 1) + { + $apiURL = $this->apiRoot . "apiGetApps-$type-$param-$recTotal-$recPerPage-$pageID.json"; + $data = $this->fetchAPI($apiURL); + return $data; + } + + /** + * Get a app info by API + * + * @param int $webappID + * @access public + * @return void + */ + public function getAppInfoByAPI($webappID) + { + $apiURL = $this->apiRoot . "apiGetAppInfo-$webappID.json"; + $data = $this->fetchAPI($apiURL); + return $data; + } + + /** + * Get webapps by status. + * + * @param string $status + * @access public + * @return array + */ + public function getLocalApps($key = 'id', $module = 0) + { + $webapps = $this->dao->select('*')->from(TABLE_WEBAPP) + ->beginIF($module != 0)->where('module')->eq($module)->fi() + ->fetchAll($key); + $localIcons = array(); + foreach($webapps as $webapp) + { + if($webapp->addType == 'custom') $localIcons[$webapp->id] = $webapp->icon; + } + + if($localIcons) + { + $files = $this->dao->select('*')->from(TABLE_FILE)->where('id')->in($localIcons)->fetchAll('id'); + $fileWebPath = $this->loadModel('file')->webPath; + foreach($localIcons as $webappID => $icon) + { + if(isset($files[$icon])) $webapps[$webappID]->icon = $fileWebPath . $files[$icon]->pathname; + } + } + + return $webapps; + } + + /** + * Get webapp info from database. + * + * @param string $webapp + * @access public + * @return object + */ + public function getLocalAppByID($webappID) + { + $webapp = $this->dao->select('*')->from(TABLE_WEBAPP)->where('id')->eq($webappID)->fetch(); + if($webapp and is_numeric($webapp->icon)) $webapp->icon = $this->loadModel('file')->getByID($webapp->icon); + return $webapp; + } + + /** + * Install web app. + * + * @param int $webappID + * @access public + * @return void + */ + public function install($webappID) + { + $data = $this->getAppInfoByAPI($webappID); + $webapp = $data->webapp; + + $installWebapp->appid = $webapp->id; + $installWebapp->module = $this->post->module; + $installWebapp->name = $webapp->name; + $installWebapp->author = $webapp->author; + $installWebapp->url = $webapp->url; + $installWebapp->icon = $webapp->icon ? $this->config->webapp->url . $webapp->icon : ''; + $installWebapp->target = empty($webapp->target) ? 'blank' : $webapp->target; + $installWebapp->size = $webapp->size; + $installWebapp->desc = $webapp->desc; + $installWebapp->addedBy = $this->app->user->account; + $installWebapp->addedDate = helper::now(); + + $this->dao->insert(TABLE_WEBAPP)->data($installWebapp)->autocheck()->exec(); + return $this->dao->lastInsertID(); + } + + /** + * Update app. + * + * @param int $webappID + * @access public + * @return void + */ + public function update($webappID) + { + $webapp = $this->getLocalAppByID($webappID); + $data = fixer::input('post')->remove('files')->get(); + + $this->dao->update(TABLE_WEBAPP)->data($data)->where('id')->eq($webappID)->check('url', 'unique', "id != $webappID", false)->exec(); + + if(!dao::isError()) + { + if($_FILES) + { + $this->loadModel('file'); + if(empty($webapp->icon)) + { + $icon = $this->file->saveUpload('webapp', $webappID); + $this->dao->update(TABLE_WEBAPP)->set('icon')->eq(key($icon))->where('id')->eq($webappID)->exec(); + } + else + { + $this->file->replaceFile($webapp->icon->id, 'files'); + } + } + } + } + + /** + * Create a web app. + * + * @access public + * @return void + */ + public function create() + { + $data = fixer::input('post') + ->add('addedBy', $this->app->user->account) + ->add('addType', 'custom') + ->add('addedDate', helper::now()) + ->add('author', $this->app->user->account) + ->remove('files')->get(); + $this->dao->insert(TABLE_WEBAPP)->data($data) + ->autocheck() + ->batchCheck($this->config->webapp->create->requiredFields, 'notempty') + ->exec(); + if(!dao::isError()) + { + $webappID = $this->dao->lastInsertID(); + if($_FILES) + { + $fileTitle = $this->loadModel('file')->saveUpload('webapp', $webappID); + $this->dao->update(TABLE_WEBAPP)->set('icon')->eq(key($fileTitle))->where('id')->eq($webappID)->exec(); + } + return $webappID; + } + } + + /** + * Get app modules. + * + * @access public + * @return void + */ + public function getModules() + { + $modules = $this->tree->getOptionMenu(0, 'webapp'); + $modules[0] = (count($modules) == 1) ? $this->lang->webapp->noModule : $this->lang->webapp->allModule; + + return $modules; + } +} diff --git a/module/webapp/view/index.html.php b/module/webapp/view/index.html.php index f9dc7981e4..c8774f63b7 100644 --- a/module/webapp/view/index.html.php +++ b/module/webapp/view/index.html.php @@ -1,64 +1,64 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - -
              -
                - -
              • - - - - - - - - - - -
                icon?>' width='72' height='72' />name?>
                desc) ? ' ' : $webapp->desc?>
                webapp->addTypeList[$webapp->addType];?>
                - id"), $lang->webapp->uninstall, 'hiddenwin', "class='button-c'"); - $url = $webapp->addType == 'custom' ? $webapp->url : $config->webapp->url . "/webapp-showapp-{$webapp->appid}.html"; - $method = ''; - $popup = ''; - $target = '_self'; - if($webapp->target == 'blank') $target = '_blank'; - if($webapp->target == 'iframe')$method = "toggleShowapp($webapp->id, \"$webapp->name\");"; - if($webapp->target == 'popup') - { - $width = 0; - $height = 0; - if($webapp->size) list($width, $height) = explode('x', $webapp->size); - $method = "popup($width, $height);"; - $popup = 'popup'; - } - $useAppCode = html::a($url, $lang->webapp->useapp, $target, "id='useapp$webapp->id' class='button-c $popup' onclick='addView($webapp->id);$method'"); - $editAppCode = html::a(inlink('edit', "webappID=$webapp->id"), $lang->edit, '', "class='button-c webapp'"); - echo $useAppCode . $editAppCode . $uninstallCode; - ?> -
                -
              • - -
              -
              - - + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + +
              +
                + +
              • + + + + + + + + + + +
                icon?>' width='72' height='72' />name?>
                desc) ? ' ' : $webapp->desc?>
                webapp->addTypeList[$webapp->addType];?>
                + id"), $lang->webapp->uninstall, 'hiddenwin', "class='button-c'"); + $url = $webapp->addType == 'custom' ? $webapp->url : $config->webapp->url . "/webapp-showapp-{$webapp->appid}.html"; + $method = ''; + $popup = ''; + $target = '_self'; + if($webapp->target == 'blank') $target = '_blank'; + if($webapp->target == 'iframe')$method = "toggleShowapp($webapp->id, \"$webapp->name\");"; + if($webapp->target == 'popup') + { + $width = 0; + $height = 0; + if($webapp->size) list($width, $height) = explode('x', $webapp->size); + $method = "popup($width, $height);"; + $popup = 'popup'; + } + $useAppCode = html::a($url, $lang->webapp->useapp, $target, "id='useapp$webapp->id' class='button-c $popup' onclick='addView($webapp->id);$method'"); + $editAppCode = html::a(inlink('edit', "webappID=$webapp->id"), $lang->edit, '', "class='button-c webapp'"); + echo $useAppCode . $editAppCode . $uninstallCode; + ?> +
                +
              • + +
              +
              + + diff --git a/module/webapp/view/obtain.html.php b/module/webapp/view/obtain.html.php index dc00f3a8e5..088f0403be 100644 --- a/module/webapp/view/obtain.html.php +++ b/module/webapp/view/obtain.html.php @@ -1,66 +1,66 @@ - - * @package webapp - * @version $Id$ - * @link http://www.zentao.net - */ -?> - - - - - - - - -
              -
              webapp->obtain;?>
              -
              - " . html::a(inlink('obtain', 'type=byUpdatedTime'), $lang->webapp->byUpdatedTime) . '
              '; - echo "" . html::a(inlink('obtain', 'type=byAddedTime'), $lang->webapp->byAddedTime) . '
              '; - echo "" . html::a(inlink('obtain', 'type=byDownloads'), $lang->webapp->byDownloads) . '
              '; - ?> -
              -
              webapp->bySearch;?>
              -
              -
              '> - post->key, "class='text-1'") . html::submitButton($lang->webapp->bySearch);?> -
              -
              -
              webapp->byCategory;?>
              -
              - webapp->errorGetModules);?> -
              -
              - -
                - -
              • - - - - - - - -
                webapp->url . $webapp->icon?>' width='72' height='72' />name?>
                desc) ? ' ' : $webapp->desc?>
                id]) ? html::commonButton($lang->webapp->installed, "disabled='disabled' style='color:gray'") : html::a(inLink('install', "webappID={$webapp->id}"), $lang->webapp->install, '_self', "class='button-c iframe'")?>
                -
              • - -
              -

              show();?>

              - -
              webapp->errorOccurs;?>
              -
              webapp->errorGetExtensions;?>
              - -
              - - + + * @package webapp + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + + + + + + + +
              +
              webapp->obtain;?>
              +
              + " . html::a(inlink('obtain', 'type=byUpdatedTime'), $lang->webapp->byUpdatedTime) . '
              '; + echo "" . html::a(inlink('obtain', 'type=byAddedTime'), $lang->webapp->byAddedTime) . '
              '; + echo "" . html::a(inlink('obtain', 'type=byDownloads'), $lang->webapp->byDownloads) . '
              '; + ?> +
              +
              webapp->bySearch;?>
              +
              +
              '> + post->key, "class='text-1'") . html::submitButton($lang->webapp->bySearch);?> +
              +
              +
              webapp->byCategory;?>
              +
              + webapp->errorGetModules);?> +
              +
              + +
                + +
              • + + + + + + + +
                webapp->url . $webapp->icon?>' width='72' height='72' />name?>
                desc) ? ' ' : $webapp->desc?>
                id]) ? html::commonButton($lang->webapp->installed, "disabled='disabled' style='color:gray'") : html::a(inLink('install', "webappID={$webapp->id}"), $lang->webapp->install, '_self', "class='button-c iframe'")?>
                +
              • + +
              +

              show();?>

              + +
              webapp->errorOccurs;?>
              +
              webapp->errorGetExtensions;?>
              + +
              + + diff --git a/www/index.php b/www/index.php index 5ae2052bd8..dd5ba965f6 100644 --- a/www/index.php +++ b/www/index.php @@ -1,42 +1,42 @@ - - * @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 3b62aebd26..e41ed25d11 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 6e78d510e7..44fed52936 100644 --- a/www/upgrade.php +++ b/www/upgrade.php @@ -1,46 +1,46 @@ - - * @package ZenTaoPMS - * @version $Id$ - * @link http://www.zentao.net - */ -/* Judge my.php exists or not. */ -$myConfig = dirname(dirname(__FILE__)) . '/config/my.php'; -if(!file_exists($myConfig)) -{ - echo "文件" . $myConfig . "不存在! 提示:不要重命名原来的禅道安装目录,下载最新的源码包,覆盖即可。" . "
              "; - echo $myConfig . " doesn't exists! Please don't rename zentao before overriding the source code!"; - exit; -} - -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 + */ +/* Judge my.php exists or not. */ +$myConfig = dirname(dirname(__FILE__)) . '/config/my.php'; +if(!file_exists($myConfig)) +{ + echo "文件" . $myConfig . "不存在! 提示:不要重命名原来的禅道安装目录,下载最新的源码包,覆盖即可。" . "
              "; + echo $myConfig . " doesn't exists! Please don't rename zentao before overriding the source code!"; + exit; +} + +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();