From e1c7f9ddff34c085cfcbcc33aebd8eb670d5d9c7 Mon Sep 17 00:00:00 2001 From: wangyidong Date: Wed, 26 Aug 2015 10:48:11 +0800 Subject: [PATCH] * revert for task #2322. --- module/group/lang/resource.php | 6 + module/testcase/control.php | 229 ++++++++++++++++++++ module/testcase/css/batchedit.css | 0 module/testcase/js/batchcreate.js | 0 module/testcase/js/view.js | 0 module/testcase/model.php | 161 ++++++++++++++ module/testcase/view/caseheader.html.php | 6 + module/testcase/view/export.html.php | 0 module/testcase/view/exporttemplet.html.php | 49 +++++ module/testcase/view/import.html.php | 19 ++ module/testcase/view/showimport.html.php | 100 +++++++++ 11 files changed, 570 insertions(+) mode change 100755 => 100644 module/testcase/css/batchedit.css mode change 100755 => 100644 module/testcase/js/batchcreate.js mode change 100755 => 100644 module/testcase/js/view.js mode change 100755 => 100644 module/testcase/view/export.html.php create mode 100644 module/testcase/view/exporttemplet.html.php create mode 100644 module/testcase/view/import.html.php create mode 100644 module/testcase/view/showimport.html.php diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 5273d4ea0e..2b5b18fc3a 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -454,6 +454,9 @@ $lang->resource->testcase->batchEdit = 'batchEdit'; $lang->resource->testcase->delete = 'delete'; $lang->resource->testcase->batchDelete = 'batchDelete'; $lang->resource->testcase->export = 'export'; +$lang->resource->testcase->exportTemplet = 'exportTemplet'; +$lang->resource->testcase->import = 'import'; +$lang->resource->testcase->showImport = 'showImport'; $lang->resource->testcase->confirmChange = 'confirmChange'; $lang->resource->testcase->confirmStoryChange = 'confirmStoryChange'; @@ -998,6 +1001,9 @@ $lang->changelog['4.3.beta'][] = 'productplan-linkBug'; $lang->changelog['4.3.beta'][] = 'productplan-unlinkBug'; $lang->changelog['4.3.beta'][] = 'productplan-batchUnlinkBug'; $lang->changelog['4.3.beta'][] = 'bug-batchCreate'; +$lang->changelog['4.3.beta'][] = 'testcase-exportTemplet'; +$lang->changelog['4.3.beta'][] = 'testcase-import'; +$lang->changelog['4.3.beta'][] = 'testcase-showImport'; $lang->changelog['4.3.beta'][] = 'testcase-confirmChange'; $lang->changelog['4.3.beta'][] = 'mail-reset'; $lang->changelog['4.3.beta'][] = 'api-debug'; diff --git a/module/testcase/control.php b/module/testcase/control.php index 252697df08..dcc52c1492 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -840,4 +840,233 @@ class testcase extends control $this->display(); } + + /** + * Export templet + * + * @param int $productID + * @access public + * @return void + */ + public function exportTemplet($productID) + { + if($_POST) + { + $fields['module'] = $this->lang->testcase->module; + $fields['story'] = $this->lang->testcase->story; + $fields['title'] = $this->lang->testcase->title; + $fields['stepDesc'] = $this->lang->testcase->stepDesc; + $fields['stepExpect'] = $this->lang->testcase->stepExpect; + $fields['keywords'] = $this->lang->testcase->keywords; + $fields['type'] = $this->lang->testcase->type; + $fields['pri'] = $this->lang->testcase->pri; + $fields['stage'] = $this->lang->testcase->stage; + $fields['precondition'] = $this->lang->testcase->precondition; + $this->post->set('fields', $fields); + $this->post->set('kind', 'testcase'); + $this->post->set('rows', array()); + $this->post->set('extraNum', $this->post->num); + $this->post->set('fileName', 'templet'); + $this->fetch('file', 'export2csv', $_POST); + } + + $this->display(); + } + + /** + * Import csv + * + * @param int $productID + * @access public + * @return void + */ + public function import($productID) + { + if($_FILES) + { + $file = $this->loadModel('file')->getUpload('file'); + $file = $file[0]; + + $fc = file_get_contents($file['tmpname']); + if( $this->post->encode != "utf-8") + { + if(function_exists('mb_convert_encoding')) + { + $fc = @mb_convert_encoding($fc, 'utf-8', $this->post->encode); + } + elseif(function_exists('iconv')) + { + $fc = @iconv($this->post->encode, 'utf-8', $fc); + } + else + { + die(js::alert($this->lang->testcase->noFunction)); + } + } + file_put_contents($this->file->savePath . $file['pathname'], $fc); + + $fileName = $this->file->savePath . $file['pathname']; + $this->session->set('importFile', $fileName); + + die(js::locate(inlink('showImport', "productID=$productID"), 'parent.parent')); + } + $this->display(); + } + + /** + * Show import data + * + * @param int $productID + * @access public + * @return void + */ + public function showImport($productID) + { + if($_POST) + { + $this->testcase->createFromImport($productID); + die(js::locate(inlink('browse', "productID=$productID"), 'parent')); + } + + $this->testcase->setMenu($this->products, $productID); + + $file = $this->session->importFile; + $caseLang = $this->lang->testcase; + $caseConfig = $this->config->testcase; + $fields = explode(',', $caseConfig->exportFields); + $modules = $this->loadModel('tree')->getOptionMenu($productID, 'case'); + $stories = $this->loadModel('story')->getProductStoryPairs($productID); + foreach($fields as $key => $fieldName) + { + $fieldName = trim($fieldName); + $fields[$fieldName] = isset($caseLang->$fieldName) ? $caseLang->$fieldName : $fieldName; + unset($fields[$key]); + } + + $rows = $this->loadModel('file')->parseCSV($file); + $header = $rows[0]; + unset($rows[0]); + + foreach($header as $title) + { + $field = array_search($title, $fields); + if(!$field) continue; + $columnKey[] = $field; + } + if(empty($columnKey)) + { + echo js::alert($this->lang->testcase->errorEncode); + die(js::locate(inlink('browse', "productID=$productID"))); + } + + $endField = $field; + $caseData = array(); + $stepData = array(); + foreach($rows as $row => $data) + { + $case = new stdclass(); + foreach($columnKey as $key => $field) + { + if(!isset($data[$key])) continue; + $cellValue = $data[$key]; + if($field == 'story') + { + $case->$field = 0; + if(strrpos($cellValue, '(#') !== false) + { + $id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')'); + $case->$field = $id; + } + } + elseif($field == 'module') + { + $case->$field = 0; + if(strrpos($cellValue, '(#') !== false) + { + $id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')'); + $case->$field = $id; + } + } + elseif(in_array($field, $caseConfig->export->listFields)) + { + if($field == 'stage') + { + $stages = explode("\n", $cellValue); + foreach($stages as $stage) $case->stage[] = array_search($stage, $caseLang->{$field . 'List'}); + $case->stage = join(',', $case->stage); + } + else + { + $case->$field = array_search($cellValue, $caseLang->{$field . 'List'}); + } + } + elseif($field != 'stepDesc' and $field != 'stepExpect') + { + $case->$field = $cellValue; + } + else + { + $steps = explode("\n", $cellValue); + $stepKey = str_replace('step', '', strtolower($field)); + $caseStep = array(); + + foreach($steps as $step) + { + $step = trim($step); + if(empty($step)) continue; + if(preg_match('/^([0-9]+)([.、]{1})/U', $step, $out)) + { + $num = $out[1]; + $sign = $out[2]; + $signbit = $sign == '.' ? 1 : 3; + $step = trim(substr($step, strpos($step, $sign) + $signbit)); + if(!empty($step)) $caseStep[$num] = $step; + } + elseif(isset($num)) + { + $caseStep[$num] .= "\n" . $step; + } + else + { + if($field == 'stepDesc') + { + $num = 1; + $caseStep[$num] = $step; + } + if($field == 'stepExpect' and isset($stepData[$row]['desc'])) + { + end($stepData[$row]['desc']); + $num = key($stepData[$row]['desc']); + $caseStep[$num] = $step; + } + } + } + unset($num); + unset($sign); + $stepData[$row][$stepKey] = $caseStep; + } + } + + $caseData[$row] = $case; + unset($case); + } + + if(empty($caseData)) + { + echo js::alert($this->lang->error->noData); + die(js::locate($this->createLink('testcase', 'browse'))); + } + + $this->view->title = $this->lang->testcase->common . $this->lang->colon . $this->lang->testcase->showImport; + $this->view->position[] = $this->lang->testcase->showImport; + + $this->view->stories = $stories; + $this->view->modules = $modules; + $this->view->cases = $this->dao->select('id, module, story')->from(TABLE_CASE)->where('product')->eq($productID)->andWhere('deleted')->eq(0)->fetchAll('id'); + $this->view->caseData = $caseData; + $this->view->stepData = $stepData; + $this->view->productID = $productID; + $this->view->product = $this->products[$productID]; + $this->display(); + } } diff --git a/module/testcase/css/batchedit.css b/module/testcase/css/batchedit.css old mode 100755 new mode 100644 diff --git a/module/testcase/js/batchcreate.js b/module/testcase/js/batchcreate.js old mode 100755 new mode 100644 diff --git a/module/testcase/js/view.js b/module/testcase/js/view.js old mode 100755 new mode 100644 diff --git a/module/testcase/model.php b/module/testcase/model.php index 07ad3448d9..ec460a4df9 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -421,4 +421,165 @@ class testcaseModel extends model return true; } + + /** + * Create from import + * + * @param int $productID + * @access public + * @return void + */ + public function createFromImport($productID) + { + $this->loadModel('action'); + $this->loadModel('story'); + $this->loadModel('file'); + $now = helper::now(); + $data = fixer::input('post')->get(); + + if(!empty($_POST['id'])) + { + $oldSteps = $this->dao->select('t2.*')->from(TABLE_CASE)->alias('t1') + ->leftJoin(TABLE_CASESTEP)->alias('t2')->on('t1.id = t2.case') + ->where('t1.id')->in(($_POST['id'])) + ->andWhere('t1.product')->eq($productID) + ->andWhere('t1.version=t2.version') + ->orderBy('t2.id') + ->fetchGroup('case'); + $oldCases = $this->dao->select('*')->from(TABLE_CASE)->where('id')->in($_POST['id'])->fetchAll('id'); + } + + $cases = array(); + foreach($data->product as $key => $product) + { + $caseData = new stdclass(); + + $caseData->product = $product; + $caseData->module = $data->module[$key]; + $caseData->story = (int)$data->story[$key]; + $caseData->title = $data->title[$key]; + $caseData->pri = (int)$data->pri[$key]; + $caseData->type = $data->type[$key]; + $caseData->status = $data->status[$key]; + $caseData->stage = join(',', $data->stage[$key]); + $caseData->frequency = 1; + $caseData->precondition = $data->precondition[$key]; + + if(isset($this->config->testcase->create->requiredFields)) + { + $requiredFields = explode(',', $this->config->testcase->create->requiredFields); + foreach($requiredFields as $requiredField) + { + $requiredField = trim($requiredField); + if(empty($caseData->$requiredField)) die(js::alert(sprintf($this->lang->testcase->noRequire, $key, $this->lang->testcase->$requiredField))); + } + } + + $cases[$key] =$caseData; + } + + foreach($cases as $key => $caseData) + { + if(!empty($_POST['id'][$key])) + { + $caseID = $data->id[$key]; + $stepChanged = false; + $steps = array(); + $oldStep = isset($oldSteps[$caseID]) ? $oldSteps[$caseID] : array(); + $oldCase = $oldCases[$caseID]; + + /* Remove the empty setps in post. */ + $steps = array(); + if(isset($_POST['desc'][$key])) + { + foreach($this->post->desc[$key] as $id => $desc) + { + $desc = trim($desc); + if(empty($desc))continue; + $step = new stdclass(); + $step->desc = $desc; + $step->expect = trim($this->post->expect[$key][$id]); + + $steps[] = $step; + } + } + + /* If step count changed, case changed. */ + if((!$oldStep != !$steps) or (count($oldStep) != count($steps))) + { + $stepChanged = true; + } + else + { + /* Compare every step. */ + foreach($oldStep as $id => $oldStep) + { + if(trim($oldStep->desc) != trim($steps[$id]->desc) or trim($oldStep->expect) != $steps[$id]->expect) + { + $stepChanged = true; + break; + } + } + } + + $version = $stepChanged ? $oldCase->version + 1 : $oldCase->version; + $caseData->version = $version; + $changes = common::createChanges($oldCase, $caseData); + if(!$changes and !$stepChanged) continue; + + if($changes or $stepChanged) + { + $caseData->lastEditedBy = $this->app->user->account; + $caseData->lastEditedDate = $now; + $this->dao->update(TABLE_CASE)->data($caseData)->where('id')->eq($caseID)->autoCheck()->exec(); + if($stepChanged) + { + foreach($steps as $id => $step) + { + $step = (array)$step; + if(empty($step['desc'])) continue; + $stepData = new stdclass(); + $stepData->case = $caseID; + $stepData->version = $version; + $stepData->desc = htmlspecialchars($step['desc']); + $stepData->expect = htmlspecialchars($step['expect']); + $this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec(); + } + } + $oldCase->steps = $this->joinStep($oldStep); + $caseData->steps = $this->joinStep($steps); + $changes = common::createChanges($oldCase, $caseData); + $actionID = $this->action->create('case', $caseID, 'Edited'); + $this->action->logHistory($actionID, $changes); + } + } + else + { + $caseData->version = 1; + $caseData->openedBy = $this->app->user->account; + $caseData->openedDate = $now; + $this->dao->insert(TABLE_CASE)->data($caseData)->autoCheck()->exec(); + + if(!dao::isError()) + { + $caseID = $this->dao->lastInsertID(); + foreach($this->post->desc[$key] as $id => $desc) + { + $desc = trim($desc); + if(empty($desc)) continue; + $stepData = new stdclass(); + $stepData->case = $caseID; + $stepData->version = 1; + $stepData->desc = htmlspecialchars($desc); + $stepData->expect = htmlspecialchars($this->post->expect[$key][$id]); + $this->dao->insert(TABLE_CASESTEP)->data($stepData)->autoCheck()->exec(); + } + $this->action->create('case', $caseID, 'Opened'); + } + } + } + + unlink($this->session->importFile); + unset($_SESSION['importFile']); + } } diff --git a/module/testcase/view/caseheader.html.php b/module/testcase/view/caseheader.html.php index be613d7eaf..299231b280 100644 --- a/module/testcase/view/caseheader.html.php +++ b/module/testcase/view/caseheader.html.php @@ -37,10 +37,16 @@ $misc = common::hasPriv('testcase', 'export') ? "class='export'" : "class=disabled"; $link = common::hasPriv('testcase', 'export') ? $this->createLink('testcase', 'export', "productID=$productID&orderBy=$orderBy") : '#'; echo "
  • " . html::a($link, $lang->testcase->export, '', $misc) . "
  • "; + + $misc = common::hasPriv('testcase', 'exportTemplet') ? "class='export'" : "class=disabled"; + $link = common::hasPriv('testcase', 'exportTemplet') ? $this->createLink('testcase', 'exportTemplet', "productID=$productID") : '#'; + echo "
  • " . html::a($link, $lang->testcase->exportTemplet, '', $misc) . "
  • "; ?> + +
    +
    + icons['export']);?> + testcase->exportTemplet;?> +
    +
    + +
    + + + + + + +
    +
    + testcase->num;?> + +
    +
    + charsets[$this->cookie->lang], 'utf-8', "class='form-control'");?> + + +
    +
    + diff --git a/module/testcase/view/import.html.php b/module/testcase/view/import.html.php new file mode 100644 index 0000000000..00c7543f75 --- /dev/null +++ b/module/testcase/view/import.html.php @@ -0,0 +1,19 @@ + +
    +
    + + + + + + +
    + + + charsets[$this->cookie->lang], 'utf-8', "class='form-control'");?> + + +
    +
    +
    + diff --git a/module/testcase/view/showimport.html.php b/module/testcase/view/showimport.html.php new file mode 100644 index 0000000000..3ff2f7edbd --- /dev/null +++ b/module/testcase/view/showimport.html.php @@ -0,0 +1,100 @@ + + +
    + + + + + + + + + + + + + + + + $case):?> + + + + + + + + + + + + + + + + + + + +
    testcase->id?>testcase->title?>testcase->module?>testcase->story?>testcase->pri?>testcase->type?>testcase->status?>testcase->stage?>testcase->precondition?> + + + + + + + + +
    testcase->steps?>
    testcase->stepDesc?>testcase->stepExpect?>
    +
    + id)) + { + echo $case->id . html::hidden("id[$key]", $case->id); + } + else + { + echo $key . " {$lang->testcase->new}"; + } + echo html::hidden("product[$key]", $productID); + ?> + title, "class='form-control' style='margin-top:2px'")?>module) ? $case->module : (!empty($case->id) ? $cases[$case->id]->module : ''), "class='form-control chosen'")?>story) ? $case->story : (!empty($case->id) ? $cases[$case->id]->story : ''), "class='form-control chosen'")?>testcase->priList, isset($case->pri) ? $case->pri : (!empty($case->id) ? $cases[$case->id]->pri : ''), "class='form-control'")?>testcase->typeList, $case->type, "class='form-control'")?>testcase->statusList, isset($case->status) ? $case->status : '', "class='form-control'")?>testcase->stageList, isset($case->stage) ? $case->stage : '', "multiple='multiple' class='form-control chosen'")?>precondition) ? $case->precondition : "", "class='form-control'")?> + + + $desc):?> + + + + + +
    + +
    +
    + +