diff --git a/config/config.php b/config/config.php
index 14507903f6..218e54c362 100644
--- a/config/config.php
+++ b/config/config.php
@@ -37,8 +37,9 @@ $config->sessionVar = 'sid'; // requestType=GET: the session var na
$config->views = ',html,json,mhtml,';
/* Set the wide window size. */
-$config->wideSize = 1400;
-$config->timeout = 30000;
+$config->wideSize = 1400;
+$config->timeout = 30000;
+$config->duplicateTime = 60; // from 1 minute.
/* Supported languages. */
$config->langs['zh-cn'] = '简体';
diff --git a/module/bug/control.php b/module/bug/control.php
index a779e40a9c..efd920d559 100644
--- a/module/bug/control.php
+++ b/module/bug/control.php
@@ -228,9 +228,10 @@ class bug extends control
}
$bugID = $bugResult['id'];
- if($bugResult['status'] == 'existed')
+ if($bugResult['status'] == 'exists')
{
- $response['locate'] = $this->createLink('bug', 'view', "bugID=$bugID");
+ $response['message'] = sprintf($this->lang->duplicate, $this->lang->bug->common);
+ $response['locate'] = $this->createLink('bug', 'view', "bugID=$bugID");
$this->send($response);
}
diff --git a/module/bug/model.php b/module/bug/model.php
index 6cb1815049..0f46b12eb4 100644
--- a/module/bug/model.php
+++ b/module/bug/model.php
@@ -56,8 +56,8 @@ class bugModel extends model
->get();
/* Check repeat bug. */
- $bugID = $this->loadModel('common')->checkRepeat('bug', 'check', $bug->title, "product={$bug->product}");
- if($bugID) return array('status' => 'existed', 'id' => $bugID);
+ $result = $this->loadModel('common')->removeDuplicate('bug', $bug, "product={$bug->product}");
+ if($result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']);
$this->dao->insert(TABLE_BUG)->data($bug)->autoCheck()->batchCheck($this->config->bug->create->requiredFields, 'notempty')->exec();
if(!dao::isError())
@@ -83,11 +83,13 @@ class bugModel extends model
$actions = array();
$data = fixer::input('post')->get();
$batchNum = count(reset($data));
- $latestBugs = $this->loadModel('common')->checkRepeat('bug', 'get', '', "product=$productID");
+
+ $result = $this->loadModel('common')->removeDuplicate('bug', $data, "product=$productID");
+ $data = $result['data'];
for($i = 0; $i < $batchNum; $i++)
{
- if(!empty($data->titles[$i]) and empty($data->openedBuilds[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->openedBuild)));
+ if(!empty($data->title[$i]) and empty($data->openedBuilds[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->bug->openedBuild)));
}
/* Get pairs(moduleID => moduleOwner) for bug. */
@@ -102,27 +104,36 @@ class bugModel extends model
$browser = '';
for($i = 0; $i < $batchNum; $i++)
{
- if(empty($data->titles[$i])) continue;
-
if($data->modules[$i] != 'ditto') $module = (int)$data->modules[$i];
if($data->projects[$i] != 'ditto') $project = (int)$data->projects[$i];
if($data->types[$i] != 'ditto') $type = $data->types[$i];
if($data->oses[$i] != 'ditto') $os = $data->oses[$i];
if($data->browsers[$i] != 'ditto') $browser = $data->browsers[$i];
+ $data->modules[$i] = (int)$module;
+ $data->projects[$i] = (int)$project;
+ $data->types[$i] = $type;
+ $data->oses[$i] = $os;
+ $data->browsers[$i] = $browser;
+ }
+
+ for($i = 0; $i < $batchNum; $i++)
+ {
+ if(empty($data->title[$i])) continue;
+
$bug = new stdClass();
$bug->openedBy = $this->app->user->account;
$bug->openedDate = $now;
$bug->product = $productID;
- $bug->module = $module;
- $bug->project = $project;
+ $bug->module = $data->modules[$i];
+ $bug->project = $data->projects[$i];
$bug->openedBuild = implode(',', $data->openedBuilds[$i]);
- $bug->title = $data->titles[$i];
+ $bug->title = $data->title[$i];
$bug->steps = nl2br($data->stepses[$i]);
- $bug->type = $type;
+ $bug->type = $data->types[$i];
$bug->severity = $data->severities[$i];
- $bug->os = $os;
- $bug->browser = $browser;
+ $bug->os = $data->oses[$i];
+ $bug->browser = $data->browsers[$i];
if(!empty($moduleOwners[$bug->module]))
{
diff --git a/module/bug/view/batchcreate.html.php b/module/bug/view/batchcreate.html.php
index cdde551c78..12fe2fc6bf 100644
--- a/module/bug/view/batchcreate.html.php
+++ b/module/bug/view/batchcreate.html.php
@@ -57,7 +57,7 @@
|
|
|
- |
+ |
|
diff --git a/module/common/lang/en.php b/module/common/lang/en.php
index af48deb4e3..65ee2d5007 100644
--- a/module/common/lang/en.php
+++ b/module/common/lang/en.php
@@ -61,6 +61,7 @@ $lang->addFiles = 'Add Files';
$lang->files = 'Files ';
$lang->pasteText = 'Paste text';
$lang->timeout = 'Timed out, please check the network, or retry!';
+$lang->duplicate = '%s has the same title';
$lang->unfold = '+';
$lang->fold = '-';
diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php
index 8a58d8a6bc..6a1a6062d6 100644
--- a/module/common/lang/zh-cn.php
+++ b/module/common/lang/zh-cn.php
@@ -61,6 +61,7 @@ $lang->addFiles = '上传了附件 ';
$lang->files = '附件 ';
$lang->pasteText = '粘贴文本 ';
$lang->timeout = '连接超时,请检查网络环境,或重试!';
+$lang->duplicate = '已有相同标题的%s';
$lang->unfold = '+';
$lang->fold = '-';
diff --git a/module/common/model.php b/module/common/model.php
index ccd093e2c3..06f097017f 100644
--- a/module/common/model.php
+++ b/module/common/model.php
@@ -741,45 +741,39 @@ class commonModel extends model
}
/**
- * Check repeat for story,task,bug,case,doc.
+ * Remove duplicate for story,task,bug,case,doc.
*
- * @param string $type
- * @param string $mode
- * @param string $title
- * @param string $condition
+ * @param string $type e.g. story task bug case doc.
+ * @param array|object $data
+ * @param string $condition
* @access public
- * @return bool|array
+ * @return array
*/
- public function checkRepeat($type, $mode = 'check', $title = '', $condition = '')
+ public function removeDuplicate($type, $data = '', $condition = '')
{
- $table = $this->config->objectTables[$type];
- $field = $type == 'task' ? 'name' : 'title';
- $date = date(DT_DATETIME1, time() - 1 * 60);
+ $table = $this->config->objectTables[$type];
+ $titleField = $type == 'task' ? 'name' : 'title';
+ $date = date(DT_DATETIME1, time() - $this->config->duplicateTime * 60);
+ $dateField = $type == 'doc' ? 'addedDate' : 'openedDate';
+ $titles = $data->$titleField;
- if($mode == 'check' and empty($title)) return false;
- if($mode == 'check')
+ if(empty($titles)) return false;
+ $duplicate = $this->dao->select("id,$titleField")->from($table)
+ ->where('deleted')->eq(0)
+ ->andWhere($titleField)->in($titles)
+ ->andWhere($dateField)->ge($date)->fi()
+ ->beginIF($condition)->andWhere($condition)->fi()
+ ->fetchPairs();
+
+ if($duplicate and is_string($titles)) return array('stop' => true, 'duplicate' => key($duplicate));
+ if($duplicate and is_array($titles))
{
- $repeatObject = $this->dao->select('*')->from($table)
- ->where('deleted')->eq(0)
- ->andWhere($field)->eq($title)
- ->beginIF($type == 'doc')->andWhere('addedDate')->ge($date)->fi()
- ->beginIF($type != 'doc')->andWhere('openedDate')->ge($date)->fi()
- ->beginIF($condition)->andWhere($condition)->fi()
- ->fetch();
-
- if($repeatObject) return $repeatObject->id;
- return false;
+ foreach($titles as $i => $title)
+ {
+ if(in_array($title, $duplicate)) unset($titles[$i]);
+ }
+ $data->$titleField = $titles;
}
- elseif($mode == 'get')
- {
- return $this->dao->select("id,$field")->from($table)
- ->where('deleted')->eq(0)
- ->beginIF($type == 'doc')->andWhere('addedDate')->ge($date)->fi()
- ->beginIF($type != 'doc')->andWhere('openedDate')->ge($date)->fi()
- ->beginIF($condition)->andWhere($condition)->fi()
- ->fetchPairs();
- }
-
- return false;
+ return array('stop' => false, 'data' => $data);
}
}
diff --git a/module/doc/control.php b/module/doc/control.php
index eeaf16dbb7..59a9a4a955 100644
--- a/module/doc/control.php
+++ b/module/doc/control.php
@@ -253,7 +253,11 @@ class doc extends control
if(!$docResult or dao::isError()) die(js::error(dao::getError()));
$docID = $docResult['id'];
- if($docResult['status'] == 'existed') die(js::locate($this->createLink('doc', 'view', "docID=$docID"), 'parent'));
+ if($docResult['status'] == 'exists')
+ {
+ echo js::alert(sprintf($this->lang->duplicate, $this->lang->doc->common));
+ die(js::locate($this->createLink('doc', 'view', "docID=$docID"), 'parent'));
+ }
$this->action->create('doc', $docID, 'Created');
if($from == 'product') $link = $this->createLink('product', 'doc', "productID={$this->post->product}");
diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php
index 627de04275..e259f678e5 100644
--- a/module/doc/lang/zh-cn.php
+++ b/module/doc/lang/zh-cn.php
@@ -10,7 +10,7 @@
* @link http://www.zentao.net
*/
/* 字段列表。*/
-$lang->doc->common = '文档视图';
+$lang->doc->common = '文档';
$lang->doc->id = '文档编号';
$lang->doc->product = '所属产品';
$lang->doc->project = '所属项目';
@@ -65,7 +65,7 @@ $lang->doc->types['url'] = '链接';
$lang->doc->types['text'] = '网页';
$lang->doc->confirmDelete = "您确定删除该文档吗?";
-$lang->doc->confirmDeleteLib = " 您确定删除该文档库吗?";
+$lang->doc->confirmDeleteLib = "您确定删除该文档库吗?";
$lang->doc->errorEditSystemDoc = "系统文档库无需修改。";
$lang->doc->placeholder = new stdclass();
diff --git a/module/doc/model.php b/module/doc/model.php
index a9bd48f81c..8a89cc835e 100644
--- a/module/doc/model.php
+++ b/module/doc/model.php
@@ -190,8 +190,8 @@ class docModel extends model
->get();
$condition = "lib = '$doc->lib' AND module = $doc->module";
- $docID = $this->loadModel('common')->checkRepeat('doc', 'check', $doc->title, $condition);
- if($docID) return array('status' => 'existed', 'id' => $docID);
+ $result = $this->loadModel('common')->removeDuplicate('doc', $doc, $condition);
+ if($result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']);
$this->dao->insert(TABLE_DOC)
->data($doc)
diff --git a/module/story/control.php b/module/story/control.php
index ff027fa5cd..8003459f3d 100644
--- a/module/story/control.php
+++ b/module/story/control.php
@@ -51,8 +51,9 @@ class story extends control
}
$storyID = $storyResult['id'];
- if($storyResult['status'] == 'existed')
+ if($storyResult['status'] == 'exists')
{
+ $response['message'] = sprintf($this->lang->duplicate, $this->lang->story->common);
if($projectID == 0)
{
$response['locate'] = $this->createLink('story', 'view', "storyID={$storyID}");
diff --git a/module/story/model.php b/module/story/model.php
index 561bfa5aae..07257db55e 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -138,8 +138,8 @@ class storyModel extends model
->get();
/* Check repeat story. */
- $storyID = $this->loadModel('common')->checkRepeat('story', 'check', $story->title, "product={$story->product}");
- if($storyID) return array('status' => 'existed', 'id' => $storyID);
+ $result = $this->loadModel('common')->removeDuplicate('story', $story, "product={$story->product}");
+ if($result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']);
$this->dao->insert(TABLE_STORY)->data($story)->autoCheck()->batchCheck($this->config->story->create->requiredFields, 'notempty')->exec();
if(!dao::isError())
@@ -210,18 +210,30 @@ class storyModel extends model
*/
public function batchCreate($productID = 0)
{
- $now = helper::now();
- $stories = fixer::input('post')->get();
- $batchNum = count(reset($stories));
- $latestStories = $this->loadModel('common')->checkRepeat('story', 'get', '', "product={$productID}");
+ $now = helper::now();
+ $stories = fixer::input('post')->get();
+ $batchNum = count(reset($stories));
+
+ $result = $this->loadModel('common')->removeDuplicate('story', $stories, "product={$productID}");
+ $stories = $result['data'];
+
+ $module = 0;
+ $plan = 0;
+ for($i = 0; $i < $batchNum; $i++)
+ {
+ $module = $stories->module[$i] == 'same' ? $module : $stories->module[$i];
+ $plan = $stories->plan[$i] == 'same' ? $plan : $stories->plan[$i];
+ $stories->module[$i] = (int)$module;
+ $stories->plan[$i] = (int)$plan;
+ }
for($i = 0; $i < $batchNum; $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]->module = $stories->module[$i];
+ $data[$i]->plan = $stories->plan[$i];
$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;
diff --git a/module/task/control.php b/module/task/control.php
index 74de17cc46..26d186b0bf 100644
--- a/module/task/control.php
+++ b/module/task/control.php
@@ -76,12 +76,24 @@ class task extends control
$this->send($response);
}
+ /* if the count of tasksID is 1 then check exists. */
+ if(count($tasksID) == 1)
+ {
+ $taskID = current($tasksID);
+ if($taskID['status'] == 'exists')
+ {
+ $response['locate'] = $this->createLink('task', 'view', "taskID={$taskID['id']}");
+ $response['message'] = sprintf($this->lang->duplicate, $this->lang->task->common);
+ $this->send($response);
+ }
+ }
+
/* Create actions. */
$this->loadModel('action');
foreach($tasksID as $taskID)
{
- /* if status is existed then this task has existed not new create. */
- if($taskID['status'] == 'existed') continue;
+ /* if status is exists then this task has exists not new create. */
+ if($taskID['status'] == 'exists') continue;
$taskID = $taskID['id'];
$actionID = $this->action->create('task', $taskID, 'Opened', '');
diff --git a/module/task/model.php b/module/task/model.php
index d43df45b96..55f81d5758 100644
--- a/module/task/model.php
+++ b/module/task/model.php
@@ -22,9 +22,8 @@ class taskModel extends model
*/
public function create($projectID)
{
- $tasksID = array();
- $taskFile = '';
- $latestTasks = $this->loadModel('common')->checkRepeat('task', 'get', '', "project=$projectID");
+ $tasksID = array();
+ $taskFile = '';
foreach($this->post->assignedTo as $assignedTo)
{
if($this->post->type == 'affair' and empty($assignedTo)) continue;
@@ -46,11 +45,15 @@ class taskModel extends model
if($assignedTo) $task->assignedDate = helper::now();
- /* Check repeat task. */
- if($latestTasks and $taskID = array_search($task->name, $latestTasks))
+ /* Check duplicate task. */
+ if($task->type != 'affair')
{
- $tasksID[$assignedTo] = array('status' => 'existed', 'id' => $taskID);
- continue;
+ $result = $this->loadModel('common')->removeDuplicate('task', $task, "project=$projectID");
+ if($result['stop'])
+ {
+ $tasksID[$assignedTo] = array('status' => 'exists', 'id' => $result['duplicate']);
+ continue;
+ }
}
$this->dao->insert(TABLE_TASK)->data($task)
@@ -95,11 +98,13 @@ class taskModel extends model
public function batchCreate($projectID)
{
$this->loadModel('action');
- $now = helper::now();
- $mails = array();
- $tasks = fixer::input('post')->get();
- $batchNum = count(reset($tasks));
- $latestTasks = $this->loadModel('common')->checkRepeat('task', 'get', '', "project=$projectID");
+ $now = helper::now();
+ $mails = array();
+ $tasks = fixer::input('post')->get();
+ $batchNum = count(reset($tasks));
+
+ $result = $this->loadModel('common')->removeDuplicate('task', $tasks, "project=$projectID");
+ $tasks = $result['data'];
/* check estimate. */
for($i = 0; $i < $batchNum; $i++)
@@ -110,15 +115,33 @@ class taskModel extends model
}
if(!empty($tasks->name[$i]) and empty($tasks->type[$i]))die(js::alert(sprintf($this->lang->error->notempty, $this->lang->task->type)));
}
+
+ $story = 0;
+ $module = 0;
+ $type = '';
+ $assignedTo = '';
+ for($i = 0; $i < $batchNum; $i++)
+ {
+ $story = $tasks->story[$i] == 'ditto' ? $story : $tasks->story[$i];
+ $module = $tasks->module[$i] == 'ditto' ? $module : $tasks->module[$i];
+ $type = $tasks->type[$i] == 'ditto' ? $type : $tasks->type[$i];
+ $assignedTo = $tasks->assignedTo[$i] == 'ditto' ? $assignedTo: $tasks->assignedTo[$i];
+
+ $tasks->story[$i] = (int)$story;
+ $tasks->module[$i] = (int)$module;
+ $tasks->type[$i] = $type;
+ $tasks->assignedTo[$i] = $assignedTo;
+ }
+
for($i = 0; $i < $batchNum; $i++)
{
if(empty($tasks->name[$i])) continue;
$data[$i] = new stdclass();
- $data[$i]->story = $tasks->story[$i] == 'ditto' ? (isset($data[$i-1]) ? $data[$i-1]->story : 0) : ($tasks->story[$i] ? $tasks->story[$i] : 0);
- $data[$i]->type = $tasks->type[$i] == 'ditto' ? (isset($data[$i-1]) ? $data[$i-1]->type : 0) : $tasks->type[$i];
- $data[$i]->module = $tasks->module[$i] == 'ditto' ? (isset($data[$i-1]) ? $data[$i-1]->module : 0) : $tasks->module[$i];
- $data[$i]->assignedTo = $tasks->assignedTo[$i] == 'ditto' ? (isset($data[$i-1]) ? $data[$i-1]->assignedTo : 0) : $tasks->assignedTo[$i];
+ $data[$i]->story = $tasks->story[$i];
+ $data[$i]->type = $tasks->type[$i];
+ $data[$i]->module = $tasks->module[$i];
+ $data[$i]->assignedTo = $tasks->assignedTo[$i];
$data[$i]->name = $tasks->name[$i];
$data[$i]->desc = nl2br($tasks->desc[$i]);
$data[$i]->pri = $tasks->pri[$i];
diff --git a/module/testcase/control.php b/module/testcase/control.php
index eae794fd9e..91f2994d55 100644
--- a/module/testcase/control.php
+++ b/module/testcase/control.php
@@ -235,9 +235,10 @@ class testcase extends control
}
$caseID = $caseResult['id'];
- if($caseResult['status'] == 'existed')
+ if($caseResult['status'] == 'exists')
{
- $response['locate'] = $this->createLink('testcase', 'view', "caseID=$caseID");
+ $response['message'] = sprintf($this->lang->duplicate, $this->lang->testcase->common);
+ $response['locate'] = $this->createLink('testcase', 'view', "caseID=$caseID");
$this->send($response);
}
diff --git a/module/testcase/lang/zh-cn.php b/module/testcase/lang/zh-cn.php
index a19d664b69..f6d5b94a72 100644
--- a/module/testcase/lang/zh-cn.php
+++ b/module/testcase/lang/zh-cn.php
@@ -52,7 +52,7 @@ $lang->testcase->stepID = '编号';
$lang->testcase->stepDesc = '步骤';
$lang->testcase->stepExpect = '预期';
-$lang->testcase->common = '用例管理';
+$lang->testcase->common = '用例';
$lang->testcase->index = "用例管理首页";
$lang->testcase->create = "建用例";
$lang->testcase->batchCreate = "批量添加";
diff --git a/module/testcase/model.php b/module/testcase/model.php
index 8abaacac19..9036003ab2 100644
--- a/module/testcase/model.php
+++ b/module/testcase/model.php
@@ -54,8 +54,8 @@ class testcaseModel extends model
->join('stage', ',')
->get();
- $caseID = $this->loadModel('common')->checkRepeat('case', 'check', $case->title, "product={$case->product}");
- if($caseID) return array('status' => 'existed', 'id' => $caseID);
+ $result = $this->loadModel('common')->removeDuplicate('case', $case, "product={$case->product}");
+ if($result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']);
$this->dao->insert(TABLE_CASE)->data($case)->autoCheck()->batchCheck($this->config->testcase->create->requiredFields, 'notempty')->exec();
if(!$this->dao->isError())
@@ -89,21 +89,37 @@ class testcaseModel extends model
$now = helper::now();
$cases = fixer::input('post')->get();
$batchNum = count(reset($cases));
- $latestCases = $this->loadModel('common')->checkRepeat('case', 'get', '', "product=$productID");
+
+ $result = $this->loadModel('common')->removeDuplicate('case', $cases, "product=$productID");
+ $cases = $result['data'];
for($i = 0; $i < $batchNum; $i++)
{
if(!empty($cases->title[$i]) and empty($cases->type[$i])) die(js::alert(sprintf($this->lang->error->notempty, $this->lang->testcase->type)));
}
+
+ $module = 0;
+ $story = 0;
+ $type = '';
+ for($i = 0; $i < $batchNum; $i++)
+ {
+ $module = $cases->module[$i] == 'same' ? $module : $cases->module[$i];
+ $story = $cases->story[$i] == 'same' ? $story : $cases->story[$i];
+ $type = $cases->type[$i] == 'same' ? $type : $cases->type[$i];
+ $cases->module[$i] = (int)$module;
+ $cases->story[$i] = (int)$story;
+ $cases->type[$i] = $type;
+ }
+
for($i = 0; $i < $batchNum; $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 = $storyID ? $storyID : ($cases->story[$i] == 'same' ? ($i == 0 ? 0 : $data[$i-1]->story) : $cases->story[$i]);
+ $data[$i]->module = $cases->module[$i];
+ $data[$i]->type = $cases->type[$i];
+ $data[$i]->story = $storyID ? $storyID : $cases->story[$i];
$data[$i]->title = $cases->title[$i];
$data[$i]->openedBy = $this->app->user->account;
$data[$i]->openedDate = $now;