PageRenderTime 39ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/functions/treeMenu.inc.php

https://bitbucket.org/pfernandez/testlink1.9.6
PHP | 2261 lines | 1381 code | 319 blank | 561 comment | 218 complexity | a498daec9acd3fa114f8e86d6dcd8d56 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * TestLink Open Source Project - http://testlink.sourceforge.net/
  4. * This script is distributed under the GNU General Public License 2 or later.
  5. *
  6. * This file generates tree menu for test specification and test execution.
  7. *
  8. * @package TestLink
  9. * @author Martin Havlat
  10. * @copyright 2005-2009, TestLink community
  11. * @version CVS: $Id: treeMenu.inc.php,v 1.144 2010/08/21 13:38:25 asimon83 Exp $
  12. * @link http://www.teamst.org/index.php
  13. * @uses config.inc.php
  14. *
  15. * @internal Revisions:
  16. * 20100820 - asimon - refactoring for less redundant checks and better readibility of code
  17. * in generateExecTree()
  18. * 20100812 - franciscom - get_filtered_req_map() - BUGID 3671
  19. * 20100810 - asimon - added filtering by TC ID on prepareNode() and generateTestSpecTree()
  20. * 20100808 - asimon - generate_reqspec_tree() implemented to generate statically filtered
  21. * requirement specification tree, plus additional functions
  22. * get_filtered_req_map(), prepare_reqspec_treenode(),
  23. * render_reqspec_treenode()
  24. * 20100702 - asimon - fixed custom field filtering problem caused by
  25. * wrong array indexes and little logic errors
  26. * 20100701 - asimon - replaced is_null in renderTreeNode() by !isset
  27. * because of warnings in event log
  28. * 20100701 - asimon - added some additional isset() checks to avoid warnings
  29. * 20100628 - asimon - removal of constants from filter control class
  30. * 20160625 - asimon - refactoring for new filter features and BUGID 3516
  31. * 20100624 - asimon - CVS merge (experimental branch to HEAD)
  32. * 20100622 - asimon - refactoring of following functions for new filter classes:
  33. * generateExecTree, renderExecTreeNode(), prepareNode(),
  34. * generateTestSpecTree, renderTreeNode(), filter_by_*()
  35. * 20100611 - franciscom - renderExecTreeNode(), renderTreeNode() interface changes
  36. * generateExecTree() - interface changes and output changes
  37. * 20100602 - franciscom - extjs_renderExecTreeNodeOnOpen() - added 'tlNodeType'
  38. * 20100428 - asimon - BUGID 3301 and related:
  39. * added filtering by custom fields to generateTestSpecTree(),
  40. * added importance setting in prepareNode() because of
  41. * "undefined" error in event log,
  42. * added function filter_by_cfield_values()
  43. * which is used from generateTestSpecTree()
  44. * 20100417 - franciscom - BUGID 2498 - spec tree - filter by test case spec importance
  45. * 20100417 - franciscom - BUGID 3380 - execution tree - filter by test case execution type
  46. * 20100415 - franciscom - BUGID 2797 - filter by test case execution type
  47. * 20100202 - asimon - changes for filtering, BUGID 2455, BUGID 3026
  48. * added filter_by_* - functions, changed generateExecTree()
  49. * 20091212 - franciscom - prepareNode(), generateTestSpecTree() interface changes
  50. * added logic to do filtering on test spec for execution type
  51. *
  52. * 20090815 - franciscom - get_last_execution() call changes
  53. * 20090801 - franciscom - table prefix missed
  54. * 20090716 - franciscom - BUGID 2692
  55. * 20090328 - franciscom - BUGID 2299 - introduced on 20090308.
  56. * Added logic to remove Empty Top level test suites
  57. * (have neither test cases nor test suites inside) when applying
  58. * test case keyword filtering.
  59. * BUGID 2296
  60. * 20090308 - franciscom - generateTestSpecTree() - changes for EXTJS tree
  61. * 20090211 - franciscom - BUGID 2094
  62. * 20090202 - franciscom - minor changes to avoid BUGID 2009
  63. * 20090118 - franciscom - replaced multiple calls config_get('testcase_cfg')
  64. * added extjs_renderTestSpecTreeNodeOnOpen(), to allow filtering
  65. *
  66. */
  67. require_once(dirname(__FILE__)."/../../third_party/dBug/dBug.php");
  68. /**
  69. * strip potential newlines and other unwanted chars from strings
  70. * Mainly for stripping out newlines, carriage returns, and quotes that were
  71. * causing problems in javascript using jtree
  72. *
  73. * @param string $str
  74. * @return string string with the newlines removed
  75. */
  76. function filterString($str)
  77. {
  78. $str = str_replace(array("\n","\r"), array("",""), $str);
  79. $str = addslashes($str);
  80. $str = htmlspecialchars($str, ENT_QUOTES);
  81. return $str;
  82. }
  83. /**
  84. * generate data for tree menu of Test Specification
  85. *
  86. * @param boolean $ignore_inactive_testcases if all test case versions are inactive,
  87. * the test case will ignored.
  88. * @param array $exclude_branches map key=node_id
  89. *
  90. * @internal Revisions:
  91. * 20100810 - asimon - filtering by testcase ID
  92. * 20100428 - asimon - BUGID 3301, added filtering by custom fields
  93. * 20090328 - franciscom - BUGID 2299, that was generated during 20090308
  94. * trying to fix another not reported bug.
  95. * 20090308 - franciscom - changed arguments in str_ireplace() call
  96. * Due to bug in Test Spec tree when using Keywords filter
  97. * 20080501 - franciscom - keyword_id can be an array
  98. * 20071014 - franciscom - $bForPrinting
  99. * used to choose Javascript function
  100. * to call when clicking on a tree node
  101. * 20070922 - franciscom - interface changes added $tplan_id,
  102. * 20070217 - franciscom - added $exclude_branches
  103. * 20061105 - franciscom - added $ignore_inactive_testcases
  104. */
  105. function generateTestSpecTree(&$db,$tproject_id, $tproject_name,$linkto,$filters=null,$options=null)
  106. {
  107. $tables = tlObjectWithDB::getDBTables(array('tcversions','nodes_hierarchy'));
  108. $my = array();
  109. // 20100412 - franciscom
  110. // $my['options'] = array('forPrinting' => 0, 'hideTestCases' => 0,'getArguments' => '',
  111. // 'tc_action_enabled' => 1, 'ignore_inactive_testcases' => 0,
  112. // 'exclude_branches' => null, 'viewType' => 'testSpecTree');
  113. // $my['options'] = array('forPrinting' => 0, 'hideTestCases' => 0,
  114. // 'tc_action_enabled' => 1, 'ignore_inactive_testcases' => 0,
  115. // 'exclude_branches' => null, 'viewType' => 'testSpecTree');
  116. $my['options'] = array('forPrinting' => 0, 'hideTestCases' => 0,
  117. 'tc_action_enabled' => 1, 'ignore_inactive_testcases' => 0,
  118. 'viewType' => 'testSpecTree');
  119. // 20100412 - franciscom
  120. // testplan => only used if opetions['viewType'] == 'testSpecTreeForTestPlan'
  121. // 20100417 - franciscom - BUGID 2498
  122. $my['filters'] = array('keywords' => null, 'executionType' => null, 'importance' => null,
  123. 'testplan' => null, 'filter_tc_id' => null);
  124. $my['options'] = array_merge($my['options'], (array)$options);
  125. $my['filters'] = array_merge($my['filters'], (array)$filters);
  126. $treeMenu = new stdClass();
  127. $treeMenu->rootnode = null;
  128. $treeMenu->menustring = '';
  129. $resultsCfg = config_get('results');
  130. $showTestCaseID = config_get('treemenu_show_testcase_id');
  131. $glueChar = config_get('testcase_cfg')->glue_character;
  132. $menustring = null;
  133. $tproject_mgr = new testproject($db);
  134. $tree_manager = &$tproject_mgr->tree_manager;
  135. $tcase_node_type = $tree_manager->node_descr_id['testcase'];
  136. // BUGID 3301
  137. $tsuite_node_type = $tree_manager->node_descr_id['testsuite'];
  138. $hash_descr_id = $tree_manager->get_available_node_types();
  139. $hash_id_descr = array_flip($hash_descr_id);
  140. $status_descr_code=$resultsCfg['status_code'];
  141. $status_code_descr=$resultsCfg['code_status'];
  142. $decoding_hash=array('node_id_descr' => $hash_id_descr,
  143. 'status_descr_code' => $status_descr_code,
  144. 'status_code_descr' => $status_code_descr);
  145. $exclude_branches = isset($filters['filter_toplevel_testsuite'])
  146. && is_array($filters['filter_toplevel_testsuite']) ?
  147. $filters['filter_toplevel_testsuite'] : null;
  148. $tcase_prefix=$tproject_mgr->getTestCasePrefix($tproject_id) . $glueChar;
  149. $test_spec = $tproject_mgr->get_subtree($tproject_id,testproject::RECURSIVE_MODE,
  150. testproject::INCLUDE_TESTCASES, $exclude_branches);
  151. // Added root node for test specification -> testproject
  152. $test_spec['name'] = $tproject_name;
  153. $test_spec['id'] = $tproject_id;
  154. $test_spec['node_type_id'] = $hash_descr_id['testproject'];
  155. $map_node_tccount=array();
  156. $tplan_tcs=null;
  157. DEFINE('DONT_FILTER_BY_TESTER',0);
  158. DEFINE('DONT_FILTER_BY_EXEC_STATUS',null);
  159. if($test_spec)
  160. {
  161. $tck_map = null; // means no filter
  162. if(!is_null($my['filters']['filter_keywords']))
  163. {
  164. //$tck_map = $tproject_mgr->get_keywords_tcases($tproject_id,$my['filters']['keywords']->items,
  165. // $my['filters']['keywords']->type);
  166. $tck_map = $tproject_mgr->get_keywords_tcases($tproject_id,
  167. $my['filters']['filter_keywords'],
  168. $my['filters']['filter_keywords_filter_type']);
  169. if( is_null($tck_map) )
  170. {
  171. $tck_map=array(); // means filter everything
  172. }
  173. }
  174. // Important: prepareNode() will make changes to $test_spec like filtering by test case
  175. // keywords using $tck_map;
  176. $pnFilters = null;
  177. // $pnFilters['filter_testcase_name'] =
  178. // isset($my['filters']['filter_testcase_name']) ?
  179. // $my['filters']['filter_testcase_name'] : null;
  180. //
  181. // $pnFilters['filter_execution_type'] =
  182. // isset($my['filters']['filter_execution_type']) ?
  183. // $my['filters']['filter_execution_type'] : null;
  184. //
  185. // $pnFilters['filter_priority'] =
  186. // isset($my['filters']['filter_priority']) ?
  187. // $my['filters']['filter_priority'] : null;
  188. $keys2init = array('filter_testcase_name',
  189. 'filter_execution_type',
  190. 'filter_priority',
  191. 'filter_tc_id');
  192. foreach ($keys2init as $keyname) {
  193. $pnFilters[$keyname] = isset($my['filters'][$keyname]) ? $my['filters'][$keyname] : null;
  194. }
  195. $pnFilters['setting_testplan'] =
  196. $my['filters']['setting_testplan'];
  197. // BUGID 3301 - added filtering by custom field values
  198. if (isset($my['filters']['filter_custom_fields'])
  199. && isset($test_spec['childNodes'])) {
  200. $test_spec['childNodes'] = filter_by_cf_values($test_spec['childNodes'],
  201. $my['filters']['filter_custom_fields'],
  202. $db, $tsuite_node_type, $tcase_node_type);
  203. }
  204. // 20100412 - franciscom
  205. $pnOptions = array('hideTestCases' => $my['options']['hideTestCases'],
  206. 'viewType' => $my['options']['viewType'],
  207. 'ignoreInactiveTestCases' => $my['options']['ignore_inactive_testcases']);
  208. $testcase_counters = prepareNode($db,$test_spec,$decoding_hash,$map_node_tccount,$tck_map,
  209. $tplan_tcs,$pnFilters,$pnOptions);
  210. foreach($testcase_counters as $key => $value)
  211. {
  212. $test_spec[$key]=$testcase_counters[$key];
  213. }
  214. $menustring = renderTreeNode(1,$test_spec,$hash_id_descr,
  215. $my['options']['tc_action_enabled'],$linkto,$tcase_prefix,
  216. $my['options']['forPrinting'],$showTestCaseID);
  217. }
  218. $menustring ='';
  219. $treeMenu->rootnode = new stdClass();
  220. $treeMenu->rootnode->name = $test_spec['text'];
  221. $treeMenu->rootnode->id = $test_spec['id'];
  222. $treeMenu->rootnode->leaf = isset($test_spec['leaf']) ? $test_spec['leaf'] : false;
  223. $treeMenu->rootnode->text = $test_spec['text'];
  224. $treeMenu->rootnode->position = $test_spec['position'];
  225. $treeMenu->rootnode->href = $test_spec['href'];
  226. // Change key ('childNodes') to the one required by Ext JS tree.
  227. if(isset($test_spec['childNodes']))
  228. {
  229. $menustring = str_ireplace('childNodes', 'children', json_encode($test_spec['childNodes']));
  230. }
  231. // 20090328 - franciscom - BUGID 2299
  232. // More details about problem found on 20090308 and fixed IN WRONG WAY
  233. // TPROJECT
  234. // |______ TSA
  235. // |__ TC1
  236. // |__ TC2
  237. // |
  238. // |______ TSB
  239. // |______ TSC
  240. //
  241. // Define Keyword K1,K2
  242. //
  243. // NO TEST CASE HAS KEYWORD ASSIGNED
  244. // Filter by K1
  245. // Tree will show root that spins Forever
  246. // menustring before str_ireplace : [null,null]
  247. // menustring AFTER [null]
  248. //
  249. // Now fixed.
  250. //
  251. // Some minor fix to do
  252. // Il would be important exclude Top Level Test suites.
  253. //
  254. //
  255. // 20090308 - franciscom
  256. // Changed because found problem on:
  257. // Test Specification tree when applying Keyword filter using a keyword NOT PRESENT
  258. // in test cases => Tree root shows loading icon and spin never stops.
  259. //
  260. // Attention: do not know if in other situation this will generate a different bug
  261. //
  262. if(!is_null($menustring))
  263. {
  264. // Remove null elements (Ext JS tree do not like it ).
  265. // :null happens on -> "children":null,"text" that must become "children":[],"text"
  266. // $menustring = str_ireplace(array(':null',',null','null,'),array(':[]','',''), $menustring);
  267. $menustring = str_ireplace(array(':null',',null','null,','null'),array(':[]','','',''), $menustring);
  268. }
  269. $treeMenu->menustring = $menustring;
  270. return $treeMenu;
  271. }
  272. /**
  273. * Prepares a Node to be displayed in a navigation tree.
  274. * This function is used in the construction of:
  275. * - Test project specification -> we want ALL test cases defined in test project.
  276. * - Test execution -> we only want the test cases linked to a test plan.
  277. *
  278. * IMPORTANT:
  279. * when analising a container node (Test Suite) if it is empty and we have requested
  280. * some sort of filtering NODE WILL BE PRUNED.
  281. *
  282. *
  283. * status: one of the possible execution status of a test case.
  284. *
  285. *
  286. * tplan_tcases: map with testcase versions linked to test plan.
  287. * due to the multiples uses of this function, null has to meanings
  288. *
  289. * When we want to build a Test Project specification tree,
  290. * WE SET it to NULL, because we are not interested in a test plan.
  291. *
  292. * When we want to build a Test execution tree, we dont set it deliverately
  293. * to null, but null can be the result of NO tcversion linked.
  294. *
  295. *
  296. * 20081220 - franciscom - status can be an array with multple values, to do OR search.
  297. *
  298. * 20071014 - franciscom - added version info fro test cases in return data structure.
  299. *
  300. * 20061105 - franciscom
  301. * ignore_inactive_testcases: useful when building a Test Project Specification tree
  302. * to be used in the add/link test case to Test Plan.
  303. *
  304. *
  305. * 20061030 - franciscom
  306. * tck_map: Test Case Keyword map:
  307. * null => no filter
  308. * empty map => filter out ALL test case ALWAYS
  309. * initialized map => filter out test case ONLY if NOT present in map.
  310. *
  311. *
  312. * added argument:
  313. * $map_node_tccount
  314. * key => node_id
  315. * values => node test case count
  316. * node name (useful only for debug purpouses
  317. *
  318. * IMPORTANT: this new argument is not useful for tree rendering
  319. * but to avoid duplicating logic to get test case count
  320. *
  321. *
  322. * return: map with keys:
  323. * 'total_count'
  324. * 'passed'
  325. * 'failed'
  326. * 'blocked'
  327. * 'not run'
  328. *
  329. * @internal Revisions
  330. * 20100810 - asimon - filtering by testcase ID
  331. * 20100417 - franciscom - BUGID 2498 - filter by test case importance
  332. * 20100415 - franciscom - BUGID 2797 - filter by test case execution type
  333. */
  334. function prepareNode(&$db,&$node,&$decoding_info,&$map_node_tccount,$tck_map = null,
  335. $tplan_tcases = null,$filters=null, $options=null)
  336. {
  337. static $hash_id_descr;
  338. static $status_descr_code;
  339. static $status_code_descr;
  340. static $debugMsg;
  341. static $tables;
  342. static $my;
  343. static $enabledFiltersOn;
  344. static $activeVersionClause;
  345. static $filterOnTCVersionAttribute;
  346. static $filtersApplied;
  347. $tpNode = null;
  348. if (!$tables)
  349. {
  350. $debugMsg = 'Class: ' . __CLASS__ . ' - ' . 'Method: ' . __FUNCTION__ . ' - ';
  351. $tables = tlObjectWithDB::getDBTables(array('tcversions','nodes_hierarchy','testplan_tcversions'));
  352. }
  353. if (!$hash_id_descr)
  354. {
  355. $hash_id_descr = $decoding_info['node_id_descr'];
  356. }
  357. if (!$status_descr_code)
  358. {
  359. $status_descr_code = $decoding_info['status_descr_code'];
  360. }
  361. if (!$status_code_descr)
  362. {
  363. $status_code_descr = $decoding_info['status_code_descr'];
  364. }
  365. if (!$my)
  366. {
  367. $my = array();
  368. $my['options'] = array('hideTestCases' => 0, 'showTestCaseID' => 1, 'viewType' => 'testSpecTree',
  369. 'getExternalTestCaseID' => 1,'ignoreInactiveTestCases' => 0);
  370. // asimon - added importance here because of "undefined" error in event log
  371. $my['filters'] = array('status' => null, 'assignedTo' => null,
  372. 'importance' => null, 'executionType' => null,
  373. 'filter_tc_id' => null);
  374. $my['options'] = array_merge($my['options'], (array)$options);
  375. $my['filters'] = array_merge($my['filters'], (array)$filters);
  376. }
  377. if(!$enabledFiltersOn)
  378. {
  379. // 3301 - added filtering by testcase name
  380. // 20100702 - and custom fields
  381. // 20100810 - and testcase ID
  382. $enabledFiltersOn['testcase_id'] =
  383. isset($my['filters']['filter_tc_id']);
  384. $enabledFiltersOn['testcase_name'] =
  385. isset($my['filters']['filter_testcase_name']);
  386. $enabledFiltersOn['keywords'] = isset($tck_map);
  387. $enabledFiltersOn['executionType'] =
  388. isset($my['filters']['filter_execution_type']);
  389. $enabledFiltersOn['importance'] = isset($my['filters']['filter_priority']);
  390. $enabledFiltersOn['custom_fields'] = isset($my['filters']['filter_custom_fields']);
  391. $filterOnTCVersionAttribute = $enabledFiltersOn['executionType'] || $enabledFiltersOn['importance'];
  392. $filtersApplied = false;
  393. foreach($enabledFiltersOn as $filterValue)
  394. {
  395. $filtersApplied = $filtersApplied || $filterValue;
  396. }
  397. $activeVersionClause = $filterOnTCVersionAttribute ? " AND TCV.active=1 " : '';
  398. }
  399. $tcase_counters = array('testcase_count' => 0);
  400. foreach($status_descr_code as $status_descr => $status_code)
  401. {
  402. $tcase_counters[$status_descr]=0;
  403. }
  404. $node_type = isset($node['node_type_id']) ? $hash_id_descr[$node['node_type_id']] : null;
  405. $tcase_counters['testcase_count']=0;
  406. if($node_type == 'testcase')
  407. {
  408. $viewType = $my['options']['viewType'];
  409. if ($enabledFiltersOn['keywords'])
  410. {
  411. if (!isset($tck_map[$node['id']]))
  412. {
  413. $node = null;
  414. }
  415. }
  416. // added filter by testcase name
  417. if ($node && $enabledFiltersOn['testcase_name']) {
  418. $filter_name = $my['filters']['filter_testcase_name'];
  419. // IMPORTANT:
  420. // checking with === here, because function stripos could return 0 when string
  421. // is found at position 0, if clause would then evaluate wrong because
  422. // 0 would be casted to false and we only want to delete node if it really is false
  423. if (stripos($node['name'], $filter_name) === FALSE) {
  424. $node = null;
  425. }
  426. }
  427. // filter by testcase ID
  428. if ($node && $enabledFiltersOn['testcase_id']) {
  429. $filter_id = $my['filters']['filter_tc_id'];
  430. if ($node['id'] != $filter_id) {
  431. $node = null;
  432. }
  433. }
  434. if ($node && $viewType == 'executionTree')
  435. {
  436. $tpNode = isset($tplan_tcases[$node['id']]) ? $tplan_tcases[$node['id']] : null;
  437. // if (!$tpNode || (!is_null($my['filters']['assignedTo'])) &&
  438. // ((isset($my['filters']['assignedTo'][TL_USER_NOBODY]) && !is_null($tpNode['user_id'])) ||
  439. // (!isset($my['filters']['assignedTo'][TL_USER_NOBODY]) && (!isset($my['filters']['assignedTo'][TL_USER_SOMEBODY])) &&
  440. // !isset($my['filters']['assignedTo'][$tpNode['user_id']]))) ||
  441. // (!is_null($my['filters']['status']) && !isset($my['filters']['status'][$tpNode['exec_status']])) ||
  442. // (isset($my['filters']['assignedTo'][TL_USER_SOMEBODY]) && !is_numeric($tpNode['user_id']))
  443. // )
  444. // {
  445. // asimon - additional variables for better readability of following if condition.
  446. // For original statement/condition see above commented out lines.
  447. // This is longer, but MUCH better readable and easier to extend for new filter conditions.
  448. $users2filter = isset($my['filters']['filter_assigned_user']) ?
  449. $my['filters']['filter_assigned_user'] : null;
  450. $results2filter = isset($my['filters']['filter_result_result']) ?
  451. $my['filters']['filter_result_result'] : null;
  452. $wrong_result = !is_null($results2filter)
  453. && !isset($results2filter[$tpNode['exec_status']]);
  454. $somebody_wanted_but_nobody_there = !is_null($users2filter)
  455. && isset($users2filter[TL_USER_SOMEBODY])
  456. && !is_numeric($tpNode['user_id']);
  457. $unassigned_wanted_but_someone_assigned = !is_null($users2filter)
  458. && isset($users2filter[TL_USER_NOBODY])
  459. && !is_null($tpNode['user_id']);
  460. $wrong_user = !is_null($users2filter)
  461. && !isset($users2filter[TL_USER_NOBODY])
  462. && !isset($users2filter[TL_USER_SOMEBODY])
  463. && !isset($users2filter[$tpNode['user_id']]);
  464. $delete_node = $unassigned_wanted_but_someone_assigned
  465. || $wrong_user
  466. || $wrong_result
  467. || $somebody_wanted_but_nobody_there;
  468. if (!$tpNode || $delete_node) {
  469. $node = null;
  470. } else {
  471. $externalID='';
  472. $node['tcversion_id'] = $tpNode['tcversion_id'];
  473. $node['version'] = $tpNode['version'];
  474. if ($my['options']['getExternalTestCaseID'])
  475. {
  476. if (!isset($tpNode['external_id']))
  477. {
  478. $sql = " /* $debugMsg - line:" . __LINE__ . " */ " .
  479. " SELECT TCV.tc_external_id AS external_id " .
  480. " FROM {$tables['tcversions']} TCV " .
  481. " WHERE TCV.id=" . $node['tcversion_id'];
  482. $result = $db->exec_query($sql);
  483. $myrow = $db->fetch_array($result);
  484. $externalID = $myrow['external_id'];
  485. }
  486. else
  487. {
  488. $externalID = $tpNode['external_id'];
  489. }
  490. }
  491. $node['external_id'] = $externalID;
  492. unset($tplan_tcases[$node['id']]);
  493. }
  494. }
  495. if ($node && $my['options']['ignoreInactiveTestCases'])
  496. {
  497. // there are active tcversions for this node ???
  498. // I'm doing this instead of creating a test case manager object, because
  499. // I think is better for performance.
  500. //
  501. // =======================================================================================
  502. // 20070106 - franciscom
  503. // Postgres Problems
  504. // =======================================================================================
  505. // Problem 1 - SQL Syntax
  506. // While testing with postgres
  507. // SELECT count(TCV.id) NUM_ACTIVE_VERSIONS -> Error
  508. //
  509. // At least for what I remember using AS to create COLUMN ALIAS IS REQUIRED and Standard
  510. // while AS is NOT REQUIRED (and with some DBMS causes errors) when you want to give a
  511. // TABLE ALIAS
  512. //
  513. // Problem 2 - alias case
  514. // At least in my installation the aliases column name is returned lower case, then
  515. // PHP fails when:
  516. // if($myrow['NUM_ACTIVE_VERSIONS'] == 0)
  517. //
  518. //
  519. $sql=" /* $debugMsg - line:" . __LINE__ . " */ " .
  520. " SELECT count(TCV.id) AS num_active_versions " .
  521. " FROM {$tables['tcversions']} TCV, {$tables['nodes_hierarchy']} NH " .
  522. " WHERE NH.parent_id=" . $node['id'] .
  523. " AND NH.id = TCV.id AND TCV.active=1";
  524. $result = $db->exec_query($sql);
  525. $myrow = $db->fetch_array($result);
  526. if($myrow['num_active_versions'] == 0)
  527. {
  528. $node = null;
  529. }
  530. }
  531. // -------------------------------------------------------------------
  532. if ($node && ($viewType=='testSpecTree' || $viewType=='testSpecTreeForTestPlan') )
  533. {
  534. $sql = " /* $debugMsg - line:" . __LINE__ . " */ " .
  535. " SELECT COALESCE(MAX(TCV.id),0) AS targetid, TCV.tc_external_id AS external_id" .
  536. " FROM {$tables['tcversions']} TCV, {$tables['nodes_hierarchy']} NH " .
  537. " WHERE NH.id = TCV.id {$activeVersionClause} AND NH.parent_id={$node['id']} " .
  538. " GROUP BY TCV.tc_external_id ";
  539. $rs = $db->get_recordset($sql);
  540. if( is_null($rs) )
  541. {
  542. $node = null;
  543. }
  544. else
  545. {
  546. $node['external_id'] = $rs[0]['external_id'];
  547. $target_id = $rs[0]['targetid'];
  548. if( $filterOnTCVersionAttribute )
  549. {
  550. // BUGID 2797
  551. switch ($viewType)
  552. {
  553. case 'testSpecTreeForTestPlan':
  554. // Try to get info from linked tcversions
  555. // Platform is not needed
  556. $sql = " /* $debugMsg - line:" . __LINE__ . " */ " .
  557. " SELECT DISTINCT TPTCV.tcversion_id AS targetid " .
  558. " FROM {$tables['tcversions']} TCV " .
  559. " JOIN {$tables['nodes_hierarchy']} NH " .
  560. " ON NH.id = TCV.id {$activeVersionClause} " .
  561. " AND NH.parent_id={$node['id']} " .
  562. " JOIN {$tables['testplan_tcversions']} TPTCV " .
  563. " ON TPTCV.tcversion_id = TCV.id " .
  564. " AND TPTCV.testplan_id = " .
  565. " {$my['filters']['setting_testplan']}";
  566. $rs = $db->get_recordset($sql);
  567. $target_id = !is_null($rs) ? $rs[0]['targetid'] : $target_id;
  568. break;
  569. }
  570. $sql = " /* $debugMsg - line:" . __LINE__ . " */ " .
  571. " SELECT TCV.execution_type " .
  572. " FROM {$tables['tcversions']} TCV " .
  573. " WHERE TCV.id = {$target_id} ";
  574. if( $enabledFiltersOn['executionType'] )
  575. {
  576. $sql .= " AND TCV.execution_type = " .
  577. " {$my['filters']['filter_execution_type']} ";
  578. }
  579. if( $enabledFiltersOn['importance'] )
  580. {
  581. $sql .= " AND TCV.importance = " .
  582. " {$my['filters']['filter_priority']} ";
  583. }
  584. $rs = $db->fetchRowsIntoMap($sql,'execution_type');
  585. if(is_null($rs))
  586. {
  587. $node = null;
  588. }
  589. }
  590. }
  591. if( !is_null($node) )
  592. {
  593. // needed to avoid problems when using json_encode with EXTJS
  594. unset($node['childNodes']);
  595. $node['leaf']=true;
  596. }
  597. }
  598. // -------------------------------------------------------------------
  599. foreach($tcase_counters as $key => $value)
  600. {
  601. $tcase_counters[$key]=0;
  602. }
  603. if(isset($tpNode['exec_status']) )
  604. {
  605. $tc_status_code = $tpNode['exec_status'];
  606. $tc_status_descr = $status_code_descr[$tc_status_code];
  607. }
  608. else
  609. {
  610. $tc_status_descr = "not_run";
  611. $tc_status_code = $status_descr_code[$tc_status_descr];
  612. }
  613. $init_value = $node ? 1 : 0;
  614. $tcase_counters[$tc_status_descr]=$init_value;
  615. $tcase_counters['testcase_count']=$init_value;
  616. if ( $my['options']['hideTestCases'] )
  617. {
  618. $node = null;
  619. }
  620. } // if($node_type == 'testcase')
  621. if (isset($node['childNodes']) && is_array($node['childNodes']))
  622. {
  623. // node has to be a Test Suite ?
  624. $childNodes = &$node['childNodes'];
  625. $childNodesQty = count($childNodes);
  626. for($idx = 0;$idx < $childNodesQty ;$idx++)
  627. {
  628. $current = &$childNodes[$idx];
  629. // I use set an element to null to filter out leaf menu items
  630. if(is_null($current))
  631. {
  632. continue;
  633. }
  634. $counters_map = prepareNode($db,$current,$decoding_info,$map_node_tccount,
  635. $tck_map,$tplan_tcases,$my['filters'],$my['options']);
  636. foreach($counters_map as $key => $value)
  637. {
  638. $tcase_counters[$key] += $counters_map[$key];
  639. }
  640. }
  641. foreach($tcase_counters as $key => $value)
  642. {
  643. $node[$key] = $tcase_counters[$key];
  644. }
  645. if (isset($node['id']))
  646. {
  647. $map_node_tccount[$node['id']] = array( 'testcount' => $node['testcase_count'],
  648. 'name' => $node['name']);
  649. }
  650. // node must be dstroyed if empty had we have using filtering conditions
  651. if( ($filtersApplied || !is_null($tplan_tcases)) &&
  652. !$tcase_counters['testcase_count'] && ($node_type != 'testproject'))
  653. {
  654. $node = null;
  655. }
  656. }
  657. else if ($node_type == 'testsuite')
  658. {
  659. // does this means is an empty test suite ??? - franciscom 20080328
  660. $map_node_tccount[$node['id']] = array( 'testcount' => 0,'name' => $node['name']);
  661. // If is an EMPTY Test suite and we have added filtering conditions,
  662. // We will destroy it.
  663. if ($filtersApplied || !is_null($tplan_tcases) )
  664. {
  665. $node = null;
  666. }
  667. }
  668. return $tcase_counters;
  669. }
  670. /**
  671. * Create the string representation suitable to create a graphic visualization
  672. * of a node, for the type of menu selected.
  673. *
  674. * @internal Revisions
  675. * 20100611 - franciscom - removed useless $getArguments
  676. */
  677. function renderTreeNode($level,&$node,$hash_id_descr,
  678. $tc_action_enabled,$linkto,$testCasePrefix,
  679. $bForPrinting=0,$showTestCaseID)
  680. {
  681. $menustring='';
  682. $node_type = $hash_id_descr[$node['node_type_id']];
  683. extjs_renderTestSpecTreeNodeOnOpen($node,$node_type,$tc_action_enabled,$bForPrinting,
  684. $showTestCaseID,$testCasePrefix);
  685. if (isset($node['childNodes']) && $node['childNodes'])
  686. {
  687. // 20090118 - franciscom - need to work always original object
  688. // in order to change it's values using reference .
  689. // Can not assign anymore to intermediate variables.
  690. //
  691. $nChildren = sizeof($node['childNodes']);
  692. for($idx = 0;$idx < $nChildren;$idx++)
  693. {
  694. // asimon - replaced is_null by !isset because of warnings in event log
  695. if(!isset($node['childNodes'][$idx]))
  696. //if(is_null($node['childNodes'][$idx]))
  697. {
  698. continue;
  699. }
  700. $menustring .= renderTreeNode($level+1,$node['childNodes'][$idx],$hash_id_descr,
  701. $tc_action_enabled,$linkto,$testCasePrefix,
  702. $bForPrinting,$showTestCaseID);
  703. }
  704. }
  705. return $menustring;
  706. }
  707. /**
  708. * Creates data for tree menu used on :
  709. * - Execution of Test Cases
  710. * - Remove Test cases from test plan
  711. *
  712. * @internal Revisions:
  713. * 20100820 - asimon - refactoring for less redundant checks and better readibility
  714. * 20100719 - asimon - BUGID 3406 - user assignments per build:
  715. * filter assigned test cases by setting_build
  716. * 20080617 - franciscom - return type changed to use extjs tree component
  717. * 20080305 - franciscom - interface refactoring
  718. * 20080224 - franciscom - added include_unassigned
  719. * 20071002 - jbarchibald - BUGID 1051 - added cf element to parameter list
  720. * 20070204 - franciscom - changed $bForPrinting -> $bHideTCs
  721. */
  722. function generateExecTree(&$db,&$menuUrl,$tproject_id,$tproject_name,$tplan_id,
  723. $tplan_name,$filters,$additionalInfo)
  724. {
  725. $treeMenu = new stdClass();
  726. $treeMenu->rootnode = null;
  727. $treeMenu->menustring = '';
  728. $resultsCfg = config_get('results');
  729. $showTestCaseID = config_get('treemenu_show_testcase_id');
  730. $glueChar=config_get('testcase_cfg')->glue_character;
  731. $menustring = null;
  732. $any_exec_status = null;
  733. $tplan_tcases = null;
  734. $tck_map = null;
  735. $idx=0;
  736. $testCaseQty=0;
  737. $testCaseSet=null;
  738. $keyword_id = 0;
  739. $keywordsFilterType = 'Or';
  740. if (property_exists($filters, 'filter_keywords') && !is_null($filters->{'filter_keywords'})) {
  741. $keyword_id = $filters->{'filter_keywords'};
  742. $keywordsFilterType = $filters->{'filter_keywords_filter_type'};
  743. }
  744. // BUGID 3406 - user assignments per build
  745. // can't use $build_id here because we need the build ID from settings panel
  746. $build2filter_assignments = isset($filters->{'setting_build'}) ? $filters->{'setting_build'} : 0;
  747. $tc_id = isset($filters->filter_tc_id) ? $filters->filter_tc_id : null;
  748. $build_id = isset($filters->filter_result_build) ? $filters->filter_result_build : null;
  749. $bHideTCs = isset($filters->hide_testcases) ? $filters->hide_testcases : false;
  750. $assignedTo = isset($filters->filter_assigned_user) ? $filters->filter_assigned_user : null;
  751. $include_unassigned = isset($filters->filter_assigned_user_include_unassigned) ?
  752. $filters->filter_assigned_user_include_unassigned : false;
  753. $setting_platform = isset($filters->setting_platform) ? $filters->setting_platform : null;
  754. $execution_type = isset($filters->filter_execution_type) ? $filters->filter_execution_type : null;
  755. $status = isset($filters->filter_result_result) ? $filters->filter_result_result : null;
  756. $cf_hash = isset($filters->filter_custom_fields) ? $filters->filter_custom_fields : null;
  757. $show_testsuite_contents = isset($filters->show_testsuite_contents) ?
  758. $filters->show_testsuite_contents : true;
  759. $urgencyImportance = isset($filters->filter_priority) ?
  760. $filters->filter_priority : null;
  761. $useCounters=isset($additionalInfo->useCounters) ? $additionalInfo->useCounters : null;
  762. $useColors=isset($additionalInfo->useColours) ? $additionalInfo->useColours : null;
  763. $colorBySelectedBuild = isset($additionalInfo->testcases_colouring_by_selected_build) ?
  764. $additionalInfo->testcases_colouring_by_selected_build : null;
  765. $tplan_mgr = new testplan($db);
  766. $tproject_mgr = new testproject($db);
  767. $tcase_mgr = new testcase($db);
  768. $tree_manager = $tplan_mgr->tree_manager;
  769. $tcase_node_type = $tree_manager->node_descr_id['testcase'];
  770. $hash_descr_id = $tree_manager->get_available_node_types();
  771. $hash_id_descr = array_flip($hash_descr_id);
  772. $decoding_hash = array('node_id_descr' => $hash_id_descr,
  773. 'status_descr_code' => $resultsCfg['status_code'],
  774. 'status_code_descr' => $resultsCfg['code_status']);
  775. $tcase_prefix = $tproject_mgr->getTestCasePrefix($tproject_id) . $glueChar;
  776. $nt2exclude = array('testplan' => 'exclude_me',
  777. 'requirement_spec'=> 'exclude_me',
  778. 'requirement'=> 'exclude_me');
  779. $nt2exclude_children = array('testcase' => 'exclude_my_children',
  780. 'requirement_spec'=> 'exclude_my_children');
  781. $my['options']=array('recursive' => true,
  782. 'order_cfg' => array("type" =>'exec_order',"tplan_id" => $tplan_id));
  783. $my['filters'] = array('exclude_node_types' => $nt2exclude,
  784. 'exclude_children_of' => $nt2exclude_children);
  785. // BUGID 3301 - added for filtering by toplevel testsuite
  786. if (isset($filters->{'filter_toplevel_testsuite'}) && is_array($filters->{'filter_toplevel_testsuite'})) {
  787. $my['filters']['exclude_branches'] = $filters->{'filter_toplevel_testsuite'};
  788. }
  789. $test_spec = $tree_manager->get_subtree($tproject_id,$my['filters'],$my['options']);
  790. $test_spec['name'] = $tproject_name . " / " . $tplan_name; // To be discussed
  791. $test_spec['id'] = $tproject_id;
  792. $test_spec['node_type_id'] = $hash_descr_id['testproject'];
  793. $map_node_tccount = array();
  794. $tplan_tcases = null;
  795. $apply_other_filters=true;
  796. if($test_spec)
  797. {
  798. if(is_null($tc_id) || $tc_id >= 0)
  799. {
  800. $doFilterByKeyword = (!is_null($keyword_id) && $keyword_id > 0);
  801. if($doFilterByKeyword)
  802. {
  803. $tck_map = $tproject_mgr->get_keywords_tcases($tproject_id,$keyword_id,$keywordsFilterType);
  804. }
  805. // Multiple step algoritm to apply keyword filter on type=AND
  806. // get_linked_tcversions filters by keyword ALWAYS in OR mode.
  807. // BUGID 3406: user assignments per build
  808. $opt = array('include_unassigned' => $include_unassigned, 'steps_info' => false,
  809. 'user_assignments_per_build' => $build2filter_assignments);
  810. // 20100417 - BUGID 3380 - execution type
  811. $linkedFilters = array('tcase_id' => $tc_id, 'keyword_id' => $keyword_id,
  812. 'assigned_to' => $assignedTo,
  813. 'cf_hash' => $cf_hash,
  814. 'platform_id' => $setting_platform,
  815. 'urgencyImportance' => $urgencyImportance,
  816. 'exec_type' => $execution_type);
  817. $tplan_tcases = $tplan_mgr->get_linked_tcversions($tplan_id,$linkedFilters,$opt);
  818. if($tplan_tcases && $doFilterByKeyword && $keywordsFilterType == 'AND')
  819. {
  820. $filteredSet = $tcase_mgr->filterByKeyword(array_keys($tplan_tcases),$keyword_id,$keywordsFilterType);
  821. // CAUTION: if $filteredSet is null,
  822. // then get_linked_tcversions() thinks there are just no filters set,
  823. // but really there are no testcases which match the wanted keyword criteria,
  824. // so we have to set $tplan_tcases to null because there is no more filtering necessary
  825. if ($filteredSet != null) {
  826. $linkedFilters = array('tcase_id' => array_keys($filteredSet));
  827. $tplan_tcases = $tplan_mgr->get_linked_tcversions($tplan_id,$linkedFilters);
  828. } else {
  829. $tplan_tcases = null;
  830. }
  831. }
  832. }
  833. if (is_null($tplan_tcases))
  834. {
  835. $tplan_tcases = array();
  836. $apply_other_filters=false;
  837. }
  838. $filter_methods = config_get('execution_filter_methods');
  839. // 20100820 - asimon - refactoring for less redundant checks and better readibility
  840. $ffn = array($filter_methods['status_code']['any_build'] => 'filter_by_status_for_any_build',
  841. $filter_methods['status_code']['all_builds'] => 'filter_by_same_status_for_all_builds',
  842. $filter_methods['status_code']['specific_build'] => 'filter_by_status_for_build',
  843. $filter_methods['status_code']['current_build'] => 'filter_by_status_for_build',
  844. $filter_methods['status_code']['latest_execution'] => 'filter_by_status_for_last_execution');
  845. $requested_filter_method = isset($filters->filter_result_method) ? $filters->filter_result_method : null;
  846. $requested_filter_result = isset($filters->filter_result_result) ? $filters->filter_result_result : null;
  847. // if "any" was selected as filtering status, don't filter by status
  848. $requested_filter_result = (array)$requested_filter_result;
  849. if (in_array($resultsCfg['status_code']['all'], $requested_filter_result)) {
  850. $requested_filter_result = null;
  851. }
  852. if ($apply_other_filters && !is_null($requested_filter_method) && isset($ffn[$requested_filter_method])) {
  853. // special case 1: when filtering by "not run" status in any build,
  854. // we need another filter function
  855. if (in_array($resultsCfg['status_code']['not_run'], $requested_filter_result)) {
  856. $ffn[$filter_methods['status_code']['any_build']] = 'filter_not_run_for_any_build';
  857. }
  858. // special case 2: when filtering by "current build", we set the build to filter with
  859. // to the build chosen in settings instead of the one in filters
  860. if ($requested_filter_method == $filter_methods['status_code']['current_build']) {
  861. $filters->filter_result_build = $filters->setting_build;
  862. }
  863. // call the filter function and do the filtering
  864. $tplan_tcases = $ffn[$requested_filter_method]($tplan_mgr, $tplan_tcases, $tplan_id, $filters);
  865. if (is_null($tplan_tcases)) {
  866. $tplan_tcases = array();
  867. $apply_other_filters=false;
  868. }
  869. }
  870. // end 20100820 refactoring
  871. // BUGID 3450 - Change colors/counters in exec tree.
  872. // Means: replace exec status in filtered array $tplan_tcases
  873. // by the one of last execution of selected build.
  874. // Since this changes exec status, replacing is done after filtering by status.
  875. // It has to be done before call to prepareNode() though,
  876. // because that one sets the counters according to status.
  877. if ($useColors && $colorBySelectedBuild) {
  878. $tables = tlObject::getDBTables('executions');
  879. foreach ($tplan_tcases as $id => $info) {
  880. // get last execution result for selected build
  881. $sql = " SELECT status FROM {$tables['executions']} E " .
  882. " WHERE tcversion_id = {$info['tcversion_id']} " .
  883. " AND testplan_id = {$tplan_id} " .
  884. " AND platform_id = {$info['platform_id']} " .
  885. " AND build_id = {$filters->setting_build} " .
  886. " ORDER BY execution_ts DESC LIMIT 1 ";
  887. $result = null;
  888. $result = $db->fetchOneValue($sql);
  889. if (is_null($result)) {
  890. // if no value can be loaded it has to be set to not run
  891. $result = $resultsCfg['status_code']['not_run'];
  892. }
  893. if ($result != $info['exec_status']) {
  894. $tplan_tcases[$id]['exec_status'] = $result;
  895. }
  896. }
  897. }
  898. // 20080224 - franciscom -
  899. // After reviewing code, seems that assignedTo has no sense because tp_tcs
  900. // has been filtered.
  901. // Then to avoid changes to prepareNode() due to include_unassigned,
  902. // seems enough to set assignedTo to 0, if include_unassigned==true
  903. $assignedTo = $include_unassigned ? null : $assignedTo;
  904. $pnFilters = array('assignedTo' => $assignedTo);
  905. $keys2init = array('filter_testcase_name',
  906. 'filter_execution_type',
  907. 'filter_priority');
  908. foreach ($keys2init as $keyname) {
  909. $pnFilters[$keyname] = isset($filters->{$keyname}) ? $filters->{$keyname} : null;
  910. }
  911. // 20100412 - franciscom
  912. $pnOptions = array('hideTestCases' => $bHideTCs, 'viewType' => 'executionTree');
  913. $testcase_counters = prepareNode($db,$test_spec,$decoding_hash,$map_node_tccount,
  914. $tck_map,$tplan_tcases,$pnFilters,$pnOptions);
  915. foreach($testcase_counters as $key => $value)
  916. {
  917. $test_spec[$key] = $testcase_counters[$key];
  918. }
  919. // BUGID 3516
  920. // can now be left in form of array, will not be sent by URL anymore
  921. //$keys = implode(array_keys($tplan_tcases), ",");
  922. $keys = array_keys($tplan_tcases);
  923. $menustring = renderExecTreeNode(1,$test_spec,$tplan_tcases,
  924. $hash_id_descr,1,$menuUrl,$bHideTCs,$useCounters,$useColors,
  925. $showTestCaseID,$tcase_prefix,$show_testsuite_contents);
  926. } // if($test_spec)
  927. $treeMenu->rootnode=new stdClass();
  928. $treeMenu->rootnode->name=$test_spec['text'];
  929. $treeMenu->rootnode->id=$test_spec['id'];
  930. $treeMenu->rootnode->leaf=$test_spec['leaf'];
  931. $treeMenu->rootnode->text=$test_spec['text'];
  932. $treeMenu->rootnode->position=$test_spec['position'];
  933. $treeMenu->rootnode->href=$test_spec['href'];
  934. if( !is_null($menustring) )
  935. {
  936. // Change key ('childNodes') to the one required by Ext JS tree.
  937. $menustring = str_ireplace('childNodes', 'children', json_encode($test_spec['childNodes']));
  938. // Remove null elements (Ext JS tree do not like it ).
  939. // :null happens on -> "children":null,"text" that must become "children":[],"text"
  940. // $menustring = str_ireplace(array(':null',',null','null,'),array(':[]','',''), $menustring);
  941. $menustring = str_ireplace(array(':null',',null','null,','null'),array(':[]','','',''), $menustring);
  942. }
  943. $treeMenu->menustring = $menustring;
  944. return array($treeMenu, $keys);
  945. }
  946. /**
  947. *
  948. *
  949. * @param integer $level
  950. * @param array &$node reference to recursive map
  951. * @param array &$tcases_map reference to map that contains info about testcase exec status
  952. * when node is of testcase type.
  953. * @param boolean $bHideTCs 1 -> hide testcase
  954. *
  955. * @return datatype description
  956. *
  957. * @internal Revisions:
  958. * 20100611 - franciscom - removed useless $getArguments
  959. * 20071229 - franciscom -added $useCounters,$useColors
  960. */
  961. function renderExecTreeNode($level,&$node,&$tcase_node,$hash_id_descr,
  962. $tc_action_enabled,$linkto,$bHideTCs,$useCounters,$useColors,
  963. $showTestCaseID,$testCasePrefix,$showTestSuiteContents)
  964. {
  965. $node_type = $hash_id_descr[$node['node_type_id']];
  966. $menustring = '';
  967. extjs_renderExecTreeNodeOnOpen($node,$node_type,$tcase_node,$tc_action_enabled,$bHideTCs,
  968. $useCounters,$useColors,$showTestCaseID,$testCasePrefix,
  969. $showTestSuiteContents);
  970. if( isset($tcase_node[$node['id']]) )
  971. {
  972. unset($tcase_node[$node['id']]);
  973. }
  974. if (isset($node['childNodes']) && $node['childNodes'])
  975. {
  976. // 20080615 - franciscom - need to work always original object
  977. // in order to change it's values using reference .
  978. // Can not assign anymore to intermediate variables.
  979. $nodes_qty = sizeof($node['childNodes']);
  980. for($idx = 0;$idx <$nodes_qty ;$idx++)
  981. {
  982. if(is_null($node['childNodes'][$idx]))
  983. {
  984. continue;
  985. }
  986. $menustring .= renderExecTreeNode($level+1,$node['childNodes'][$idx],$tcase_node,
  987. $hash_id_descr,
  988. $tc_action_enabled,$linkto,$bHideTCs,
  989. $useCounters,$useColors,$showTestCaseID,
  990. $testCasePrefix,$showTestSuiteContents);
  991. }
  992. }
  993. return $menustring;
  994. }
  995. /**
  996. * @return array a map:
  997. * key => node_id
  998. * values => node test case count considering test cases presents
  999. * in the nodes of the subtree that starts on node_id
  1000. * Means test case can not be sons/daughters of node_id.
  1001. * node name (useful only for debug purpouses).
  1002. */
  1003. function get_testproject_nodes_testcount(&$db,$tproject_id, $tproject_name,
  1004. $keywordsFilter=null)
  1005. {
  1006. $tproject_mgr = new testproject($db);
  1007. $tree_manager = &$tproject_mgr->tree_manager;
  1008. $tcase_node_type = $tree_manager->node_descr_id['testcase'];
  1009. $hash_descr_id = $tree_manager->get_available_node_types();
  1010. $hash_id_descr = array_flip($hash_descr_id);
  1011. $resultsCfg = config_get('results');
  1012. $decoding_hash = array('node_id_descr' => $hash_id_descr,
  1013. 'status_descr_code' => $resultsCfg['status_code'],
  1014. 'status_code_descr' => $resultsCfg['code_status']);
  1015. $test_spec = $tproject_mgr->get_subtree($tproject_id,RECURSIVE_MODE);
  1016. $test_spec['name'] = $tproject_name;
  1017. $test_spec['id'] = $tproject_id;
  1018. $test_spec['node_type_id'] = 1;
  1019. $map_node_tccount = array();
  1020. $tplan_tcases = null;
  1021. if($test_spec)
  1022. {
  1023. $tck_map = null;
  1024. if( !is_null($keywordsFilter) )
  1025. {
  1026. $tck_map = $tproject_mgr->get_keywords_tcases($tproject_id,
  1027. $keywordsFilter->items,$keywordsFilter->type);
  1028. }
  1029. //@TODO: schlundus, can we speed up with NO_EXTERNAL?
  1030. $filters = null;
  1031. // 20100412 - franciscon
  1032. $options = array('hideTestCases' => 0, 'viewType' => 'testSpecTree');
  1033. $testcase_counters = prepareNode($db,$test_spec,$decoding_hash,$map_node_tccount,
  1034. $tck_map,$tplan_tcases,$filters,$options);
  1035. $test_spec['testcase_count'] = $testcase_counters['testcase_count'];
  1036. }
  1037. return $map_node_tccount;
  1038. }
  1039. /**
  1040. * @return array a map:
  1041. * key => node_id
  1042. * values => node test case count considering test cases presents
  1043. * in the nodes of the subtree that starts on node_id
  1044. * Means test case can not be sons/daughters of node_id.
  1045. *
  1046. * node name (useful only for debug purpouses).
  1047. */
  1048. function get_testplan_nodes_testcount(&$db,$tproject_id, $tproject_name,
  1049. $tplan_id,$tplan_name,$keywordsFilter=null)
  1050. {
  1051. $tplan_mgr = new testplan($db);
  1052. $tproject_mgr = new testproject($db);
  1053. $tree_manager = $tplan_mgr->tree_manager;
  1054. $tcase_node_type = $tree_manager->node_descr_id['testcase'];
  1055. $hash_descr_id = $tree_manager->get_available_node_types();
  1056. $hash_id_descr = array_flip($hash_descr_id);
  1057. $resultsCfg=config_get('results');
  1058. $decoding_hash=array('node_id_descr' => $hash_id_descr, 'status_descr_code' => $resultsCfg['status_code'],
  1059. 'status_code_descr' => $resultsCfg['code_status']);
  1060. $test_spec = $tproject_mgr->get_subtree($tproject_id,RECURSIVE_MODE);
  1061. $linkedFilters = array('keyword_id' => $keywordsFilter->items);
  1062. $tplan_tcases = $tplan_mgr->get_linked_tcversions($tplan_id,$linkedFilters);
  1063. if (is_null($tplan_tcases))
  1064. {
  1065. $tplan_tcases = array();
  1066. }
  1067. $test_spec['name'] = $tproject_name;
  1068. $test_spec['id'] = $tproject_id;
  1069. $test_spec['node_type_id'] = $hash_descr_id['testproject'];
  1070. $map_node_tccount=array();
  1071. if($test_spec)
  1072. {
  1073. $tck_map = null;
  1074. if(!is_null($keywordsFilter))
  1075. {
  1076. $tck_map = $tproject_mgr->get_keywords_tcases($tproject_id,
  1077. $keywordsFilter->items,$keywordsFilter->type);
  1078. }
  1079. //@TODO: schlundus, can we speed up with NO_EXTERNAL?
  1080. $filters = null;
  1081. $options = array('hideTestCases' => 0, 'viewType' => 'executionTree');
  1082. $testcase_counters = prepareNode($db,$test_spec,$decoding_hash,$map_node_tccount,
  1083. $tck_map,$tplan_tcases,$filters,$options);
  1084. $test_spec['testcase_count'] = $testcase_counters['testcase_count'];
  1085. }
  1086. return($map_node_tccount);
  1087. }
  1088. function create_counters_info(&$node,$useColors)
  1089. {
  1090. $resultsCfg=config_g

Large files files are truncated, but you can click here to view the full file