See More

From ce84e9fed154c2c03a98a9b79d086efe3d586463 Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Sun, 7 Nov 2010 10:51:05 +0000 Subject: [PATCH 0001/1141] define('TL_VERSION', '2.0 (Development)'); --- cfg/const.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cfg/const.inc.php b/cfg/const.inc.php index 8e05070a59..d76e09bf47 100644 --- a/cfg/const.inc.php +++ b/cfg/const.inc.php @@ -9,7 +9,7 @@ * @package TestLink * @author Martin Havlat * @copyright 2007-2009, TestLink community - * @version CVS: $Id: const.inc.php,v 1.167 2010/11/07 10:20:21 franciscom Exp $ + * @version CVS: $Id: const.inc.php,v 1.168 2010/11/07 10:51:05 franciscom Exp $ * @see config.inc.php * * @internal @@ -21,8 +21,8 @@ /* [GLOBAL SETTINGS] */ /** TestLink Release version (MUST BE changed before the release day) */ -define('TL_FACE_DIR', 'prague'); -define('TL_VERSION', '1.9 (QA - 20101107 - Prague)'); +define('TL_FACE_DIR', 'baires'); +define('TL_VERSION', '2.0 (Development)'); // needed to avoid problems in install scripts that do not include config.inc.php // want to point to root install dir, need to remove fixed part From ff01160fdcc595148533aa76016730d005270898 Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Sun, 7 Nov 2010 20:06:57 +0000 Subject: [PATCH 0002/1141] *** empty log message *** --- locale/en_GB/strings.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locale/en_GB/strings.txt b/locale/en_GB/strings.txt index 24fc2d4928..b18561cc50 100644 --- a/locale/en_GB/strings.txt +++ b/locale/en_GB/strings.txt @@ -24,7 +24,7 @@ * @package TestLink * @author Francisco Mancardi, Andreas Morsing, Martin Havlat * @copyright 2003, TestLink community - * @version CVS: $Id: strings.txt,v 1.751 2010/11/06 18:46:33 amkhullar Exp $ + * @version CVS: $Id: strings.txt,v 1.752 2010/11/07 20:06:57 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: Not listed - check repository history @@ -3125,6 +3125,9 @@ $TLS_insert_step = "Insert step"; $TLS_frozen_req_unable_to_import = 'Skipped - Requirement - Doc ID:%s - is FROZEN'; +$TLS_no_linked_cfields_for_testcase = 'There are no custom fields applicable to Test Cases, linked to Test Project'; +$TLS_no_cfield_with_this_name = 'There is no custom field with requested name (%s)'; + // ----- lib/plan/planExport.php ----- $TLS_export_test_plan = 'Export Test Plan'; From 70969107ab8143f68cb30cf005a9c65da0ff0929 Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Sun, 7 Nov 2010 20:11:20 +0000 Subject: [PATCH 0003/1141] BUGID 3843 - get_id_by_custom_field() --- lib/functions/testcase.class.php | 43 +++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/functions/testcase.class.php b/lib/functions/testcase.class.php index 6c4293ecc0..2052370b0b 100644 --- a/lib/functions/testcase.class.php +++ b/lib/functions/testcase.class.php @@ -6,11 +6,12 @@ * @package TestLink * @author Francisco Mancardi ([email protected]) * @copyright 2005-2009, TestLink community - * @version CVS: $Id: testcase.class.php,v 1.331 2010/10/30 15:17:29 franciscom Exp $ + * @version CVS: $Id: testcase.class.php,v 1.332 2010/11/07 20:11:20 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: * + * 20101107 - franciscom - BUGID 3843 - get_id_by_custom_field() (WIP) * 20101030 - franciscom - get_by_external() interface changes * get_basic_info() interface changes * @@ -5010,6 +5011,46 @@ function filter_tcversions_by_cfields($tcversion_id,$cf_hash,$options=null) * * */ + function get_id_by_custom_field($cf_name, $cf_value, $tproject_id) + { + static $lbl; + if( is_null($lbl) ) + { + $lbl = array(); + $lbl['no_linked_cfields_for_testcase'] = lang_get('no_linked_cfields_for_testcase'); + $lbl['no_cfield_with_this_name'] = lang_get('no_cfield_with_this_name'); + } + $ret = array('status_ok' => false, 'msg' => '', 'id' => 0); + + + // check if custom field is linked to test project + $cfields_set = $this->tproject_mgr->get_linked_custom_fields($tproject_id,'testcase','name'); + $ret['status_ok'] = !is_null($cfields_set); + if(!$ret['status_ok']) + { + $ret['msg'] = $lbl['no_linked_cfields_for_testcase']; + + } + + if($ret['status_ok']) + { + if( ($ret['status_ok'] = isset($cfields_set[$cf_name])) ) + { + $cfield_id = $cfields_set[$cf_name]['id']; + } + else + { + $ret['msg'] = sprintf($lbl['no_cfield_with_this_name'],$cf_name); + } + } + + if($ret['status_ok']) + { + // go for the test case + } + + return $ret; + } } // end class ?> \ No newline at end of file From 6f4ce31bd8bd78f540e6fa76ce124ddcb8e05201 Mon Sep 17 00:00:00 2001 From: amkhullar <> Date: Mon, 8 Nov 2010 11:30:44 +0000 Subject: [PATCH 0004/1141] *** empty log message *** --- lib/functions/requirements.inc.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/functions/requirements.inc.php b/lib/functions/requirements.inc.php index 1a4c1fd66c..7b5c581c56 100644 --- a/lib/functions/requirements.inc.php +++ b/lib/functions/requirements.inc.php @@ -8,11 +8,12 @@ * @package TestLink * @author Martin Havlat * @copyright 2007-2009, TestLink community - * @version CVS: $Id: requirements.inc.php,v 1.115 2010/11/06 18:46:33 amkhullar Exp $ + * @version CVS: $Id: requirements.inc.php,v 1.116 2010/11/08 11:30:44 amkhullar Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: * + * 20101106 - amitkhullar - BUGID 3978: BTS integration Code getting triggered * 20100919 - franciscom - importReqDataFromCSV() refactoring * importReqDataFromDocBook() added missing keys on generated map * 20100904 - franciscom - BUGID 0003745: CSV Requirements Import Updates Frozen Requirement @@ -33,7 +34,7 @@ /** inlude basic functions for printing Test Specification document */ //require_once("print.inc.php"); //TODO is this needed here anymore after removal of render functions? - +// BUGID 3978 /** * exportReqDataToXML From d28cb0c21dfccc386e052505d1c2225397b72f66 Mon Sep 17 00:00:00 2001 From: asimon83 <> Date: Tue, 9 Nov 2010 11:11:28 +0000 Subject: [PATCH 0005/1141] BUGID 3989 --- config.inc.php | 6 ++- lib/functions/cfield_mgr.class.php | 39 +++++++++++++++----- lib/functions/requirement_mgr.class.php | 11 ++++-- lib/functions/requirement_spec_mgr.class.php | 17 ++++++--- lib/functions/testcase.class.php | 11 ++++-- lib/functions/testplan.class.php | 13 ++++--- lib/functions/testsuite.class.php | 11 ++++-- 7 files changed, 77 insertions(+), 31 deletions(-) diff --git a/config.inc.php b/config.inc.php index 3d46d4c839..c8c3dee9ba 100644 --- a/config.inc.php +++ b/config.inc.php @@ -18,10 +18,11 @@ * * @package TestLink * @copyright 2005-2009, TestLink community - * @version CVS: $Id: config.inc.php,v 1.333 2010/10/30 07:50:43 franciscom Exp $ + * @version CVS: $Id: config.inc.php,v 1.334 2010/11/09 11:11:28 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: + * 20101109 - asimon - added $tlCfg->custom_fields->show_custom_fields_without_value * 20101030 - franciscom - bullet image config removed * 20101028 - Julian - BUGID 3950 - added $tlCfg->gui->dynamic_quick_tcase_search_input_size * 20101014 - Julian - BUGID 3893 - added $tlCfg->metrics_dashboard->show_test_plan_status @@ -1210,6 +1211,9 @@ $tlCfg->default_roleid = TL_ROLES_GUEST; +// only show custom fields if their value isn't empty +$tlCfg->custom_fields->show_custom_fields_without_value = true; + /** used to check size in char for TEXT AREA type custom fields */ // can not be greater that column definition on DB // 0 => do not check. diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index 442f597821..5266aa2c91 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,10 +7,11 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.96 2010/11/06 11:43:09 amkhullar Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.97 2010/11/09 11:11:28 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: + * 20101109 - asimon - BUGID 3989: save custom field values only to db if they are not empty * 20101104 - amitkhullar - Updated Order By Clause in get_linked_to_testproject() * 20101026 - asimon - BUGID 3930: changing date format according to given locale * 20101025 - asimon - BUGID 3716: date pull downs changed to calendar interface @@ -854,14 +855,16 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) } $safe_value=$this->db->prepare_string($value); - if($this->db->num_rows( $result ) > 0 ) + // BUGID 3989 + if($this->db->num_rows( $result ) > 0 && $value != "") { $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_design_values']} " . " SET value='{$safe_value}' " . " WHERE field_id={$field_id} AND node_id={$node_id}"; } - else + // BUGID 3989 + else if ($value != "") { # Remark got from Mantis code: # Always store the value, even if it's the dafault value @@ -870,7 +873,11 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) $sql = "/* $debugMsg */ INSERT INTO {$this->tables['cfield_design_values']} " . " ( field_id, node_id, value ) " . " VALUES ( {$field_id}, {$node_id}, '{$safe_value}' )"; - } + // BUGID 3989 + } else { + $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_design_values']} " . + " WHERE field_id={$field_id} AND node_id={$node_id}"; + } $this->db->exec_query($sql); } //foreach($cfield } //if( !is_null($cfield) ) @@ -1654,14 +1661,16 @@ function execution_values_to_db($hash,$node_id,$execution_id,$testplan_id, $safe_value=$this->db->prepare_string($value); // file_put_contents('c:\sql-count.txt',$this->db->num_rows( $result )); - if( count($rs) > 0 ) //$this->db->num_rows($result) > 0 ) + // BUGID 3989 + if( count($rs) > 0 && $value != "") //$this->db->num_rows($result) > 0 ) { $sql = "UPDATE {$this->tables['cfield_execution_values']} " . " SET value='{$safe_value}' " . $where_clause; // file_put_contents('c:\update.txt',$sql); } - else + // BUGID 3989 + else if ($value != "") { # Remark got from Mantis code: @@ -1673,7 +1682,11 @@ function execution_values_to_db($hash,$node_id,$execution_id,$testplan_id, " VALUES ( {$field_id}, {$node_id}, {$execution_id}, {$testplan_id}, '{$safe_value}' )"; // file_put_contents('c:\insert.txt',$sql); - } + // BUGID 3989 + } else { + $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_execution_values']} " . + " WHERE field_id={$field_id} AND node_id={$node_id}"; + } $this->db->exec_query($sql); } //foreach($cfield @@ -2100,14 +2113,16 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash } $safe_value=$this->db->prepare_string($value); - if($this->db->num_rows( $result ) > 0 ) + // BUGID 3989 + if($this->db->num_rows( $result ) > 0 && $value != "") { $sql = "UPDATE {$this->tables['cfield_testplan_design_values']} " . " SET value='{$safe_value}' " . " WHERE field_id={$field_id} AND link_id={$link_id}"; } - else + // BUGID 3989 + else if ($value != "") { # Remark got from Mantis code: # Always store the value, even if it's the dafault value @@ -2116,7 +2131,11 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash $sql = "INSERT INTO {$this->tables['cfield_testplan_design_values']} " . " ( field_id, link_id, value ) " . " VALUES ( {$field_id}, {$link_id}, '{$safe_value}' )"; - } + // BUGID 3989 + } else { + $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testplan_design_values']} " . + " WHERE field_id={$field_id} AND node_id={$node_id}"; + } $this->db->exec_query($sql); } //foreach($cfield } //if( !is_null($cfield) ) diff --git a/lib/functions/requirement_mgr.class.php b/lib/functions/requirement_mgr.class.php index 5a20960a8a..14f2721dee 100644 --- a/lib/functions/requirement_mgr.class.php +++ b/lib/functions/requirement_mgr.class.php @@ -5,14 +5,15 @@ * * Filename $RCSfile: requirement_mgr.class.php,v $ * - * @version $Revision: 1.114 $ - * @modified $Date: 2010/10/12 05:52:38 $ by $Author: franciscom $ + * @version $Revision: 1.115 $ + * @modified $Date: 2010/11/09 11:11:28 $ by $Author: asimon83 $ * @author Francisco Mancardi * * Manager for requirements. * Requirements are children of a requirement specification (requirements container) * * rev: + * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101012 - franciscom - html_table_of_custom_field_inputs() refactoring to use new method on cfield_mgr class * 20101011 - franciscom - BUGID 3886: CF Types validation - changes in html_table_of_custom_field_inputs() * 20101011 - Julian - BUGID 3876: Values of custom fields are not displayed when editing requirement @@ -1496,12 +1497,16 @@ function html_table_of_custom_field_values($id,$version_id) $cf_map = $this->get_linked_cfields($id,$version_id,$PID_NO_NEEDED); + // BUGID 3989 + $show_cf = config_get('custom_fields')->show_custom_fields_without_value; + if(!is_null($cf_map)) { foreach($cf_map as $cf_id => $cf_info) { // if user has assigned a value, then node_id is not null - if($cf_info['node_id']) + // BUGID 3989 + if($cf_info['node_id'] || $show_cf) { $label = str_replace(TL_LOCALIZE_TAG,'', lang_get($cf_info['label'],null,$NO_WARNING_IF_MISSING)); diff --git a/lib/functions/requirement_spec_mgr.class.php b/lib/functions/requirement_spec_mgr.class.php index 3285453814..b2b1d63d1f 100644 --- a/lib/functions/requirement_spec_mgr.class.php +++ b/lib/functions/requirement_spec_mgr.class.php @@ -5,16 +5,16 @@ * * Filename $RCSfile: requirement_spec_mgr.class.php,v $ * - * @version $Revision: 1.87 $ - * @modified $Date: 2010/09/19 17:43:52 $ by $Author: franciscom $ + * @version $Revision: 1.88 $ + * @modified $Date: 2010/11/09 11:11:28 $ by $Author: asimon83 $ * @author Francisco Mancardi * * Manager for requirement specification (requirement container) * - * @internal revision: + * @internal revision: + * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20100908 - franciscom - BUGID 3762 Import Req Spec - custom fields values are ignored * createFromXML() - * * 20100320 - franciscom - xmlToMapReqSpec() added attributes: type,total_req * 20100311 - franciscom - fixed bug due to missed isset() control * 20100307 - amitkhullar - small bug fix for Requirements based report. @@ -1258,12 +1258,17 @@ function html_table_of_custom_field_values($id,$tproject_id) $NO_WARNING_IF_MISSING=true; $cf_smarty = ''; $cf_map = $this->get_linked_cfields($id,$tproject_id); - if(!is_null($cf_map)) + + // BUGID 3989 + $show_cf = config_get('custom_fields')->show_custom_fields_without_value; + + if(!is_null($cf_map)) { foreach($cf_map as $cf_id => $cf_info) { // if user has assigned a value, then node_id is not null - if($cf_info['node_id']) + // BUGID 3989 + if($cf_info['node_id'] || $show_cf) { $label = str_replace(TL_LOCALIZE_TAG,'', lang_get($cf_info['label'],null,$NO_WARNING_IF_MISSING)); diff --git a/lib/functions/testcase.class.php b/lib/functions/testcase.class.php index 2052370b0b..fc7e6bf422 100644 --- a/lib/functions/testcase.class.php +++ b/lib/functions/testcase.class.php @@ -6,11 +6,12 @@ * @package TestLink * @author Francisco Mancardi ([email protected]) * @copyright 2005-2009, TestLink community - * @version CVS: $Id: testcase.class.php,v 1.332 2010/11/07 20:11:20 franciscom Exp $ + * @version CVS: $Id: testcase.class.php,v 1.333 2010/11/09 11:11:28 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: * + * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101107 - franciscom - BUGID 3843 - get_id_by_custom_field() (WIP) * 20101030 - franciscom - get_by_external() interface changes * get_basic_info() interface changes @@ -4078,13 +4079,17 @@ function html_table_of_custom_field_values($id,$scope='design',$filters=null,$ex $testplan_id,$tproject_id,$location); break; } - + + // BUGID 3989 + $show_cf = config_get('custom_fields')->show_custom_fields_without_value; + if(!is_null($cf_map)) { foreach($cf_map as $cf_id => $cf_info) { // if user has assigned a value, then node_id is not null - if(isset($cf_info['node_id']) ) + // BUGID 3989 + if(isset($cf_info['node_id']) || $show_cf) { // true => do not create input in audit log $label=str_replace(TL_LOCALIZE_TAG,'',lang_get($cf_info['label'],null,true)); diff --git a/lib/functions/testplan.class.php b/lib/functions/testplan.class.php index 78843dda49..56f4cba53b 100644 --- a/lib/functions/testplan.class.php +++ b/lib/functions/testplan.class.php @@ -9,13 +9,13 @@ * @package TestLink * @author franciscom * @copyright 2007-2009, TestLink community - * @version CVS: $Id: testplan.class.php,v 1.235 2010/11/01 11:43:00 franciscom Exp $ + * @version CVS: $Id: testplan.class.php,v 1.236 2010/11/09 11:11:28 asimon83 Exp $ * @link http://www.teamst.org/index.php * * * @internal Revisions: + * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101101 - franciscom - exportTestPlanDataToXML() interface changes + changes in output (more info added) - * * 20101030 - amitkhullar - BUGID 3845 delete() - Reordered deletion of tables due to error generated * when using this method as part of Test Project delete. * (Postgres complains due to use of Foreing Keys). @@ -2467,8 +2467,10 @@ function html_table_of_custom_field_values($id,$scope='design',$filters=null,$fo $add_table=isset($formatOptions['add_table']) ? $formatOptions['add_table'] : true; $table_style=isset($formatOptions['table_css_style']) ? $formatOptions['table_css_style'] : $table_style; } - - + + // BUGID 3989 + $show_cf = config_get('custom_fields')->show_custom_fields_without_value; + if( $scope=='design' ) { $cf_map=$this->get_linked_cfields_at_design($id,$parent_id,$filters); @@ -2483,7 +2485,8 @@ function html_table_of_custom_field_values($id,$scope='design',$filters=null,$fo foreach($cf_map as $cf_id => $cf_info) { // if user has assigned a value, then node_id is not null - if(isset($cf_info['node_id']) && $cf_info['node_id']) + // BUGID 3989 + if(isset($cf_info['node_id']) || $cf_info['node_id'] || $show_cf) { // true => do not create input in audit log $label=str_replace(TL_LOCALIZE_TAG,'',lang_get($cf_info['label'],null,true)); diff --git a/lib/functions/testsuite.class.php b/lib/functions/testsuite.class.php index 9dd7b16468..df44fc320d 100644 --- a/lib/functions/testsuite.class.php +++ b/lib/functions/testsuite.class.php @@ -6,11 +6,12 @@ * @package TestLink * @author franciscom * @copyright 2005-2009, TestLink community - * @version CVS: $Id: testsuite.class.php,v 1.106 2010/10/12 19:06:20 franciscom Exp $ + * @version CVS: $Id: testsuite.class.php,v 1.107 2010/11/09 11:11:28 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: * + * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101012 - franciscom - html_table_of_custom_field_inputs() refactoring to use new method on cfield_mgr class * 20101009 - franciscom - exportTestSuiteDataToXML() - better checks on $optExport * 20100920 - franciscom - html_table_of_custom_field_values() changed keys on $formatOptions @@ -1266,7 +1267,10 @@ function html_table_of_custom_field_values($id,$scope='design',$show_on_executio $cf_smarty=''; $parent_id=null; - + + // BUGID 3989 + $show_cf = config_get('custom_fields')->show_custom_fields_without_value; + if( $scope=='design' ) { $cf_map = $this->get_linked_cfields_at_design($id,$parent_id,$filters,$tproject_id); @@ -1283,7 +1287,8 @@ function html_table_of_custom_field_values($id,$scope='design',$show_on_executio foreach($cf_map as $cf_id => $cf_info) { // if user has assigned a value, then node_id is not null - if($cf_info['node_id']) + // BUGID 3989 + if($cf_info['node_id'] || $show_cf) { // true => do not create input in audit log $label=str_replace(TL_LOCALIZE_TAG,'',lang_get($cf_info['label'],null,true)); From 97e9323245a5088b7dc31c7048b00a4b10cdef82 Mon Sep 17 00:00:00 2001 From: asimon83 <> Date: Tue, 9 Nov 2010 14:58:41 +0000 Subject: [PATCH 0006/1141] BUGID 3989: save custom field values only to db if they are not empty --- lib/functions/cfield_mgr.class.php | 40 ++++++++++++++++-------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index 5266aa2c91..89adee3b28 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,7 +7,7 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.97 2010/11/09 11:11:28 asimon83 Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.98 2010/11/09 14:58:41 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -862,6 +862,7 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_design_values']} " . " SET value='{$safe_value}' " . " WHERE field_id={$field_id} AND node_id={$node_id}"; + $this->db->exec_query($sql); } // BUGID 3989 else if ($value != "") @@ -873,12 +874,14 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) $sql = "/* $debugMsg */ INSERT INTO {$this->tables['cfield_design_values']} " . " ( field_id, node_id, value ) " . " VALUES ( {$field_id}, {$node_id}, '{$safe_value}' )"; + $this->db->exec_query($sql); // BUGID 3989 } else { $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_design_values']} " . " WHERE field_id={$field_id} AND node_id={$node_id}"; + $this->db->exec_query($sql); } - $this->db->exec_query($sql); + } //foreach($cfield } //if( !is_null($cfield) ) @@ -1644,14 +1647,13 @@ function execution_values_to_db($hash,$node_id,$execution_id,$testplan_id, $where_clause = " WHERE field_id={$field_id} AND tcversion_id={$node_id} " . " AND execution_id={$execution_id} AND testplan_id={$testplan_id}" ; + $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__; // do I need to update or insert this value? $sql = " SELECT value,field_id,execution_id " . " FROM {$this->tables['cfield_execution_values']} " . $where_clause; - // file_put_contents('c:\sql.txt',$sql); $rs = $this->db->get_recordset($sql); - // file_put_contents('c:\sql-dd.txt',serialize($rs)); // max_length_value = 0 => no limit if( $this->max_length_value > 0 && tlStringLen($value) > $this->max_length_value) @@ -1660,17 +1662,16 @@ function execution_values_to_db($hash,$node_id,$execution_id,$testplan_id, } $safe_value=$this->db->prepare_string($value); - // file_put_contents('c:\sql-count.txt',$this->db->num_rows( $result )); // BUGID 3989 if( count($rs) > 0 && $value != "") //$this->db->num_rows($result) > 0 ) { $sql = "UPDATE {$this->tables['cfield_execution_values']} " . " SET value='{$safe_value}' " . $where_clause; - // file_put_contents('c:\update.txt',$sql); + $this->db->exec_query($sql); } // BUGID 3989 - else if ($value != "") + else if (count($rs) == 0 && $value != "") { # Remark got from Mantis code: @@ -1680,19 +1681,17 @@ function execution_values_to_db($hash,$node_id,$execution_id,$testplan_id, $sql = "INSERT INTO {$this->tables['cfield_execution_values']} " . " ( field_id, tcversion_id, execution_id,testplan_id,value ) " . " VALUES ( {$field_id}, {$node_id}, {$execution_id}, {$testplan_id}, '{$safe_value}' )"; - // file_put_contents('c:\insert.txt',$sql); - + $this->db->exec_query($sql); + // BUGID 3989 - } else { + } else if (count($rs) > 0 && $value == "") { $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_execution_values']} " . - " WHERE field_id={$field_id} AND node_id={$node_id}"; + $where_clause; + $this->db->exec_query($sql); } - - $this->db->exec_query($sql); + } //foreach($cfield } //if( !is_null($cfield) ) - // file_put_contents('c:\bye.txt','bye'); - } //function end @@ -2091,7 +2090,7 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash { return; } - + $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__; $cfield = is_null($hash_type) ? $this->_build_cfield($hash,$cf_map) : $hash; if( !is_null($cfield) ) { @@ -2120,9 +2119,10 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash $sql = "UPDATE {$this->tables['cfield_testplan_design_values']} " . " SET value='{$safe_value}' " . " WHERE field_id={$field_id} AND link_id={$link_id}"; + $this->db->exec_query($sql); } // BUGID 3989 - else if ($value != "") + else if ($this->db->num_rows( $result ) == 0 && $value != "") { # Remark got from Mantis code: # Always store the value, even if it's the dafault value @@ -2131,12 +2131,14 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash $sql = "INSERT INTO {$this->tables['cfield_testplan_design_values']} " . " ( field_id, link_id, value ) " . " VALUES ( {$field_id}, {$link_id}, '{$safe_value}' )"; + $this->db->exec_query($sql); // BUGID 3989 - } else { + } else if ($this->db->num_rows( $result ) > 0 && $value == "") { $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testplan_design_values']} " . " WHERE field_id={$field_id} AND node_id={$node_id}"; + $this->db->exec_query($sql); } - $this->db->exec_query($sql); + } //foreach($cfield } //if( !is_null($cfield) ) From c52a690756eeb3d02bc302dbf7ef44e44fa67b93 Mon Sep 17 00:00:00 2001 From: asimon83 <> Date: Tue, 9 Nov 2010 15:27:19 +0000 Subject: [PATCH 0007/1141] BUGID 3989 --- lib/functions/cfield_mgr.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index 89adee3b28..bb707e0c96 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,7 +7,7 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.98 2010/11/09 14:58:41 asimon83 Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.99 2010/11/09 15:27:19 asimon83 Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -2132,11 +2132,11 @@ function testplan_design_values_to_db($hash,$node_id,$link_id,$cf_map=null,$hash " ( field_id, link_id, value ) " . " VALUES ( {$field_id}, {$link_id}, '{$safe_value}' )"; $this->db->exec_query($sql); - // BUGID 3989 - } else if ($this->db->num_rows( $result ) > 0 && $value == "") { - $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testplan_design_values']} " . - " WHERE field_id={$field_id} AND node_id={$node_id}"; - $this->db->exec_query($sql); + // BUGID 3989 + } else if ($this->db->num_rows( $result ) > 0 && $value == "") { + $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testplan_design_values']} " . + " WHERE field_id={$field_id} AND link_id={$link_id}"; + $this->db->exec_query($sql); } } //foreach($cfield From 8820baf3cc2cbde3bfd87e9c3313dcc13d37d4f1 Mon Sep 17 00:00:00 2001 From: amkhullar <> Date: Wed, 10 Nov 2010 07:05:16 +0000 Subject: [PATCH 0008/1141] BUGID 3995 Custom Field Filters not working properly since the cf_hash is array --- lib/functions/testplan.class.php | 34 ++++++++++++++---- lib/functions/treeMenu.inc.php | 60 ++++++++++++++++++++++---------- 2 files changed, 69 insertions(+), 25 deletions(-) diff --git a/lib/functions/testplan.class.php b/lib/functions/testplan.class.php index 56f4cba53b..4de36dad2a 100644 --- a/lib/functions/testplan.class.php +++ b/lib/functions/testplan.class.php @@ -9,11 +9,12 @@ * @package TestLink * @author franciscom * @copyright 2007-2009, TestLink community - * @version CVS: $Id: testplan.class.php,v 1.236 2010/11/09 11:11:28 asimon83 Exp $ + * @version CVS: $Id: testplan.class.php,v 1.237 2010/11/10 07:05:16 amkhullar Exp $ * @link http://www.teamst.org/index.php * * * @internal Revisions: + * 20101110 - amitkhullar - BUGID 3995 Custom Field Filters not working properly since the cf_hash is array * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101101 - franciscom - exportTestPlanDataToXML() interface changes + changes in output (more info added) * 20101030 - amitkhullar - BUGID 3845 delete() - Reordered deletion of tables due to error generated @@ -2524,12 +2525,30 @@ function filter_cf_selection ($tp_tcs, $cf_hash) // BUGID 3809 - Radio button based Custom Fields not working $or_clause = ''; $cf_query = ''; - foreach ($cf_hash as $cf_id => $cf_value) - { - $cf_query .= $or_clause . " (CFD.field_id=" . $cf_id . " AND CFD.value='" . $cf_value . "') "; - $or_clause = ' or '; + //BUGID 3995 Custom Field Filters not working properly since the cf_hash is array + if (isset($cf_hash)) { + $suffix = 1; + + foreach ($cf_hash as $cf_id => $cf_value) { + // single value or array? + if (is_array($cf_value)) { + $cf_query .= " AND ( "; + $count = 1; + foreach ($cf_value as $value) { + if ($count > 1) { + $cf_query .= " AND "; + } + $cf_query .= " ( CFD.value LIKE '%{$value}%' AND CFD.field_id = {$cf_id} )"; + $count++; + } + $cf_query .= " ) "; + } else { + $cf_query .= " AND CFD.value LIKE '%{$cf_value}%' "; + } + $suffix ++; + } } - + $cf_qty = count($cf_hash); foreach ($tp_tcs as $tc_id => $tc_value) { @@ -2537,7 +2556,8 @@ function filter_cf_selection ($tp_tcs, $cf_hash) $sql = " /* $debugMsg */ SELECT CFD.value FROM {$this->tables['cfield_design_values']} CFD," . " {$this->tables['nodes_hierarchy']} NH" . " WHERE CFD.node_id = NH.id " . - " AND NH.parent_id = {$tc_value['tc_id']} AND ({$cf_query})"; + " AND NH.parent_id = {$tc_value['tc_id']} " . + " {$cf_query} "; $rows = $this->db->fetchRowsIntoMap($sql,'value'); // if there exist as many rows as custom fields to be filtered by => tc does meet the criteria diff --git a/lib/functions/treeMenu.inc.php b/lib/functions/treeMenu.inc.php index 7daec3840c..9c9a69b3a7 100644 --- a/lib/functions/treeMenu.inc.php +++ b/lib/functions/treeMenu.inc.php @@ -8,22 +8,23 @@ * @package TestLink * @author Martin Havlat * @copyright 2005-2009, TestLink community - * @version CVS: $Id: treeMenu.inc.php,v 1.154 2010/10/10 14:45:20 franciscom Exp $ + * @version CVS: $Id: treeMenu.inc.php,v 1.155 2010/11/10 07:05:16 amkhullar Exp $ * @link http://www.teamst.org/index.php * @uses config.inc.php * * @internal Revisions: - * 20101010 - franciscom - added testlink_node_name as new attribute to be accessed while working with EXT-JS tree - * 20101003 - franciscom - generateExecTree() - added option remove_empty_nodes_of_type on get_subtree() call + * 20101110 - amitkhullar - BUGID 3995 Custom Field Filters not working properly since the cf_hash is array + * 20101010 - franciscom - added testlink_node_name as new attribute to be accessed while working with EXT-JS tree + * 20101003 - franciscom - generateExecTree() - added option remove_empty_nodes_of_type on get_subtree() call * 20100929 - asimon - BUGID 3814: fixed keyword filtering with "and" selected as type * 20100926 - amitkhullar - BUGID 3806 - Filter not working in tree menu for Assign TC Execution - * 20100912 - franciscom - BUGID 3772: MS SQL - LIMIT CLAUSE can not be used - * 20100908 - Julian - BUGID 2877 - Custom Fields linked to Req versions + * 20100912 - franciscom - BUGID 3772: MS SQL - LIMIT CLAUSE can not be used + * 20100908 - Julian - BUGID 2877 - Custom Fields linked to Req versions * - Custom Fields linked to TC versions - * 20100908 - franciscom - extjs_renderExecTreeNodeOnOpen() - 'tlNodeType' -> testlink_node_type + * 20100908 - franciscom - extjs_renderExecTreeNodeOnOpen() - 'tlNodeType' -> testlink_node_type * 20100820 - asimon - refactoring for less redundant checks and better readibility of code * in generateExecTree() - * 20100812 - franciscom - get_filtered_req_map() - BUGID 3671 + * 20100812 - franciscom - get_filtered_req_map() - BUGID 3671 * 20100810 - asimon - added filtering by TC ID on prepareNode() and generateTestSpecTree() * 20100808 - asimon - generate_reqspec_tree() implemented to generate statically filtered * requirement specification tree, plus additional functions @@ -40,7 +41,7 @@ * 20100622 - asimon - refactoring of following functions for new filter classes: * generateExecTree, renderExecTreeNode(), prepareNode(), * generateTestSpecTree, renderTreeNode(), filter_by_*() - * 20100611 - franciscom - renderExecTreeNode(), renderTreeNode() interface changes + * 20100611 - franciscom - renderExecTreeNode(), renderTreeNode() interface changes * generateExecTree() - interface changes and output changes * 20100602 - franciscom - extjs_renderExecTreeNodeOnOpen() - added 'tlNodeType' * 20100428 - asimon - BUGID 3301 and related: @@ -49,18 +50,18 @@ * "undefined" error in event log, * added function filter_by_cfield_values() * which is used from generateTestSpecTree() - * 20100417 - franciscom - BUGID 2498 - spec tree - filter by test case spec importance - * 20100417 - franciscom - BUGID 3380 - execution tree - filter by test case execution type - * 20100415 - franciscom - BUGID 2797 - filter by test case execution type - * 20100202 - asimon - changes for filtering, BUGID 2455, BUGID 3026 + * 20100417 - franciscom - BUGID 2498 - spec tree - filter by test case spec importance + * 20100417 - franciscom - BUGID 3380 - execution tree - filter by test case execution type + * 20100415 - franciscom - BUGID 2797 - filter by test case execution type + * 20100202 - asimon - changes for filtering, BUGID 2455, BUGID 3026 * added filter_by_* - functions, changed generateExecTree() - * 20091212 - franciscom - prepareNode(), generateTestSpecTree() interface changes + * 20091212 - franciscom - prepareNode(), generateTestSpecTree() interface changes * added logic to do filtering on test spec for execution type * - * 20090815 - franciscom - get_last_execution() call changes + * 20090815 - franciscom - get_last_execution() call changes * 20090801 - franciscom - table prefix missed - * 20090716 - franciscom - BUGID 2692 - * 20090328 - franciscom - BUGID 2299 - introduced on 20090308. + * 20090716 - franciscom - BUGID 2692 + * 20090328 - franciscom - BUGID 2299 - introduced on 20090308. * Added logic to remove Empty Top level test suites * (have neither test cases nor test suites inside) when applying * test case keyword filtering. @@ -232,7 +233,6 @@ function generateTestSpecTree(&$db,$tproject_id, $tproject_name,$linkto,$filters // BUGID 3301 - added filtering by custom field values if (isset($my['filters']['filter_custom_fields']) && isset($test_spec['childNodes'])) { - $test_spec['childNodes'] = filter_by_cf_values($test_spec['childNodes'], $my['filters']['filter_custom_fields'], $db, $tsuite_node_type, $tcase_node_type); @@ -1500,7 +1500,31 @@ function filter_by_cf_values(&$tcase_tree, &$cf_hash, &$db, $node_type_testsuite $sql = " /* $debugMsg */ SELECT CFD.value FROM {$tables['cfield_design_values']} CFD," . " {$tables['nodes_hierarchy']} NH" . " WHERE CFD.node_id = NH.id" . - " AND NH.parent_id = {$node['id']} AND value in ('" . implode("' , '",$cf_hash) . "')"; + " AND NH.parent_id = {$node['id']} "; + // AND value in ('" . implode("' , '",$cf_hash) . "')"; + //BUGID 3995 Custom Field Filters not working properly since the cf_hash is array + if (isset($cf_hash)) { + $suffix = 1; + + foreach ($cf_hash as $cf_id => $cf_value) { + // single value or array? + if (is_array($cf_value)) { + $sql .= " AND ( "; + $count = 1; + foreach ($cf_value as $value) { + if ($count > 1) { + $sql .= " AND "; + } + $sql .= " ( CFD.value LIKE '%{$value}%' AND CFD.field_id = {$cf_id} )"; + $count++; + } + $sql .= " ) "; + } else { + $sql .= " AND CFD.value LIKE '%{$cf_value}%' "; + } + $suffix ++; + } + } $rows = $db->fetchRowsIntoMap($sql,'value'); From df27d1b8bd359bf494c800f21e48de2ee91a5fdc Mon Sep 17 00:00:00 2001 From: mx-julian <> Date: Wed, 10 Nov 2010 09:48:37 +0000 Subject: [PATCH 0009/1141] BUGID 3989 - improved else if statements --- lib/functions/cfield_mgr.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index bb707e0c96..cce1caf48a 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,7 +7,7 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.99 2010/11/09 15:27:19 asimon83 Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.100 2010/11/10 09:48:37 mx-julian Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -865,7 +865,7 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) $this->db->exec_query($sql); } // BUGID 3989 - else if ($value != "") + else if ($this->db->num_rows( $result ) == 0 && $value != "") { # Remark got from Mantis code: # Always store the value, even if it's the dafault value @@ -876,7 +876,7 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) " VALUES ( {$field_id}, {$node_id}, '{$safe_value}' )"; $this->db->exec_query($sql); // BUGID 3989 - } else { + } else if ($this->db->num_rows( $result ) > 0 && $value == 0) { $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_design_values']} " . " WHERE field_id={$field_id} AND node_id={$node_id}"; $this->db->exec_query($sql); From f2323d087e1166c088918f28bf954ebd2cc33d73 Mon Sep 17 00:00:00 2001 From: mx-julian <> Date: Wed, 10 Nov 2010 09:52:51 +0000 Subject: [PATCH 0010/1141] fixed wrong comparison of value --- lib/functions/cfield_mgr.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index cce1caf48a..15a29deaf2 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,7 +7,7 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.100 2010/11/10 09:48:37 mx-julian Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.101 2010/11/10 09:52:51 mx-julian Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -876,7 +876,7 @@ function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null) " VALUES ( {$field_id}, {$node_id}, '{$safe_value}' )"; $this->db->exec_query($sql); // BUGID 3989 - } else if ($this->db->num_rows( $result ) > 0 && $value == 0) { + } else if ($this->db->num_rows( $result ) > 0 && $value == "") { $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_design_values']} " . " WHERE field_id={$field_id} AND node_id={$node_id}"; $this->db->exec_query($sql); From 64042636dacb5b0067fa903472e3f3b1384cef9f Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 15:09:00 +0000 Subject: [PATCH 0011/1141] BUGID 3992 - getTestCasesForTestPlan() keywords issue BUGID 3991 - getValidKeywordSetById() missing $this in return --- .../php/clientGetTestCasesForTestPlan.php | 37 +++++++++++++++---- lib/api/xmlrpc.class.php | 33 +++++++++++------ 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/lib/api/sample_clients/php/clientGetTestCasesForTestPlan.php b/lib/api/sample_clients/php/clientGetTestCasesForTestPlan.php index 9932aa39b4..5447fcf0e1 100644 --- a/lib/api/sample_clients/php/clientGetTestCasesForTestPlan.php +++ b/lib/api/sample_clients/php/clientGetTestCasesForTestPlan.php @@ -5,8 +5,8 @@ * * Filename $RCSfile: clientGetTestCasesForTestPlan.php,v $ * - * @version $Revision: 1.5 $ - * @modified $Date: 2010/07/15 16:27:25 $ by $Author: franciscom $ + * @version $Revision: 1.6 $ + * @modified $Date: 2010/11/10 15:09:00 $ by $Author: franciscom $ * @Author: [email protected] * * rev: @@ -21,9 +21,10 @@ $test_num=1; $unitTestDescription="Test {$test_num} - {$method}"; +$tplan_id = 3020; $args=array(); $args["devKey"]=DEV_KEY; -$args["testplanid"]=227; +$args["testplanid"]=$tplan_id; $args["executiontype"]=2; $additionalInfo=''; @@ -42,9 +43,9 @@ $args=array(); $args["devKey"]=DEV_KEY; -$args["testplanid"]=227; -$args["keywords"]='KU,UOL'; -$additionalInfo='Filter by Keyword name'; +$args["testplanid"]=$tplan_id; +$args["keywords"]='Key Feature'; +$additionalInfo='Filter by Keyword name - JUST ONE KEYWORD'; $debug=true; echo $unitTestDescription; @@ -61,7 +62,27 @@ $args=array(); $args["devKey"]=DEV_KEY; -$args["testplanid"]=227; +$args["testplanid"]=$tplan_id; +$args["keywords"]='Key Feature,Must have,Obsolete,Performance,System wide,Usability'; +$additionalInfo='Filter by Keyword name - Multiple Keywords - ONLY OR Search'; + +$debug=true; +echo $unitTestDescription; +echo $additionalInfo; + +$client = new IXR_Client($server_url); +$client->debug=$debug; + +$answer = runTest($client,$method,$args,$test_num); +// --------------------------------------------------------------------------------- + + +// --------------------------------------------------------------------------------- +$test_num++; + +$args=array(); +$args["devKey"]=DEV_KEY; +$args["testplanid"]=$tplan_id; $args["getstepsinfo"]=false; $additionalInfo='get steps info: -> false'; @@ -81,7 +102,7 @@ $args=array(); $args["devKey"]=DEV_KEY; -$args["testplanid"]=227; +$args["testplanid"]=$tplan_id; $args["getstepsinfo"]=true; $additionalInfo='get steps info: -> true'; diff --git a/lib/api/xmlrpc.class.php b/lib/api/xmlrpc.class.php index c935f0beb8..dab4539a0b 100644 --- a/lib/api/xmlrpc.class.php +++ b/lib/api/xmlrpc.class.php @@ -5,8 +5,8 @@ * * Filename $RCSfile: xmlrpc.class.php,v $ * - * @version $Revision: 1.23 $ - * @modified $Date: 2010/10/23 09:45:34 $ by $Author: franciscom $ + * @version $Revision: 1.24 $ + * @modified $Date: 2010/11/10 15:09:00 $ by $Author: franciscom $ * @author Asiel Brumfield * @package TestlinkAPI * @@ -22,6 +22,8 @@ * * * rev : + * 20101110 - franciscom - BUGID 3992 - getTestCasesForTestPlan() keywords issue + * BUGID 3991 - getValidKeywordSetById() missing $this in return * 20101023 - franciscom - BUGID 3916: getTestCaseCustomFieldDesignValue() - missing refactoring regarding * custom field values linked to test case version * @@ -2280,7 +2282,7 @@ protected function checkTestCaseIdentity($messagePrefix='') * @param int $args["testplanid"] * @param int $args["testcaseid"] - optional * @param int $args["buildid"] - optional - * @param int $args["keywordid"] - optional mutual exclusive with $args["keywordname"] + * @param int $args["keywordid"] - optional mutual exclusive with $args["keywords"] * @param int $args["keywords"] - optional mutual exclusive with $args["keywordid"] * * @param boolean $args["executed"] - optional @@ -2328,25 +2330,32 @@ public function getTestCasesForTestPlan($args) } } - $keywordSet = null; - $keywordList=$this->getKeywordSet($tplanInfo['parent_id']); - if( !is_null($keywordList) ) - { - $keywordSet = explode(",",$keywordList); - } - + // 20101110 - franciscom + // honors what has been written in documentation + $keywordSet = $opt[self::$keywordIDParamName]; + if( is_null($keywordSet) ) + { + $keywordSet = null; + $keywordList=$this->getKeywordSet($tplanInfo['parent_id']); + if( !is_null($keywordList) ) + { + $keywordSet = explode(",",$keywordList); + } + } // BUGID 3604 $options = array('executed_only' => $opt[self::$executedParamName], 'steps_info' => $opt[self::$getStepsInfoParamName], 'details' => 'full'); + // BUGID 3992 $filters = array('tcase_id' => $opt[self::$testCaseIDParamName], - 'keyword_id' => $opt[self::$keywordIDParamName], + 'keyword_id' => $keywordSet, 'assigned_to' => $opt[self::$assignedToParamName], 'exec_status' => $opt[self::$executeStatusParamName], 'build_id' => $opt[self::$buildIDParamName], 'exec_type' => $opt[self::$executionTypeParamName]); + $recordset=$this->tplanMgr->get_linked_tcversions($tplanid,$filters,$options); return $recordset; } @@ -2676,7 +2685,7 @@ protected function getValidKeywordSet($tproject_id,$keywords,$byName) */ protected function getValidKeywordSetById($tproject_id,$keywords) { - return getValidKeywordSet($tproject_id,$keywords,false); + return $this->getValidKeywordSet($tproject_id,$keywords,false); } From 79c210419c677564813fdef294a3589a5644ab6e Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 15:30:13 +0000 Subject: [PATCH 0012/1141] BUGID 3843 - get_id_by_custom_field() (Work in Progress) --- lib/functions/testcase.class.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/functions/testcase.class.php b/lib/functions/testcase.class.php index fc7e6bf422..2d52e190cd 100644 --- a/lib/functions/testcase.class.php +++ b/lib/functions/testcase.class.php @@ -6,11 +6,12 @@ * @package TestLink * @author Francisco Mancardi ([email protected]) * @copyright 2005-2009, TestLink community - * @version CVS: $Id: testcase.class.php,v 1.333 2010/11/09 11:11:28 asimon83 Exp $ + * @version CVS: $Id: testcase.class.php,v 1.334 2010/11/10 15:30:13 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: * + * 20101110 - franciscom - BUGID 3843 - get_id_by_custom_field() (WIP) * 20101109 - asimon - BUGID 3989: now it is configurable if custom fields without values are shown * 20101107 - franciscom - BUGID 3843 - get_id_by_custom_field() (WIP) * 20101030 - franciscom - get_by_external() interface changes @@ -5013,6 +5014,9 @@ function filter_tcversions_by_cfields($tcversion_id,$cf_hash,$options=null) } /** + * Attention: + * has limited scope i.e.: used to do search on custom fields that hold simple values + * example: strings and numbers. * * */ @@ -5052,6 +5056,14 @@ function get_id_by_custom_field($cf_name, $cf_value, $tproject_id) if($ret['status_ok']) { // go for the test case + // Need to get all node id (will be test case VERSION ID), that has cf with requested value + // After this I need to get ONLY ID of test case that belong to Test Project + // If more than one Test Case exists -> we have a problem ? + // If this method has to be generica, then will be possible + // Check test cases that have a certain value on custom field + // (We alredy are doing this may be in a different way when applying filters on CF values). + // + } return $ret; From 21ecb50121dc56c45c872a93146acb40d419e9ea Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 16:51:35 +0000 Subject: [PATCH 0013/1141] BUGID 3843 -> get_linked_items_at_design() new method --- lib/functions/cfield_mgr.class.php | 43 +++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index 15a29deaf2..4fd69ed559 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,10 +7,11 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.101 2010/11/10 09:52:51 mx-julian Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.102 2010/11/10 16:51:35 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: + * 20101110 - franciscom - BUGID 3843 -> get_linked_items_at_design() new method * 20101109 - asimon - BUGID 3989: save custom field values only to db if they are not empty * 20101104 - amitkhullar - Updated Order By Clause in get_linked_to_testproject() * 20101026 - asimon - BUGID 3930: changing date format according to given locale @@ -2622,6 +2623,46 @@ function getValuesFromUserInput($cf_map,$name_suffix='',$input_values=null) } +/** + * given a CF id and value, returns all node_id that has requested node type + * + * Important Notice: for Test Cases and Requirements (where CF are saved at Version level) + * we have to understand that we use 'testcase' but the real type of node_id + * will be tcversion. + * + * @param int $id Custom Field ID + * @param string $value Custom Field Value + * @param string $node_type verbose node type (see tree.class.php) + * + * @return map key: node_id + * + * @internal revision + * 20101110 - franciscom - created as part of refactoring related to BUGID 3843 + * + */ +function get_linked_items_at_design($id,$value,$node_type) +{ + $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__; + + $hash_descr_id = $this->tree_manager->get_available_node_types(); + $node_type_id=$hash_descr_id[$node_type]; + + $safe_value = $this->db->prepare_string($value); + + $sql="/* $debugMsg */ SELECT CF.name,CFDV.value,CFDV.node_id AS node_id,NH.parent_id" . + " FROM {$this->object_table} CF " . + " JOIN {$this->tables['cfield_node_types']} CFNT ON CFNT.field_id=CF.id " . + " JOIN {$this->tables['cfield_design_values']} CFDV ON CFDV.field_id=CF.id " . + " JOIN {$this->tables['nodes_hierarchy']} NH ON NH.id=CFDV.node_id " . + " WHERE CFNT.node_type_id={$node_type_id} " . + " AND CFDV.value = '{$safe_value}' "; + // echo "
debug - " . __FUNCTION__ . "
" . $sql . "
"; + + + $rs = $this->db->fetchRowsIntoMap($sql,'node_id'); + return($rs); +} + } // end class ?> From 43266b6454583faa2cc4837d1caa8bff9491da7e Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 17:21:13 +0000 Subject: [PATCH 0014/1141] BUGID 3843 -> get_linked_items_at_design() new method --- lib/functions/cfield_mgr.class.php | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/functions/cfield_mgr.class.php b/lib/functions/cfield_mgr.class.php index 4fd69ed559..42a7710948 100644 --- a/lib/functions/cfield_mgr.class.php +++ b/lib/functions/cfield_mgr.class.php @@ -7,7 +7,7 @@ * @author franciscom * @copyright 2005-2009, TestLink community * @copyright Mantis BT team (some parts of code was reuse from the Mantis project) - * @version CVS: $Id: cfield_mgr.class.php,v 1.102 2010/11/10 16:51:35 franciscom Exp $ + * @version CVS: $Id: cfield_mgr.class.php,v 1.103 2010/11/10 17:21:13 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -2633,16 +2633,21 @@ function getValuesFromUserInput($cf_map,$name_suffix='',$input_values=null) * @param int $id Custom Field ID * @param string $value Custom Field Value * @param string $node_type verbose node type (see tree.class.php) + * @param map $options default -> null , get defaults inside method * - * @return map key: node_id + * @return map key: depends of options * * @internal revision * 20101110 - franciscom - created as part of refactoring related to BUGID 3843 * */ -function get_linked_items_at_design($id,$value,$node_type) +function get_linked_items_at_design($id,$value,$node_type,$options=null) { $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__; + + $my['opt'] = array('access_key' => 'node_id', 'secondary:_access_key' => null, + 'cumulative' => !database::CUMULATIVE); + $my['opt'] = array_merge($my['opt'], (array)$options); $hash_descr_id = $this->tree_manager->get_available_node_types(); $node_type_id=$hash_descr_id[$node_type]; @@ -2656,10 +2661,16 @@ function get_linked_items_at_design($id,$value,$node_type) " JOIN {$this->tables['nodes_hierarchy']} NH ON NH.id=CFDV.node_id " . " WHERE CFNT.node_type_id={$node_type_id} " . " AND CFDV.value = '{$safe_value}' "; - // echo "
debug - " . __FUNCTION__ . "
" . $sql . "
"; - - $rs = $this->db->fetchRowsIntoMap($sql,'node_id'); + if( is_null($my['opt']['secondary_access_key']) ) + { + $rs = $this->db->fetchRowsIntoMap($sql,$my['opt']['access_key'],$my['opt']['cumulative']); + } + else + { + $rs = $this->db->fetchMapRowsIntoMap($sql,$my['opt']['access_key'], + $my['opt']['secondary_access_key'],$my['opt']['cumulative']); + } return($rs); } From 798d19b00dce6ab975185b19ec9ef08fcc046402 Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 17:34:25 +0000 Subject: [PATCH 0015/1141] BUGID 3843 - get_id_by_custom_field() work in progress --- lib/functions/testcase.class.php | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/functions/testcase.class.php b/lib/functions/testcase.class.php index 2d52e190cd..8171195f83 100644 --- a/lib/functions/testcase.class.php +++ b/lib/functions/testcase.class.php @@ -6,7 +6,7 @@ * @package TestLink * @author Francisco Mancardi ([email protected]) * @copyright 2005-2009, TestLink community - * @version CVS: $Id: testcase.class.php,v 1.334 2010/11/10 15:30:13 franciscom Exp $ + * @version CVS: $Id: testcase.class.php,v 1.335 2010/11/10 17:34:25 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: @@ -5029,7 +5029,7 @@ function get_id_by_custom_field($cf_name, $cf_value, $tproject_id) $lbl['no_linked_cfields_for_testcase'] = lang_get('no_linked_cfields_for_testcase'); $lbl['no_cfield_with_this_name'] = lang_get('no_cfield_with_this_name'); } - $ret = array('status_ok' => false, 'msg' => '', 'id' => 0); + $ret = array('status_ok' => false, 'msg' => '', 'id' => null); // check if custom field is linked to test project @@ -5059,11 +5059,35 @@ function get_id_by_custom_field($cf_name, $cf_value, $tproject_id) // Need to get all node id (will be test case VERSION ID), that has cf with requested value // After this I need to get ONLY ID of test case that belong to Test Project // If more than one Test Case exists -> we have a problem ? - // If this method has to be generica, then will be possible + // If this method has to be generic, then will be possible // Check test cases that have a certain value on custom field // (We alredy are doing this may be in a different way when applying filters on CF values). // + $cfget_opt = array('access_key' => 'parent_id', 'secondary_access_key' => 'node_id'); + // map key: test case id + // map value: map indexed by test case version id + $itemSet = $this->cfield_mgr->get_linked_items_at_design($cfield_id,$cf_value,'testcase',$cfget_opt); + + // // Now filter result + if( !is_null($itemSet) ) + { + $tcaseSet = array_keys($itemSet); + $cache = array('tproject_id' => array()); + + foreach($tcaseSet as $tcase_id) + { + if( !isset($cache['tproject_id'][$tcase_id]) ) + { + $cache['tproject_id'][$tcase_id] = $this->tree_manager->getTreeRoot($tcase_id); + } + if( $tproject_id == $cache['tproject_id'][$tcase_id] ) + { + $ret['id'] = array($tcase_id => $itemSet[$tcase_id]); + break; + } + } + } } return $ret; From 4b5176806fed387b2493c31fa1304e4f737a110f Mon Sep 17 00:00:00 2001 From: asimon83 <> Date: Wed, 10 Nov 2010 17:46:07 +0000 Subject: [PATCH 0016/1141] BUGID 3822: Keywords combobox was absent on the Filters pane of 'Add / Remove Test Cases' --- lib/functions/tlTestCaseFilterControl.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/functions/tlTestCaseFilterControl.class.php b/lib/functions/tlTestCaseFilterControl.class.php index afc29534f9..dc1cb535f7 100644 --- a/lib/functions/tlTestCaseFilterControl.class.php +++ b/lib/functions/tlTestCaseFilterControl.class.php @@ -6,7 +6,7 @@ * @package TestLink * @author Andreas Simon * @copyright 2006-2010, TestLink community - * @version CVS: $Id: tlTestCaseFilterControl.class.php,v 1.33 2010/11/03 08:06:16 asimon83 Exp $ + * @version CVS: $Id: tlTestCaseFilterControl.class.php,v 1.34 2010/11/10 17:46:07 asimon83 Exp $ * @link http://www.teamst.org/index.php * @filesource http://testlink.cvs.sourceforge.net/viewvc/testlink/testlink/lib/functions/tlTestCaseFilterControl.class.php?view=markup * @@ -35,6 +35,7 @@ * * @internal Revisions: * + * 20101110 - asimon - BUGID 3822: Keywords combobox is absent on the Filters pane of 'Add / Remove Test Cases' * 20101103 - asimon - custom fields on test spec did not retain value after apply * 20101028 - asimon - BUGID 3933: Add test case to test plan - Left Pane filter uses * priority concept to filter test spec where priority does not exist @@ -1185,6 +1186,8 @@ private function init_filter_keywords() { switch ($this->mode) { case 'edit_mode': + // BUGID 3822 + case 'plan_add_mode': // we need the keywords for the whole testproject if (!$this->testproject_mgr) { $this->testproject_mgr = new testproject($this->db); From c72564ae35dffa0dd75afe374fb115a632d047ab Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 18:10:18 +0000 Subject: [PATCH 0017/1141] *** empty log message *** --- locale/en_GB/strings.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/locale/en_GB/strings.txt b/locale/en_GB/strings.txt index b18561cc50..5032ad73a0 100644 --- a/locale/en_GB/strings.txt +++ b/locale/en_GB/strings.txt @@ -24,7 +24,7 @@ * @package TestLink * @author Francisco Mancardi, Andreas Morsing, Martin Havlat * @copyright 2003, TestLink community - * @version CVS: $Id: strings.txt,v 1.752 2010/11/07 20:06:57 franciscom Exp $ + * @version CVS: $Id: strings.txt,v 1.753 2010/11/10 18:10:18 franciscom Exp $ * @link http://www.teamst.org/index.php * * @internal Revisions: Not listed - check repository history @@ -2072,6 +2072,9 @@ $TLS_bug_id_invalid_len = "BUG ID length is invalid [%s > %s] " . $TLS_imp_resul $TLS_tproject_id_not_found = "Test Project ID not found [%s] " . $TLS_imp_result_ko; $TLS_invalid_exec_type = "Execution type code [%s] is not valid" . $TLS_imp_result_ko; $TLS_missing_exec_type = "Execution type code was not provided - using (%s => %s)"; +$TLS_internal_id = "Internal ID:%s"; +$TLS_external_id = "External ID:%s"; + // ----- lib/functions/results.inc.php ----- $TLS_trep_failing = "Failing"; From 79ac68c2eccf15e56e4954f2f47e1943a94fdb9d Mon Sep 17 00:00:00 2001 From: franciscom <> Date: Wed, 10 Nov 2010 18:10:59 +0000 Subject: [PATCH 0018/1141] BUGID 3843 - Contribution - Match testcases on custom fields when importing test results --- lib/results/resultsImport.php | 124 ++++++++++++++++++++++++---------- 1 file changed, 87 insertions(+), 37 deletions(-) diff --git a/lib/results/resultsImport.php b/lib/results/resultsImport.php index aca8fcb4c3..a3dc0c649f 100644 --- a/lib/results/resultsImport.php +++ b/lib/results/resultsImport.php @@ -8,10 +8,11 @@ * @package TestLink * @author Kevin Levy * @copyright 2010, TestLink community - * @version CVS: $Id: resultsImport.php,v 1.22 2010/10/04 19:48:00 franciscom Exp $ + * @version CVS: $Id: resultsImport.php,v 1.23 2010/11/10 18:10:59 franciscom Exp $ * * @internal Revisions: * + * 20101107 - franciscom - BUGID 3843 - Contribution - Match testcases on custom fields when importing test results * 20101004 - franciscom - added new checks other than if( isset($tcase_exec['bug_id']) ) * to avoid warnings on event viewer. * 20100926 - franciscom - BUGID 3751: New attribute "execution type" makes old XML import files incompatible @@ -190,6 +191,7 @@ function: saveImportedResultData returns: rev: + 20101107 - franciscom - BUGID 3843 - Contribution 20100823 - franciscom - BUGID 3543 - added execution_type 20100328 - franciscom - BUGID 3331 manage bug id */ @@ -204,7 +206,8 @@ function saveImportedResultData(&$db,$resultData,$context) $l18n = array('import_results_tc_not_found' => '' ,'import_results_invalid_result' => '', - 'tproject_id_not_found' => '', 'import_results_ok' => ''); + 'tproject_id_not_found' => '', 'import_results_ok' => '', + 'internal_id' => '', 'external_id' => ''); foreach($l18n as $key => $value) { $l18n[$key] = lang_get($key); @@ -233,11 +236,15 @@ function saveImportedResultData(&$db,$resultData,$context) $resultMap=array(); $tplan_mgr=null; $tc_qty=sizeof($resultData); - + $cfields = null; + if($tc_qty) { - $tplan_mgr=new testplan($db); - $tproject_mgr=new testproject($db); + $tplan_mgr = new testplan($db); + $tproject_mgr = new testproject($db); + + // BUGID 3843 + $cfields = $tproject_mgr->get_linked_custom_fields($context->tprojectID,'testcase','name'); } // Need to do checks on common settings @@ -278,6 +285,7 @@ function saveImportedResultData(&$db,$resultData,$context) // -------------------------------------------------------------------- + for($idx=0; $doIt && $idx < $tc_qty;$idx++) { $tester_id = 0; @@ -291,7 +299,9 @@ function saveImportedResultData(&$db,$resultData,$context) // Important NOTICE: // tcase_exec is passed BY REFERENCE to allow check_exec_values()change execution type if needed // - $checks = check_exec_values($db,$tcase_mgr,$user_mgr,$tcaseCfg,$tcase_exec,$columnDef['execution_bugs']); + + $checks = check_exec_values($db,$context->tprojectID,$cfields,$tcase_mgr,$user_mgr,$tcaseCfg, + $tcase_exec,$columnDef['execution_bugs']); $status_ok = $checks['status_ok']; if($status_ok) { @@ -312,7 +322,10 @@ function saveImportedResultData(&$db,$resultData,$context) if( $status_ok) { - $tcase_identity=$using_external_id ? $tcase_external_id : $tcase_id; + $tcase_identity = $using_external_id ? $tcase_external_id : $tcase_id; + $verbose_identity = $using_external_id ? $l18n['external_id'] : $l18n['internal_id']; + $verbose_identity = sprintf($verbose_identity,$tcase_identity); + $result_code=strtolower($tcase_exec['result']); $result_is_acceptable=isset($resulstCfg['code_status'][$result_code]) ? true : false; @@ -323,14 +336,14 @@ function saveImportedResultData(&$db,$resultData,$context) $linked_cases=$tplan_mgr->get_linked_tcversions($context->tplanID,$filters); $info_on_case=$linked_cases[$tcase_id]; - + if (!$linked_cases) { - $message=sprintf($l18n['import_results_tc_not_found'],$tcase_identity); + $message=sprintf($l18n['import_results_tc_not_found'],$verbose_identity); } else if (!$result_is_acceptable) { - $message=sprintf($l18n['import_results_invalid_result'],$tcase_identity,$tcase_exec['result']); + $message=sprintf($l18n['import_results_invalid_result'],$verbose_identity,$tcase_exec['result']); } else { @@ -382,9 +395,10 @@ function saveImportedResultData(&$db,$resultData,$context) } } } - $message=sprintf($l18n['import_results_ok'],$tcase_identity,$version,$tester_name, - $resulstCfg['code_status'][$result_code],$execution_ts); - + + // Improvements on feedback + $message=sprintf($l18n['import_results_ok'],($info_on_case['name'] . " - " . $verbose_identity), + $version,$tester_name,$resulstCfg['code_status'][$result_code],$execution_ts); } } @@ -454,7 +468,6 @@ function importExecutionFromXML(&$xmlTCExec) $execInfo['tester'] = (string) trim($xmlTCExec->tester); $execInfo['execution_type'] = intval((int) trim($xmlTCExec->execution_type)); //BUGID 3543 - $bugQty = count($xmlTCExec->bug_id); if( ($bugQty = count($xmlTCExec->bug_id)) > 0 ) { @@ -463,6 +476,18 @@ function importExecutionFromXML(&$xmlTCExec) $execInfo['bug_id'][] = (string) $bug; // BUGID 3331 } } + + // BUGID 3843 - Contribution + // Can get link to test case using Custom Field + $execInfo['link_by_cf_name'] = null; + $execInfo['link_by_cf_value'] = null; + $link_attrs = $xmlTCExec->linkby->attributes(); + if ($link_attrs) + { + $execInfo['link_by_cf_name'] = (string) $link_attrs->custom_field; + $execInfo['link_by_cf_value'] = (string) $link_attrs->value; + } + return $execInfo; } @@ -546,40 +571,65 @@ function: check_exec_values() msg -> array with localized messages @internal revisions: + 20101107 - franciscom - BUGID 3843 20100926 - franciscom - BUGID 3751: New attribute "execution type" makes old XML import files incompatible Passed $execValues BY REFERENCE to allow change of execution type if needed */ -function check_exec_values(&$db,&$tcase_mgr,&$user_mgr,$tcaseCfg,&$execValues,&$columnDef) +function check_exec_values(&$db,$tproject_id,$cfields,&$tcase_mgr,&$user_mgr,$tcaseCfg,&$execValues,&$columnDef) { $tables = tlObjectWithDB::getDBTables(array('users','execution_bugs')); - $checks=array('status_ok' => false, 'tcase_id' => 0, 'tester_id' => 0, 'msg' => array()); + $checks=array('status_ok' => true, 'tcase_id' => 0, 'tester_id' => 0, 'msg' => array()); - $tcase_id=$execValues['tcase_id']; - $tcase_external_id=trim($execValues['tcase_external_id']); + $tcase_id = $execValues['tcase_id']; + $tcase_external_id = trim($execValues['tcase_external_id']); // external_id has precedence over internal id $using_external_id = ($tcase_external_id != ""); - if($using_external_id) - { - // need to get internal id - $checks['tcase_id']=$tcase_mgr->getInternalID($tcase_external_id,$tcaseCfg->glue_character); - $checks['status_ok']=intval($checks['tcase_id']) > 0 ? true : false; - if(!$checks['status_ok']) - { - $checks['msg'][]=sprintf(lang_get('tcase_external_id_do_not_exists'),$tcase_external_id); - } - } - else - { - // before using internal id, I want to check it's a number - $checks['tcase_id']=$tcase_id; - $checks['status_ok']=intval($checks['tcase_id']) > 0 ? true : false; - if(!$checks['status_ok']) - { - $checks['msg'][]=sprintf(lang_get('tcase_id_is_not_number'),$tcase_id); - } + + // BUGID 3843 - Contribution + // Possibly using custom fields to identify test cases. + if( $tcase_id <= 0 && !$using_external_id) + { + $cf_name = $execValues['link_by_cf_name']; + if( !is_null($cf_name) ) + { + $cf_value = $execValues['link_by_cf_value']; + $ret = $tcase_mgr->get_id_by_custom_field($cf_name,$cf_value,$tproject_id); + + $checks['status_ok'] = $ret['status_ok']; + $checks['msg'][] = $ret['msg']; + if( $ret['status_ok']) + { + $tcase_id = key($ret['id']); + } + } + } + + if( $checks['status_ok'] ) + { + if($using_external_id) + { + // need to get internal id + $checks['tcase_id']=$tcase_mgr->getInternalID($tcase_external_id,$tcaseCfg->glue_character); + $checks['status_ok']=intval($checks['tcase_id']) > 0 ? true : false; + if(!$checks['status_ok']) + { + $checks['msg'][]=sprintf(lang_get('tcase_external_id_do_not_exists'),$tcase_external_id); + } + } + else + { + // before using internal id, I want to check it's a number + $checks['tcase_id']=$tcase_id; + $checks['status_ok']=intval($checks['tcase_id']) > 0 ? true : false; + if(!$checks['status_ok']) + { + $checks['msg'][]=sprintf(lang_get('tcase_id_is_not_number'),$tcase_id); + } + } } + if($checks['status_ok']) { // useful for user feedback From df0dec7e0bf02448b105f9dadad2ec4b4e008314 Mon Sep 17 00:00:00 2001 From: amkhullar <> Date: Thu, 11 Nov 2010 16:50:37 +0000 Subject: [PATCH 0019/1141] BUGID 4011 - Export XML for Requirements also using the same file. --- docs/utils/XLSTOXML.xls | Bin 0 -> 153600 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/utils/XLSTOXML.xls diff --git a/docs/utils/XLSTOXML.xls b/docs/utils/XLSTOXML.xls new file mode 100644 index 0000000000000000000000000000000000000000..d96a3129f0da74d02c3dee0f0f8127c6fe1a094f GIT binary patch literal 153600 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

hto2~$qGx@=o_S!qNiS$#&tU|xuhSlGB( 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