model.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /**
  3. * The model file of test suite module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chunsheng Wang <chunsheng@cnezsoft.com>
  8. * @package testsuite
  9. * @link https://www.zentao.net
  10. */
  11. ?>
  12. <?php
  13. class testsuiteModel extends model
  14. {
  15. /**
  16. * 创建一个测试套件。
  17. * Create a test suite.
  18. *
  19. * @param object $suite
  20. * @access public
  21. * @return bool|int
  22. */
  23. public function create($suite)
  24. {
  25. $this->dao->insert(TABLE_TESTSUITE)->data($suite)
  26. ->batchcheck($this->config->testsuite->create->requiredFields, 'notempty')
  27. ->checkFlow()
  28. ->exec();
  29. if(dao::isError()) return false;
  30. $suiteID = $this->dao->lastInsertID();
  31. $this->loadModel('action')->create('testsuite', $suiteID, 'opened');
  32. return $suiteID;
  33. }
  34. /**
  35. * 获取一个产品下的测试套件。
  36. * Get test suites of a product.
  37. *
  38. * @param int|array $productID
  39. * @param string $orderBy
  40. * @param object $pager
  41. * @param string $param
  42. * @access public
  43. * @return array
  44. */
  45. public function getSuites($productID, $orderBy = 'id_desc', $pager = null, $param = '')
  46. {
  47. return $this->dao->select('*')->from(TABLE_TESTSUITE)
  48. ->where('product')->in($productID)
  49. ->beginIF($this->lang->navGroup->testsuite != 'qa')->andWhere('project')->eq($this->session->project)->fi()
  50. ->andWhere('deleted')->eq('0')
  51. ->andWhere('`type`', true)->eq('public')
  52. ->orWhere('(`type`')->eq('private')
  53. ->andWhere('`addedBy`')->eq($this->app->user->account)
  54. ->markRight(2)
  55. ->beginIF(strpos($param, 'review') !== false)->andWhere("FIND_IN_SET('{$this->app->user->account}', `reviewers`)")->fi()
  56. ->orderBy($orderBy)
  57. ->page($pager)
  58. ->fetchAll('id', false);
  59. }
  60. /**
  61. * 获取一个产品下的测试套件对。
  62. * Get test suites pairs of a product.
  63. *
  64. * @param int|array $productID
  65. * @access public
  66. * @return array
  67. */
  68. public function getSuitePairs($productID)
  69. {
  70. return $this->dao->select('id, name')->from(TABLE_TESTSUITE)
  71. ->where('product')->in($productID)
  72. ->beginIF($this->lang->navGroup->testsuite != 'qa')->andWhere('project')->eq($this->session->project)->fi()
  73. ->andWhere('deleted')->eq('0')
  74. ->andWhere("(`type` = 'public' OR (`type` = 'private' AND `addedBy` = '{$this->app->user->account}'))")
  75. ->orderBy('id_desc')
  76. ->fetchPairs();
  77. }
  78. /**
  79. * 获取单元测试的套件。
  80. * Get suites of unit test.
  81. *
  82. * @param int $productID
  83. * @param string $orderBy
  84. * @access public
  85. * @return array
  86. */
  87. public function getUnitSuites($productID, $orderBy = 'id_desc')
  88. {
  89. return $this->dao->select('*')->from(TABLE_TESTSUITE)
  90. ->where('product')->eq($productID)
  91. ->andWhere('deleted')->eq('0')
  92. ->andWhere('type')->eq('unit')
  93. ->orderBy($orderBy)
  94. ->fetchAll('id', false);
  95. }
  96. /**
  97. * 通过id获取测试套件的详情。
  98. * Get test suite info by id.
  99. *
  100. * @param int $suiteID
  101. * @param bool $setImgSize
  102. * @access public
  103. * @return object|bool
  104. */
  105. public function getById($suiteID, $setImgSize = false)
  106. {
  107. $suite = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('id')->eq((int)$suiteID)->fetch();
  108. if(!$suite) return false;
  109. $suite = $this->loadModel('file')->replaceImgURL($suite, 'desc');
  110. if($setImgSize) $suite->desc = $this->file->setImgSize($suite->desc);
  111. return $suite;
  112. }
  113. /**
  114. * 更新一个测试套件。
  115. * Update a test suite.
  116. *
  117. * @param object $suite
  118. * @param string $uid
  119. * @access public
  120. * @return array|bool
  121. */
  122. public function update($suite, $uid)
  123. {
  124. $oldSuite = $this->dao->select('*')->from(TABLE_TESTSUITE)->where('id')->eq((int)$suite->id)->fetch();
  125. $suite = $this->loadModel('file')->processImgURL($suite, $this->config->testsuite->editor->edit['id'], $uid);
  126. $this->dao->update(TABLE_TESTSUITE)->data($suite)
  127. ->autoCheck()
  128. ->batchcheck($this->config->testsuite->edit->requiredFields, 'notempty')
  129. ->checkFlow()
  130. ->where('id')->eq((int)$suite->id)
  131. ->exec();
  132. if(dao::isError()) return false;
  133. $this->file->updateObjectID($uid, $suite->id, 'testsuite');
  134. return common::createChanges($oldSuite, $suite);
  135. }
  136. /**
  137. * 关联测试用例。
  138. * Link cases.
  139. *
  140. * @param int $suiteID
  141. * @param array $cases
  142. * @param array $versions
  143. * @access public
  144. * @return bool
  145. */
  146. public function linkCase($suiteID, $cases, $versions)
  147. {
  148. if(empty($cases)) return false;
  149. $suiteCase = new stdclass();
  150. $suiteCase->suite = $suiteID;
  151. foreach($cases as $case)
  152. {
  153. $suiteCase->case = $case;
  154. $suiteCase->version = zget($versions, $case, 0);
  155. $this->dao->replace(TABLE_SUITECASE)->data($suiteCase)->exec();
  156. }
  157. return !dao::isError();
  158. }
  159. /**
  160. * 获取套件下关联的测试用例。
  161. * Get linked cases of the suite.
  162. *
  163. * @param int $suiteID
  164. * @param string $orderBy
  165. * @param object $pager
  166. * @param bool $append
  167. * @access public
  168. * @return array
  169. */
  170. public function getLinkedCases($suiteID, $orderBy = 'id_desc', $pager = null, $append = true)
  171. {
  172. $suite = $this->getById($suiteID);
  173. if(!$suite) return array();
  174. $cases = $this->dao->select('t1.*, t2.version AS caseVersion, t2.suite, t3.title AS caseTitle')->from(TABLE_CASE)->alias('t1')
  175. ->leftJoin(TABLE_SUITECASE)->alias('t2')->on('t1.id=t2.case')
  176. ->leftJoin(TABLE_CASESPEC)->alias('t3')->on('t1.id=t3.case AND t2.version=t3.version')
  177. ->where('t2.suite')->eq($suiteID)
  178. ->beginIF($this->lang->navGroup->testsuite != 'qa')->andWhere('t1.project')->eq($this->session->project)->fi()
  179. ->andWhere('t1.product')->eq($suite->product)
  180. ->andWhere('t1.deleted')->eq('0')
  181. ->orderBy($orderBy)
  182. ->page($pager)
  183. ->fetchAll('id', false);
  184. foreach($cases as $case)
  185. {
  186. if(empty($case->caseTitle)) $case->caseTitle = $case->title;
  187. }
  188. $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'testcase', false);
  189. if(!$append) return $cases;
  190. return $this->loadModel('testcase')->appendData($cases);
  191. }
  192. /**
  193. * 获取套件下关联的测试用例对。
  194. * Get linked cases pairs of the suite.
  195. *
  196. * @param int $suiteID
  197. * @access public
  198. * @return array
  199. */
  200. public function getLinkedCasePairs($suiteID)
  201. {
  202. $suite = $this->getById($suiteID);
  203. if(!$suite) return array();
  204. return $this->dao->select('t1.id, t1.title')->from(TABLE_CASE)->alias('t1')
  205. ->leftJoin(TABLE_SUITECASE)->alias('t2')->on('t1.id=t2.case')
  206. ->where('t2.suite')->eq($suiteID)
  207. ->beginIF($this->lang->navGroup->testsuite != 'qa')->andWhere('t1.project')->eq($this->session->project)->fi()
  208. ->andWhere('t1.product')->eq($suite->product)
  209. ->andWhere('t1.deleted')->eq('0')
  210. ->orderBy('id_desc')
  211. ->fetchPairs('id');
  212. }
  213. /**
  214. * 获取套件下未关联的测试用例。
  215. * Get unlinked cases for suite.
  216. *
  217. * @param object $suite
  218. * @param string $browseType
  219. * @param int $param
  220. * @param object $pager
  221. * @access public
  222. * @return array
  223. */
  224. public function getUnlinkedCases($suite, $browseType = 'all', $param = 0, $pager = null)
  225. {
  226. if($this->session->testsuiteQuery == false) $this->session->set('testsuiteQuery', ' 1 = 1');
  227. if($param)
  228. {
  229. $query = $this->loadModel('search')->getQuery($param);
  230. if($query)
  231. {
  232. $this->session->set('testsuiteQuery', $query->sql);
  233. $this->session->set('testsuiteForm', $query->form);
  234. }
  235. }
  236. $query = $browseType == 'bySearch' ? $this->session->testsuiteQuery : ' 1 = 1';
  237. $allProduct = "`product` = 'all'";
  238. if(strpos($query, '`product` =') === false) $query .= " AND `product` = {$suite->product}";
  239. if(strpos($query, $allProduct) !== false) $query = str_replace($allProduct, '1', $query);
  240. $linkedCases = $this->getLinkedCases($suite->id, 'id_desc', null, $append = false);
  241. return $this->dao->select('*')->from(TABLE_CASE)
  242. ->where($query)
  243. ->beginIF($linkedCases)->andWhere('id')->notIN(array_keys($linkedCases))->fi()
  244. ->beginIF($this->lang->navGroup->testsuite != 'qa')->andWhere('project')->eq($this->session->project)->fi()
  245. ->andWhere('deleted')->eq('0')
  246. ->orderBy('id desc')
  247. ->page($pager)
  248. ->fetchAll('id', false);
  249. }
  250. /**
  251. * 判断操作是否可以点击。
  252. * Judge an action is clickable or not.
  253. *
  254. * @param object $report
  255. * @param string $action
  256. * @access public
  257. * @return bool
  258. */
  259. public function isClickable($report, $action)
  260. {
  261. if($action == 'confirmCaseChange') return isset($report->caseVersion) && $report->version > $report->caseVersion;
  262. return common::hasPriv('testsuite', $action);
  263. }
  264. /**
  265. * 移除一个套件下的所有用例。
  266. * Remove all use cases under a suite.
  267. *
  268. * @param array $cases
  269. * @param int $suiteID
  270. * @access public
  271. * @return void
  272. */
  273. public function deleteCaseBySuiteID($cases, $suiteID)
  274. {
  275. return $this->dao->delete()->from(TABLE_SUITECASE)->where('`case`')->in($cases)->andWhere('`suite`')->eq($suiteID)->exec();
  276. }
  277. /**
  278. * 获取产品下用例关联的需求
  279. * Get case stories by productID.
  280. *
  281. * @param int $productID
  282. * @access public
  283. * @return array
  284. */
  285. public function getCaseLinkedStories($productID)
  286. {
  287. return $this->dao->select('t1.story, t2.title')->from(TABLE_CASE)->alias('t1')
  288. ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id')
  289. ->where('t1.product')->eq($productID)
  290. ->andWhere('t1.deleted')->eq('0')
  291. ->andWhere('t1.story')->ne(0)
  292. ->fetchPairs();
  293. }
  294. }