diff --git a/module/cron/lang/zh-cn.php b/module/cron/lang/zh-cn.php index 5f526482c7..c7919b7a71 100644 --- a/module/cron/lang/zh-cn.php +++ b/module/cron/lang/zh-cn.php @@ -54,3 +54,4 @@ $lang->cron->notice->mon = '取值范围:1-12'; $lang->cron->notice->dow = '取值范围:0-6'; $lang->cron->notice->help = '注:如果服务器重启,或者发现计划任务没有正常工作,那么计划任务已经停止工作。需要手动点击【重启】按钮,或者一分钟后刷新页面,来开启计划任务。如果任务列表中第一条记录的最后执行时间改变,说明任务开启成功。'; $lang->cron->notice->errorRule = '"%s" 填写的不是合法的值'; +$lang->cron->notice->errorType = '不能创建操作系统命令类型的计划任务'; diff --git a/module/cron/model.php b/module/cron/model.php index 6690222c3b..ab9822d8fc 100644 --- a/module/cron/model.php +++ b/module/cron/model.php @@ -13,8 +13,8 @@ class cronModel extends model { /** * Get by Id. - * - * @param int $cronID + * + * @param int $cronID * @access public * @return object */ @@ -25,8 +25,8 @@ class cronModel extends model /** * Get crons. - * - * @param string $params + * + * @param string $params * @access public * @return array */ @@ -40,8 +40,8 @@ class cronModel extends model /** * Parse crons. - * - * @param array $crons + * + * @param array $crons * @access public * @return array */ @@ -64,12 +64,12 @@ class cronModel extends model $parsedCron['cron'] = CronExpression::factory($parsedCron['schema']); $parsedCron['time'] = $parsedCron['cron']->getNextRunDate(); $parsedCrons[$cron->id] = $parsedCron; - } - catch(InvalidArgumentException $e) + } + catch(InvalidArgumentException $e) { $this->dao->update(TABLE_CRON)->set('status')->eq('stop')->where('id')->eq($cron->id)->exec(); continue; - } + } } } $this->dao->update(TABLE_CRON)->set('lastTime')->eq(date(DT_DATETIME1))->where('lastTime')->eq('0000-00-00 00:00:00')->andWhere('status')->ne('stop')->exec(); @@ -78,10 +78,10 @@ class cronModel extends model /** * Change cron status. - * - * @param int $cronID - * @param string $status - * @param bool $changeTime + * + * @param int $cronID + * @param string $status + * @param bool $changeTime * @access public * @return bool */ @@ -96,8 +96,8 @@ class cronModel extends model /** * Log cron. - * - * @param string $log + * + * @param string $log * @access public * @return void */ @@ -115,7 +115,7 @@ class cronModel extends model /** * Get last execed time. - * + * * @access public * @return string */ @@ -127,7 +127,7 @@ class cronModel extends model /** * Runable cron. - * + * * @access public * @return bool */ @@ -145,7 +145,7 @@ class cronModel extends model /** * Check change cron. - * + * * @access public * @return bool */ @@ -156,8 +156,8 @@ class cronModel extends model } /** - * Create cron. - * + * Create cron. + * * @access public * @return int */ @@ -169,6 +169,12 @@ class cronModel extends model ->skipSpecial('m,h,dom,mon,dow,command') ->get(); + if(!$this->config->features->cronSystemCall and $cron->type == 'system') + { + dao::$errors[] = $this->lang->cron->notice->errorType; + return false; + } + $result = $this->checkRule($cron); if(!empty($result)) { @@ -182,9 +188,9 @@ class cronModel extends model } /** - * Update cron. - * - * @param int $cronID + * Update cron. + * + * @param int $cronID * @access public * @return bool */ @@ -195,6 +201,12 @@ class cronModel extends model ->skipSpecial('m,h,dom,mon,dow,command') ->get(); + if(!$this->config->features->cronSystemCall and $cron->type == 'system') + { + dao::$errors[] = $this->lang->cron->notice->errorType; + return false; + } + $result = $this->checkRule($cron); if(!empty($result)) { @@ -208,8 +220,8 @@ class cronModel extends model /** * Check cron rule. - * - * @param object $cron + * + * @param object $cron * @access public * @return string */ @@ -256,7 +268,7 @@ class cronModel extends model /** * Get current cron status. - * + * * @access public * @return int */ diff --git a/module/execution/model.php b/module/execution/model.php index 68f135c88c..ee2c4fb8ce 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -72,7 +72,6 @@ class executionModel extends model if($execution->type == 'stage') { global $lang; - $this->loadModel('execution'); $this->app->loadLang('project'); $lang->executionCommon = $lang->project->stage; include $this->app->getModulePath('execution') . 'lang/' . $this->app->getClientLang() . '.php'; diff --git a/module/repo/control.php b/module/repo/control.php index 9580fd9d4f..411c1b0bc5 100644 --- a/module/repo/control.php +++ b/module/repo/control.php @@ -867,7 +867,7 @@ class repo extends control set_time_limit(0); $repo = $this->repo->getRepoByID($repoID); if(empty($repo)) die(); - //if($repo->synced) die('finish'); + if($repo->synced) die('finish'); $this->commonAction($repoID); $this->scm->setEngine($repo); diff --git a/module/repo/model.php b/module/repo/model.php index fd22ec2338..03ec69715a 100644 --- a/module/repo/model.php +++ b/module/repo/model.php @@ -281,15 +281,18 @@ class repoModel extends model $repo = $this->getRepoByID($id); $data = fixer::input('post') + ->setIf($this->post->SCM == 'Gitlab', 'password', $this->post->gitlabToken) + ->setIf($this->post->SCM == 'Gitlab', 'client', $this->post->gitlabHost) + ->setIf($this->post->SCM == 'Gitlab', 'extra', $this->post->gitlabProject) ->setDefault('client', 'svn') ->setDefault('prefix', $repo->prefix) ->setDefault('product', '') - ->setIF($this->post->path != $repo->path, 'synced', 0) ->skipSpecial('path,client,account,password') ->join('product', ',') ->get(); if($this->post->SCM == 'Gitlab') $data->path = sprintf($this->config->repo->gitlab->apiPath, $data->gitlabHost, $this->post->gitlabProject); + if($data->path != $repo->path) $data->synced = 0; $data->acl = empty($data->acl) ? '' : json_encode($data->acl); @@ -313,7 +316,7 @@ class repoModel extends model $this->dao->update(TABLE_REPO)->data($data, $skip = 'gitlabHost,gitlabToken,gitlabProject') ->batchCheck($this->config->repo->edit->requiredFields, 'notempty') ->checkIF($data->SCM == 'Subversion', $this->config->repo->svn->requiredFields, 'notempty') - ->checkIF($data->SCM == 'GitLab', 'gitlabProject', 'notempty') + ->checkIF($data->SCM == 'GitLab', 'extra', 'notempty') ->autoCheck() ->where('id')->eq($id)->exec(); diff --git a/module/todo/css/batchcreate.css b/module/todo/css/batchcreate.css index 222fe0e42e..19576bc2ab 100755 --- a/module/todo/css/batchcreate.css +++ b/module/todo/css/batchcreate.css @@ -16,3 +16,7 @@ html[lang="en"] .main-header > .input-group {width: 250px;} #formSettingBtn {position: absolute; top: 14px; right: 20px; z-index: 1000;} #formSettingBtn .dropdown {margin-right: 0px;} +#formSettingBtn #formSetting {padding: 10px 12px;} +#formSettingBtn .checkboxes {padding: 10px 3px;} +#formSettingBtn .checkbox-primary {width: 50%; float: left; margin: 3px 0;} +#formSetting .btn {margin-right: 8px;} diff --git a/module/tree/control.php b/module/tree/control.php index d1d3686718..eaf069b278 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -419,10 +419,12 @@ class tree extends control * @param string $returnType * @param string $fieldID * @param bool $needManage + * @param string $extra + * @param int $currentModuleID * @access public * @return string the html select string. */ - public function ajaxGetOptionMenu($rootID, $viewType = 'story', $branch = 0, $rootModuleID = 0, $returnType = 'html', $fieldID = '', $needManage = false, $extra = '') + public function ajaxGetOptionMenu($rootID, $viewType = 'story', $branch = 0, $rootModuleID = 0, $returnType = 'html', $fieldID = '', $needManage = false, $extra = '', $currentModuleID = 0) { if($viewType == 'task') { @@ -448,7 +450,7 @@ class tree extends control $changeFunc = ''; if($viewType == 'task' or $viewType == 'bug' or $viewType == 'case') $changeFunc = "onchange='loadModuleRelated()'"; $field = $fieldID ? "modules[$fieldID]" : 'module'; - $output = html::select("$field", $optionMenu, '', "class='form-control' $changeFunc"); + $output = html::select("$field", $optionMenu, $currentModuleID, "class='form-control' $changeFunc"); if(count($optionMenu) == 1 and $needManage) { $output .= ""; diff --git a/module/user/model.php b/module/user/model.php index ee703dba6e..3b68f42bee 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -191,7 +191,7 @@ class userModel extends model /** * Get user info by ID. * - * @param int $userID + * @param mix $userID * @access public * @return object|bool */ diff --git a/test/init.php b/test/init.php index 23acb0c613..93c3aa8626 100644 --- a/test/init.php +++ b/test/init.php @@ -1,6 +1,6 @@ loadCommon() 方法创建名为 tester 的commonModel对象。 + * 本文件创建一个 app 实例,并且通过执行 $app->loadCommon() 方法创建名为 tester 的commonModel对象。 * This file build a app instance and provide a instance of commonModel named as tester by $app->loadCommon(). * * All request of entries should be routed by this router. @@ -13,13 +13,89 @@ * @link http://www.zentao.net */ /* Set the error reporting. */ -error_reporting(0); +error_reporting(E_ALL & E_STRICT); + +$frameworkRoot = dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR; /* Load the framework. */ -include '../framework/router.class.php'; -include '../framework/control.class.php'; -include '../framework/model.class.php'; -include '../framework/helper.class.php'; +include $frameworkRoot . 'router.class.php'; +include $frameworkRoot . 'control.class.php'; +include $frameworkRoot . 'model.class.php'; +include $frameworkRoot . 'helper.class.php'; $app = router::createApp('pms', dirname(dirname(__FILE__)), 'router'); $tester = $app->loadCommon(); + +$config->zendataRoot = dirname(__FILE__) . DS . 'zendata'; +$config->zdPath = "/usr/local/zd/zd"; + +/** + * Save variable to $_result. + * + * @param mix $result + * @access public + * @return bool true + */ +function run($result) +{ + global $_result; + $_result = $result; + return true; +} + +/** + * Print expect data. + * + * @param int $key + * @param string $delimiter + * @access public + * @return void + */ +function expect($key, $delimiter = ',') +{ + global $_result; + echo ">> "; + $result = ""; + + if(!is_array($_result) and !is_object($_result)) + { + $result = (string) $_result; + } + else + { + $keyList = explode(',', $key); + $dimension = 1; + foreach($_result as $value) + { + if(is_array($value) or is_object($value)) $dimension = 2; + } + + if($dimension == 1) $_result = array($_result); + foreach($_result as $object) + { + foreach($keyList as $key) $result .= zget($object, $key, '') . $delimiter; + } + $result = trim($result, $delimiter); + } + echo $result . "\n"; + echo "\n"; +} + +/** + * Import data create by zendata to one table. + * + * @param string $table + * @param string $yaml + * @param int $count + * @access public + * @return void + */ +function zdImport($table, $yaml, $count = 10) +{ + chdir(dirname(__FILE__)); + global $app, $config; + $dns = "mysql://{$config->db->user}:{$config->db->password}@{$config->db->host}:{$config->db->port}/{$config->db->name}#utf8"; + $table = trim($table, '`'); + $commad = "$config->zdPath -c $yaml -t $table -T -dns $dns --clear -n $count"; + system($commad); +} diff --git a/test/model/user/getbyid.php b/test/model/user/getbyid.php new file mode 100755 index 0000000000..b1643434ab --- /dev/null +++ b/test/model/user/getbyid.php @@ -0,0 +1,31 @@ +#!/usr/bin/env php +> `\d,\w+` + 2. 使用account获取一个存在的用户 >> `\d` + 3. 使用account获取一个存在的用户 >> `` +[esac] +*/ +$user = $tester->loadModel('user'); + +$app->dbh->query("truncate zt_user"); +zdImport(TABLE_USER, "zendata/user.yaml", 10); + +$randUser = $tester->dao->select('*,rand() as rand')->from(TABLE_USER)->orderBy('rand')->fetch(); +if(!$randUser) exit("Prepair data error."); +unset($randUser->rand); + +/* Step 1.*/ +run($user->getByID($randUser->id, 'id')) and expect('id,account'); + +/* Step 2.*/ +run($user->getByID($randUser->account, 'account')) and expect('id'); + +/* Step 3.*/ +run($user->getByID(null, 'id')) and expect('id'); diff --git a/test/zendata/user.yaml b/test/zendata/user.yaml new file mode 100644 index 0000000000..5acb5c1855 --- /dev/null +++ b/test/zendata/user.yaml @@ -0,0 +1,256 @@ +title: table zt_user +desc: "用户信息" +author: automated export +version: "1.0" +fields: + - field: id + note: "ID" + range: 1-10000 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: dept + note: "所属部门" + range: 1-10000 + prefix: "" + postfix: "\t" + format: "" + - field: account + note: "用户名" + from: name.enaccount.v1.yaml + use: common_underline + postfix: "\t" # 后缀,特殊字符加引号,否则无法解析。 + format: "" + - field: password + note: "密码" + range: 123456 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: role + note: "职位" + range: qa,dev,pm,po,td,pd,qd,top,market,service,operation,support,others + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: realname + note: "真实姓名" + from: name.cnreal.v1.yaml + use: three + format: "" + - field: nickname + note: "昵称" + from: name.enaccount.v1.yaml + use: common + postfix: "\t" + loop: 0 + - field: commiter + note: "源代码帐号" + from: name.enaccount.v1.yaml + use: common + postfix: "@zentao.net" + loop: 0 + format: "" + - field: avatar + note: "" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: birthday + note: "生日" + from: time.date.v1.yaml + use: date + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: gender + note: "性别" + range: f,m + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: email + note: "邮箱" + range: 1-10000 + prefix: "这里是邮箱" + postfix: "\t" + loop: 0 + format: "" + - field: skype + note: "Skype" + range: Skype + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: qq + note: "QQ" + range: QQ + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: mobile + note: "手机" + range: mobile + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: phone + note: "电话" + range: phone + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: weixin + note: "微信" + range: weixin + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: dingding + note: "钉钉" + range: dingding + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: slack + note: "Slack" + range: slack + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: whatsapp + note: "WhatsApp" + range: whatsApp + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: address + note: "通讯地址" + range: 1-10000 + prefix: "这是通讯地址" + postfix: "\t" + loop: 0 + format: "" + - field: zipcode + note: "邮编" + range: 1-10000 + prefix: "这是邮编" + postfix: "\t" + loop: 0 + format: "" + - field: join + note: "入职日期" + from: time.date.v1.yaml + use: date + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: visits + note: "访问次数" + range: 0-10000:R + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: ip + note: "最后IP" + from: ip.v1.yaml + use: ipA,ipB + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: last + note: "最后登录" + range: 1-10000 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: fails + note: "失败次数" + range: 1-10000 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: locked + note: "锁定时间" + from: time.date.v1.yaml + use: date + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: feedback + note: "反馈[非研发]" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: ranzhi + note: "ZDOO账号" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: ldap + note: "" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: score + note: "积分" + range: 1-10000:R + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: scoreLevel + note: "积分等级" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: deleted + note: "是否删除" + range: 0 + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: clientStatus + note: "连接状态" + range: offline + prefix: "" + postfix: "\t" + loop: 0 + format: "" + - field: clientLang + note: "连接语言" + range: en + prefix: "" + postfix: "\t" + loop: 0 + format: ""