/lib/functions/cfield_mgr.class.php
PHP | 2483 lines | 1242 code | 276 blank | 965 comment | 137 complexity | e97915df1f3c9decff1eda939b21c97b 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
- <?php
- /**
- * TestLink Open Source Project - http://testlink.sourceforge.net/
- * This script is distributed under the GNU General Public License 2 or later.
- *
- * @package TestLink
- * @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.82 2010/08/29 09:26:16 franciscom Exp $
- * @link http://www.teamst.org/index.php
- *
- * @internal Revisions:
- *
- * 20100829 - franciscom - BUGID 3707,3708 usability issue + browser different behaviour
- * 20100825 - eloff - BUGID 3713 - add platform_name to output of get_linked_cfields_at_execution()
- * 20100726 - amitkhullar - BUGID 3555 - sort order while displaying custom fields.
- * 20100701 - asimon - BUGID 3414: removed a single space character in string_custom_field_input()
- * because of an error that was caused by it
- * 20100218 - franciscom - string_custom_field_input() changes on checkbox management
- * 20100204 - franciscom - getByLinkID() - new method
- * 20090823 - franciscom - added logic to remove 255 size limit
- * 20090718 - franciscom - buildLocationMap()
- * 20090717 - franciscom - get_linked_cfields_at_design() - added filter by location
- * get_linked_cfields_at_execution() - location argument
- *
- * 20090607 - franciscom - refactoring to manage table prefix
- * 20090530 - franciscom - execution_values_to_db() added logic to manage insert or update.
- * 20090523 - franciscom - changes on show_on, enable_on logics
- * 20090426 - franciscom - new method getSizeLimit()
- * 20090420 - amitkhullar- BUGID-2410 - get_linked_cfields_at_testplan_design() - added logic to get data
- * for custom field values stores at test plan level.
- * 20090420 - franciscom - BUGID 2158 - get_linked_cfields_at_design() added filter on custom field id
- *
- * 20090408 - franciscom - BUGID 2352 - added new method remove_all_scopes_values();
- * changes in delete()
- *
- * 20090321 - franciscom - fixed bug due to missing code on get_linked_cfields_at_design()
- * 20090321 - franciscom - exportValueAsXML()
- * 20090303 - franciscom - get_linked_cfields_at_execution() - fixed bugs on query
- * and added logic to change fetch method.
- *
- * 20090223 - franciscom - get_linked_cfields_at_execution() - added logic
- * to use this method on report created by:
- * Amit Khullar - amkhullar@gmail.com
- *
- * 20080817 - franciscom - added logic give default logic to manage
- * new custom field types that have no specific code.
- *
- * 20080816 - franciscom - new feature: user defined Custom Fields.
- * Important:
- * solution is a mix of own ideas and Mantis 1.2.0a1 approach.
- * string_custom_field_input(), _build_cfield()
- *
- * added radio type, datetime type.
- *
- *
- * 20080810 - franciscom - documentation improvements
- * BUGID 1650 (REQ)
- * get_linked_cfields_at_design() - interface changes
- *
- * 20080304 - franciscom - prepare_string() before insert
- * 20080216 - franciscom - added testproject name to logAudit recorded information
- * 20071102 - franciscom - BUGID - Feature
- * addition and refactoring of contributed code
- *
- * 20071027 - franciscom - using Mantis (a php based bugtracking system)
- * logic, to improve custom field management
- * adding support for url on string custom fields.
- *
- *
- * 20070617 - franciscom - BUGID insert_id() problems for Postgres and Oracle?
- * 20070501 - franciscom - limiting length of values while writting to db.
- * 20070429 - franciscom - added text area custom field
- * code contributed by Seweryn Plywaczyk
- *
- * 20070227 - franciscom - BUGID 677
- * 20070110 - franciscom - solved bug set_active()
- *
- * 20070105 - franciscom -
- * 1. solved bugs on design_values_to_db()
- * 2. refactoring - design_values_to_db()
- * execution_values_to_db()
- *
- **/
-
- /** load conversion functions */
- require_once(dirname(__FILE__) . '/date_api.php');
- require_once(dirname(__FILE__) . '/string_api.php');
-
- // Copied from mantis, allow load of user custom implementations
- // some sort of poor's man plugin
- $cf_files=glob( TL_ABS_PATH . "custom/cf_*.php");
- if( count($cf_files) > 0 )
- {
- foreach($cf_files as $inc)
- {
- require_once($inc);
- }
- }
-
-
- /**
- * class is responsible for logic and store Custom Fields functionality
- * @package TestLink
- */
- class cfield_mgr extends tlObject
- {
- const DEFAULT_INPUT_SIZE = 50;
- const MULTISELECTIONLIST_WINDOW_SIZE = 5;
- const TEXTAREA_MAX_SIZE = 255;
-
- // EDIT HERE IF YOU CUSTOMIZE YOUR DB
- /** for text area custom field 40 x 6 -> 240 chars <= 255 chars table field size */
- const TEXTAREA_DEFAULT_COLS = 70;
- const TEXTAREA_DEFAULT_ROWS = 4;
-
- const CF_ENABLED = 1;
- const ENABLED = 1;
- const DISABLED = 0;
-
- /** @var resource the database handler */
- var $db;
-
- /** @var object tree class */
- var $tree_manager;
-
- /**
- * @var array $application_areas
- * Holds string keys used on this object and pages that manages CF,
- * identifying in what areas/features something will be done
- * 'execution' => mainly on test execution pages,
- * identifies TL features/pages to record test results
- * 'design' => test suites, test cases creation
- * identifies TL features/pages to create test specification
- * 'testplan_design' => link test cases to test plan (assign testcase option)
- *
- * IMPORTANT: this values are used as access keys in several properties of this object.
- * then if you add one here, remember to update other properties.
- */
- var $application_areas = array('execution','design','testplan_design');
-
- /**
- * @var array Define type of custom fields managed.
- * Values will be displayed in "Custom Field Type" combo box when
- * users create custom fields. No localization is applied
- */
- // 20080809 - franciscom
- // Added specific type for test automation related custom fields.
- // Start at code 500
- var $custom_field_types = array(0=>'string',
- 1=>'numeric',
- 2=>'float',
- 4=>'email',
- 5=>'checkbox',
- 6=>'list',
- 7=>'multiselection list',
- 8=>'date',
- 9=>'radio',
- 10=>'datetime',
- 20=>'text area',
- 500=>'script',
- 501=>'server');
-
- /**
- * @var array Configures for what type of CF "POSSIBLE_VALUES" field need to be manage at GUI level
- * Keys of this map must be the values present in:
- * <code>$this->custom_field_types</code>
- */
- var $possible_values_cfg = array('string' => 0,
- 'numeric'=> 0,
- 'float'=> 0,
- 'email'=> 0,
- 'checkbox' => 1,
- 'list' => 1,
- 'multiselection list' => 1,
- 'date' => 0,
- 'radio' => 1,
- 'datetime' =>0,
- 'text area' => 0,
- 'script'=> 0,
- 'server' => 0);
-
- /** @var array only the types listed here can have custom fields */
- var $node_types = array('testsuite','testplan','testcase','requirement_spec','requirement');
-
- /**
- * @var map of maps $locations
- *
- * Location is place on page where to display custom field.
- * This concept has been created to implement a user contribution, that allows for
- * test cases, display custom fields in a different location (standard location is after
- * all test case definition), to implemente Prerequisites using CF.
- *
- * First map key: node type: 'testcase','testsuite', etc.
- * Each element will be a map with following structure:
- * key:Holds string keys used on this object and pages that manages CF.
- * current options: 1 -> standard location, i.e. work as done before this implementation.
- * 2 -> before steps and results, => between summary and steps/results.
- *
- * value: used to get translated label to use on User Interface.
- *
- * IMPORTANT: if you add a new key, this values are used as access keys in several properties of this object.
- * then if you add one here, remember to update other properties.
- */
- var $locations = array( 'testcase' =>
- array( 1 => 'standard_location', 2 => 'before_steps_results'));
-
- // 20090523 - changes in configuration
- //
- // Needed to manage user interface, when creating Custom Fields.
- // When user choose a item type (test case, etc), a javascript logic
- // uses this information to hide/show enable_on, and show_on combos.
- //
- // 0 => combo will not displayed
- //
- // BUGID 3707,3708
- // May be need a review, because after the changes, seems a little bit silly.
- var $enable_on_cfg = array( 'execution' => array('testsuite' => 0,
- 'testplan' => 0,
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0),
- 'design' => array('testsuite' => 0, //
- 'testplan' => 0, //
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0),
- 'testplan_design' => array('testsuite' => 0,
- 'testplan' => 0,
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0));
-
- // 0 => combo will not displayed
- var $show_on_cfg=array('execution'=>array('testsuite' => 1,
- 'testplan' => 1,
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0 ),
- 'design' => array('testsuite' => 1,
- 'testplan' => 1,
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0 ),
- 'testplan_design' => array('testsuite' => 1,
- 'testplan' => 1,
- 'testcase' => 1,
- 'requirement_spec' => 0,
- 'requirement' => 0 )
- );
-
- // the name of html input will have the following format
- // <name_prefix>_<custom_field_type_id>_<progressive>
- //
- var $name_prefix='custom_field_';
- var $sizes = null;
-
- // must be equal to the lenght of:
- // value column on cfield_*_values tables
- // default_value column on custom_fields table
- // 0 -> no limit
- // Is used on text area types
- var $max_length_value;
-
- // must be equal to the lenght of:
- // possible_values column on custom_fields table
- // 0 -> no limit
- var $max_length_possible_values;
-
-
- /**
- * Class constructor
- *
- * @param resource &$db reference to the database handler
- */
- function __construct(&$db)
- {
- parent::__construct();
-
- $this->db = &$db;
- $this->tree_manager = new tree($this->db);
-
- $cfConfig = config_get('custom_fields');
- $this->sizes = $cfConfig->sizes;
-
- if( property_exists($cfConfig,'types') &&
- !is_null($cfConfig->types) )
- {
- $this->custom_field_types +=$cfConfig->types;
- ksort($this->custom_field_types);
- }
-
- if( property_exists($cfConfig,'possible_values_cfg') &&
- !is_null($cfConfig->possible_values_cfg) )
- {
- $this->possible_values_cfg +=$cfConfig->possible_values_cfg;
- }
- $this->object_table=$this->tables["custom_fields"];
-
- $this->max_length_value = $cfConfig->max_length;
- $this->max_length_possible_values = $this->max_length_value;
- }
-
- function getSizeLimit()
- {
- return $this->max_length_value;
- }
-
- function get_application_areas()
- {
- return($this->application_areas);
- }
-
- /**
- * @return hash with available locatipons
- *
- *
- */
- function getLocations()
- {
- return($this->locations);
- }
-
-
- /**
- * @return hash with custom field available types
- * key: numeric id
- * value: short description
- */
- function get_available_types()
- {
- return($this->custom_field_types);
- }
-
- /**
- * @return string
- */
- function get_name_prefix()
- {
- return($this->name_prefix);
- }
-
- /**
- * @return hash with node types id, that can have custom fields.
- * key: short description (node_types.description)
- * value: node_type_id (node_types.id)
- */
- function get_allowed_nodes()
- {
- $allowed_nodes=array();
- $tl_node_types=$this->tree_manager->get_available_node_types();
- foreach($this->node_types as $verbose_type )
- {
- $allowed_nodes[$verbose_type]=$tl_node_types[$verbose_type];
- }
- return($allowed_nodes);
- }
-
- /**
- * @return hash with node types id, that can have custom fields with enabled_on_$ui_mode.
- * key : node_type_id (node_types.id)
- * value: 1 -> enable on exec can be configured by user
- */
- function get_enable_on_cfg($ui_mode)
- {
- $mgmt_cfg=array();
- $mgmt_cfg=$this->_get_ui_mgtm_cfg_for_node_type($this->enable_on_cfg[$ui_mode]);
- return($mgmt_cfg);
- }
-
-
- function get_show_on_cfg($ui_mode)
- {
- $mgmt_cfg=array();
- $mgmt_cfg=$this->_get_ui_mgtm_cfg_for_node_type($this->show_on_cfg[$ui_mode]);
- return($mgmt_cfg);
- }
-
-
- /*
- function: _get_ui_mgtm_cfg_for_node_type
- utility method
-
- returns: hash with node types id.
- key : node_type_id (node_types.id)
- value: 1 -> enable on exec can be configured by user
-
-
- */
- function _get_ui_mgtm_cfg_for_node_type($map_node_id_cfg)
- {
- $enabled_mgmt=array();
- $tl_node_types=$this->tree_manager->get_available_node_types();
- foreach($this->node_types as $verbose_type)
- {
- $type_id=$tl_node_types[$verbose_type];
- if( isset($map_node_id_cfg[$verbose_type]) )
- {
- $enabled_mgmt[$type_id]=$map_node_id_cfg[$verbose_type];
- }
- }
- return($enabled_mgmt);
- }
-
-
-
- /*
- function: get_possible_values_cfg
-
- returns: hash
- key : cf_type_id (see $custom_field_types)
- value: 1 -> possible values can be managed on UI.
-
-
- */
- function get_possible_values_cfg()
- {
- $pv_cfg=array();
- $custom_field_types_id=array_flip($this->custom_field_types);
-
- foreach($this->possible_values_cfg as $verbose_cf_type => $use_on_ui)
- {
- $cf_type_id=$custom_field_types_id[$verbose_cf_type];
- $pv_cfg[$cf_type_id]=$use_on_ui;
- }
- return($pv_cfg);
- }
-
-
-
-
- /*
- function: get_linked_cfields_at_design
- returns information about custom fields that can be used
- at least at design time, with the value assigned (is any has been assigned).
-
-
- $tproject_id: needed because is possible to associate/link
- a different set of custom field for every test project
-
- $enabled : 1 -> get custom fields that are has been configured
- to be shown during specification design AND are enabled.
-
- Remember that also exist custom fields
- that can be only used during TEST CASE EXECUTION.
-
- [$filters]:default: null
- map with keys:
- [show_on_execution]: 1 -> filter on field show_on_execution=1
- 0 or null or not exists -> don't filter
-
- [show_on_testplan_design]: 1 -> filter on field show_on_execution=1
- 0 or null or not exists -> don't filter
-
- [cfield_id]: if exists use it's value to filter on custom field id
- null or not exists -> don't filter
-
- [location]: new concept used to define on what location on screen
- custom field will be designed.
- Initally used with CF available for Test cases, to
- implement pre-requisites.
- null => no filtering
-
- [$node_type]: default: null
- verbose id ('testcase', 'testsuite', etc) of a node type.
- custom fields are linked also to different node types.
- Example:
- I can define a custom field "Aspect" with values
- Performace, Usability and wnat use it only for test suites.
-
- [$node_id]: default: null
- identification of a node/element on node hierarchy.
- Needed when I want to get the value of custom fields
- linked to a node.
- Example:
- Have two test cases (ID:9999, ID:89800), and want to get
- the value assigned to custom field "Operating System".
- I will do two calls to this method.
-
- [$access_key]: default id, field name to use as access key in returned hash
-
- returns: hash
- key: custom field id
-
-
- rev :
-
- 20090420 - franciscom
- added new key cfield_id on filters
-
- 20080811 - franciscom
- interface changes $show_on_execution -> $filters
-
-
- 20070526 - franciscom
- changed order by clause
-
- 20070101 - franciscom
- 1. added filter on cfield_testprojects.active=1
- 2. added new argument $show_on_execution
-
-
- */
- function get_linked_cfields_at_design($tproject_id,$enabled,$filters=null,
- $node_type=null,$node_id=null,$access_key='id')
- {
- $additional_join="";
- $additional_values="";
- $additional_filter="";
-
- if( !is_null($node_type) )
- {
- $hash_descr_id = $this->tree_manager->get_available_node_types();
- $node_type_id=$hash_descr_id[$node_type];
-
- $additional_join .= " JOIN {$this->tables['cfield_node_types']} CFNT ON CFNT.field_id=CF.id " .
- " AND CFNT.node_type_id={$node_type_id} ";
- }
- if( !is_null($node_id) )
- {
- $additional_values .= ",CFDV.value AS value,CFDV.node_id AS node_id";
- $additional_join .= " LEFT OUTER JOIN {$this->tables['cfield_design_values']} CFDV ON CFDV.field_id=CF.id " .
- " AND CFDV.node_id={$node_id} ";
- }
-
- // 20080811 - franciscom - refactoring for BUGID 1650 (REQ)
- if( !is_null($filters) )
- {
- if( isset($filters['show_on_execution']) && !is_null($filters['show_on_execution']) )
- {
- $additional_filter .= " AND CF.show_on_execution=1 ";
- }
-
- // 20090523 - franciscom
- // Probably this piece need to be changed to act on enable_on_ attribute
- // due to CF display logic refactoring
- // if( isset($filters['show_on_testplan_design']) && !is_null($filters['show_on_testplan_design']) )
- // {
- // $additional_filter .= " AND CF.show_on_testplan_design=1 ";
- // }
- if( isset($filters['show_on_testplan_design']) && !is_null($filters['show_on_testplan_design']) )
- {
- $additional_filter .= " AND CF.enable_on_testplan_design=1 ";
- }
-
- if( isset($filters['cfield_id']) && !is_null($filters['cfield_id']) )
- {
- $additional_filter .= " AND CF.id={$filters['cfield_id']} ";
- }
-
- // 20090717 - franciscom
- $filterKey='location';
- if( isset($filters[$filterKey]) && !is_null($filters[$filterKey]) )
- {
- $additional_filter .= " AND CFTP.$filterKey={$filters[$filterKey]} ";
- }
- }
-
- $sql="SELECT CF.*,CFTP.display_order,CFTP.location" .
- $additional_values .
- " FROM {$this->object_table} CF " .
- " JOIN {$this->tables['cfield_testprojects']} CFTP ON CFTP.field_id=CF.id " .
- $additional_join .
- " WHERE CFTP.testproject_id={$tproject_id} " .
- " AND CFTP.active=1 " .
- " AND CF.show_on_design=1 " .
- " AND CF.enable_on_design={$enabled} " .
- $additional_filter .
- " ORDER BY display_order,CF.id ";
-
-
- $map = $this->db->fetchRowsIntoMap($sql,$access_key);
- return($map);
- }
-
-
- /*
- ====================================================================
- ** Very Imporant **
- This code is based on Mantis code.
- Initial development was based on 1.x.x versions.
- file:custom_field_api.php - function:print_custom_field_input()
-
- 20080815: some changes are done to add more flexibility, and idea
- was compared with 1.2.0a1 Mantis implementation.
- ====================================================================
-
- function: string_custom_field_input
- returns an string with the html needed to display the custom field.
-
- If no specific code is found to manage a custom field type,
- it will be used code that manage string type.
-
- args: $p_field_def: contains the definition of the custom field
- (including it's field id)
-
- [$name_suffix]: if used must start with _.
- example _TCID017
-
- returns: html string
-
- rev :
- 20080816 - franciscom
- added code to manange user defined (and code developed) Custom Fields.
- Important: solution is a mix of own ideas and Mantis 1.2.0a1 approach
-
- 20071006 - francisco.mancardi@gruppotesi.com
- Added field_size argument
-
- 20070104 - franciscom - added 'multiselection list'
-
- */
- function string_custom_field_input($p_field_def,$name_suffix='',$field_size=0)
- {
-
- $str_out='';
- $t_id = $p_field_def['id'];
- $t_type = $p_field_def['type'];
-
- $t_custom_field_value = $p_field_def['default_value'];
- if( isset($p_field_def['value']) )
- {
- $t_custom_field_value = $p_field_def['value'];
- }
-
-
- $verbose_type=trim($this->custom_field_types[$t_type]);
- $t_custom_field_value = htmlspecialchars( $t_custom_field_value );
-
- $input_name="{$this->name_prefix}{$t_type}_{$t_id}{$name_suffix}";
- $size = isset($this->sizes[$verbose_type]) ? intval($this->sizes[$verbose_type]) : 0;
-
- if( $field_size > 0)
- {
- $size=$field_size;
- }
-
-
- switch ($verbose_type)
- {
- case 'list':
- case 'multiselection list':
- $t_values = explode( '|', $p_field_def['possible_values']);
- if( $verbose_type == 'list' )
- {
- $t_multiple=' ';
- $t_list_size = intval($size) > 0 ? $size :1;
- // 20100701 - asimon - removed single space in next line,
- // it was causing errors in field names on HTML because it somehow gets replaced
- // by an underscore somwhere and then the field name doesn't match anymore
- //$t_name_suffix=' ';
- $t_name_suffix='';
- }
- else
- {
- $window_size = intval($size) > 1 ? $size : self::MULTISELECTIONLIST_WINDOW_SIZE;
- $t_name_suffix='[]';
- $t_multiple=' multiple="multiple" ';
- $t_list_size = count( $t_values );
- if($t_list_size > $window_size)
- {
- $t_list_size=$window_size;
- }
- }
- $html_identity=$input_name . $t_name_suffix;
- $str_out .="<select name=\"{$html_identity}\" id=\"{$input_name}\" {$t_multiple}";
- $str_out .= ' size="' . $t_list_size . '">';
-
- $t_selected_values = explode( '|', $t_custom_field_value );
- foreach( $t_values as $t_option ) {
- if( in_array( $t_option, $t_selected_values ) ) {
- $str_out .='<option value="' . $t_option . '" selected> ' . $t_option . '</option>';
- } else {
- $str_out .='<option value="' . $t_option . '">' . $t_option . '</option>';
- }
- }
- $str_out .='</select>';
- break;
-
- case 'checkbox':
- $t_values = explode( '|', $p_field_def['possible_values']);
- $t_checked_values = explode( '|', $t_custom_field_value );
- foreach( $t_values as $t_option )
- {
- $str_out .= '<input type="checkbox" name="' . $input_name . '[]"' . " id=\"{$input_name}\"";
-
- // 20100218 - franciscom - added check $t_option != '' to make check box start NOT CHECKED
- if( $t_option != '' && in_array($t_option, $t_checked_values) )
- {
- $str_out .= ' value="' . $t_option . '" checked="checked"> ' . $t_option . ' ';
- }
- else
- {
- $str_out .= ' value="' . $t_option . '"> ' . $t_option . ' ';
- }
-
- }
- break;
-
- case 'string':
- case 'email':
- case 'float':
- case 'numeric':
- $str_out .= $this->string_input_string($p_field_def,$input_name,$t_custom_field_value,$size);
- break ;
-
- case 'text area':
- $cols = intval($this->sizes['text area']['cols']);
- $rows = intval($this->sizes['text area']['rows']);
- if($cols <= 0)
- {
- $cols = self::TEXTAREA_DEFAULT_COLS;
- }
- if($rows <= 0)
- {
- $rows = self::TEXTAREA_DEFAULT_ROWS;
- }
-
- if( $this->max_length_value > 0 )
- {
- $counterId = $input_name . '_counter';
- $cf_current_size = $this->max_length_value - tlStringLen($t_custom_field_value);
-
- // call JS function for check max. size from validate.js
- $js_function = '"textCounter(this.form.' . $input_name .
- ',document.getElementById(\''. $counterId.'\'),' . $this->max_length_value .');" ';
-
- $str_out .= '<textarea name="' . $input_name . '" ' . " id=\"{$input_name}\" " .
- 'onKeyDown=' . $js_function . ' onKeyUp=' . $js_function . 'cols="' .
- $cols . '" rows="' . $rows . '">' . "{$t_custom_field_value}</textarea>\n";
-
- // show character counter
- $str_out .= '<br><span style="vertical-align: top; padding: 5px;">' .
- sprintf(lang_get('text_counter_feedback'), $this->max_length_value) .
- ' <span id="' . $counterId .'">'.$cf_current_size.'</span>.</span><br>';
- }
- else
- {
- // unlimited
- $str_out .= '<textarea name="' . $input_name . '" ' . " id=\"{$input_name}\" " .
- 'cols="' . $cols . '" rows="' . $rows . '">' . "{$t_custom_field_value}</textarea>\n";
-
- }
- break;
-
- case 'date':
- $str_out .= create_date_selection_set($input_name,config_get('date_format'),
- $t_custom_field_value, false, true) ;
- break;
-
- case 'datetime':
- $cfg=config_get('gui');
-
- // Important
- // We can do this mix (get date format configuration from standard variable
- // and time format from an specific custom field config) because string used
- // for date_format on strftime() has no problem
- // on date() calls (that are used in create_date_selection_set() ).
- $datetime_format=config_get('date_format') . " " .$cfg->custom_fields->time_format;
- $str_out .=create_date_selection_set($input_name,$datetime_format,
- $t_custom_field_value, false, true,date( "Y" )-1) ;
- break;
-
-
- default:
- $dynamic_call='string_input_' . str_replace(' ', '_', $verbose_type);
- if( function_exists($dynamic_call) )
- {
- $str_out .= $dynamic_call($p_field_def, $input_name, $t_custom_field_value);
- }
- else if( method_exists($this, $dynamic_call) )
- {
- $str_out .= $this->$dynamic_call($p_field_def, $input_name, $t_custom_field_value);
- }
- else
- {
- // treat it as an simple string
- $str_out .= $this->string_input_string($p_field_def,$input_name,$t_custom_field_value,$size);
- }
- break;
-
-
- }
- return ($str_out);
- } //function end
-
-
- /*
- function: design_values_to_db
- write values of custom fields that are used at design time.
-
- args: $hash: contains info about CF gathered at user interface.
- (normally $_REQUEST variable)
- key: custom_field_<field_type_id>_<cfield_id>.
- Example custom_field_0_67 -> 0=> string field
-
- $node_id:
- [$cf_map]: hash -> all the custom fields linked and enabled
- that are applicable to the node type of $node_id.
-
- For the keys not present in $hash, we will write
- an appropriate value according to custom field
- type.
-
- This is needed because when trying to udpate
- with hash being $_REQUEST, $_POST or $_GET
- some kind of custom fields (checkbox, list, multiple list)
- when has been deselected by user.
-
-
- rev:
- 20070525 - franciscom - added [hash_type], to reuse this method on
- class testcase method copy_cfields_design_values()
- 20070501 - franciscom - limiting lenght of value before writting
- 20070105 - franciscom - added $cf_map
- 20070104 - franciscom - need to manage multiselection in a different way
- */
- function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null)
- {
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- if( is_null($hash) && is_null($cf_map) )
- {
- return;
- }
- if( is_null($hash_type) )
- {
- $cfield=$this->_build_cfield($hash,$cf_map);
- }
- else
- {
- $cfield=$hash;
- }
- if( !is_null($cfield) )
- {
- //new dBug($cfield);
- foreach($cfield as $field_id => $type_and_value)
- {
- $value = $type_and_value['cf_value'];
-
- // do I need to update or insert this value?
- $sql = "/* $debugMsg */ SELECT value FROM {$this->tables['cfield_design_values']} " .
- " WHERE field_id={$field_id} AND node_id={$node_id}";
-
- $result = $this->db->exec_query($sql);
-
- // max_length_value = 0 => no limit
- if( $this->max_length_value > 0 && tlStringLen($value) > $this->max_length_value)
- {
- $value = substr($value,0,$this->max_length_value);
- }
-
- $safe_value=$this->db->prepare_string($value);
- if($this->db->num_rows( $result ) > 0 )
- {
-
- $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_design_values']} " .
- " SET value='{$safe_value}' " .
- " WHERE field_id={$field_id} AND node_id={$node_id}";
- }
- else
- {
- # Remark got from Mantis code:
- # Always store the value, even if it's the dafault value
- # This is important, as the definitions might change but the
- # values stored with a bug must not change
- $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);
- } //foreach($cfield
- } //if( !is_null($cfield) )
-
- } //function end
-
-
-
- /*
- function: remove_all_design_values_from_node
- remove the values of ALL custom fields linked to
- a node. (example test case 5555)
-
- args: $node_id: single value or array
-
- returns: -
-
- rev :
- 20070102 - franciscom - $node_id can be an array
-
- */
- function remove_all_design_values_from_node($node_id)
- {
-
- $sql="DELETE FROM {$this->tables['cfield_design_values']} ";
- if( is_array($node_id) )
- {
-
- $sql .= " WHERE node_id IN(" . implode(",",$node_id) . ") ";
- }
- else
- {
- $sql .= " WHERE node_id={$node_id}";
- }
- $this->db->exec_query($sql);
- } //function end
-
-
- /*
- function: get_all
- get the definition of all custom field defined in the system,
- or all custom fields with id not included in $id2exclude.
-
- args: [$id2exclude]: array with custom field ids
-
- returns: hash:
- key: custom field id
-
- */
- function get_all($id2exclude=null)
- {
- $not_in_clause="";
- if( !is_null($id2exclude) )
- {
- $not_in_clause=" AND CF.id NOT IN (" .implode(',',$id2exclude) .") ";
- }
- $sql="SELECT CF.*,NT.description AS node_description,NT.id AS node_type_id " .
- " FROM {$this->object_table} CF, " .
- " {$this->tables['cfield_node_types']} CFNT, " .
- " {$this->tables['node_types']} NT " .
- " WHERE CF.id=CFNT.field_id " .
- " AND NT.id=CFNT.node_type_id " .
- $not_in_clause .
- " ORDER BY CF.name";
- // $map = $this->db->fetchArrayRowsIntoMap($sql,'id');
- $map = $this->db->fetchRowsIntoMap($sql,'id');
- return($map);
- }
-
- /*
- function: get_linked_to_testproject
- get definition of all custom fields linked to a test project.
-
-
- args: $tproject_id
- [$active]: if not null will add the following filter " AND CFTP.active={$active}"
-
- returns: hash:
- key: custom field id
-
- internal revision:
- 20090717 - franciscom - added location to result recordset
- */
- function get_linked_to_testproject($tproject_id,$active=null)
- {
- $sql="SELECT CF.*,NT.description AS node_description,NT.id AS node_type_id, " .
- " CFTP.display_order, CFTP.active, CFTP.location " .
- " FROM {$this->object_table} CF, " .
- " {$this->tables['cfield_testprojects']} CFTP, " .
- " {$this->tables['cfield_node_types']} CFNT, " .
- " {$this->tables['node_types']} NT " .
- " WHERE CF.id=CFNT.field_id " .
- " AND CF.id=CFTP.field_id " .
- " AND NT.id=CFNT.node_type_id " .
- " AND CFTP.testproject_id={$tproject_id} ";
-
- if( !is_null($active) )
- {
- $sql .= " AND CFTP.active={$active} ";
- }
- //$sql .= " ORDER BY display_order, CF.name";
- // BUGID 3555
- $sql .= " ORDER BY CF.enable_on_design desc, " .
- "CF.enable_on_execution desc, " .
- "CF.enable_on_testplan_design desc,".
- "CFTP.display_order, CF.name";
- $map = $this->db->fetchRowsIntoMap($sql,'id');
- return($map);
- }
-
-
- /*
- function: link_to_testproject
-
-
-
- args: $tproject_id
- $cfields_id: array()
-
- returns: -
- */
- function link_to_testproject($tproject_id,$cfield_ids)
- {
- if(is_null($cfield_ids))
- {
- return;
- }
-
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
- foreach($cfield_ids as $field_id)
- {
- $sql = "/* $debugMsg */ INSERT INTO {$this->tables['cfield_testprojects']} " .
- " (testproject_id,field_id) " .
- " VALUES({$tproject_id},{$field_id})";
-
- if ($this->db->exec_query($sql))
- {
- $cf = $this->get_by_id($field_id);
- if ($cf)
- {
- logAuditEvent(TLS("audit_cfield_assigned",$cf[$field_id]['name'],$tproject_info['name']),
- "ASSIGN",$tproject_id,"testprojects");
- }
- }
- }
- } //function end
-
-
- /*
- function: set_active_for_testproject
- set the value of active field
-
-
- args: $tproject_id
- $cfields_id: array()
- $active_val: 1/0
-
- returns: -
- */
- function set_active_for_testproject($tproject_id,$cfield_ids,$active_val)
- {
- if(is_null($cfield_ids))
- {
- return;
- }
-
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
- $auditMsg = $active_val ? "audit_cfield_activated" : "audit_cfield_deactivated";
- foreach($cfield_ids as $field_id)
- {
- $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_testprojects']} " .
- " SET active={$active_val} " .
- " WHERE testproject_id={$tproject_id} " .
- " AND field_id={$field_id}";
-
- if ($this->db->exec_query($sql))
- {
- $cf = $this->get_by_id($field_id);
- if ($cf)
- {
- logAuditEvent(TLS($auditMsg,$cf[$field_id]['name'],$tproject_info['name']),
- "SAVE",$tproject_id,"testprojects");
- }
- }
- }
- } //function end
-
-
- /**
- * unlink_from_testproject
- * remove custom field links from target test project
- * N.B.: following Mantis Bugtracking System model,
- * this operation will NOR remove all values assigned to
- * these custom fields .
- *
- * @param int $tproject_id
- * @param array $cfield_ids
- *
- */
- function unlink_from_testproject($tproject_id,$cfield_ids)
- {
- if(is_null($cfield_ids))
- {
- return;
- }
-
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- // just for audit porpouses
- $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
- foreach($cfield_ids as $field_id)
- {
- // BUGID 0000677
- $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testprojects']} " .
- " WHERE field_id = {$field_id} AND testproject_id = {$tproject_id} ";
- if ($this->db->exec_query($sql))
- {
- $cf = $this->get_by_id($field_id);
- if ($cf)
- {
- logAuditEvent(TLS("audit_cfield_unassigned",$cf[$field_id]['name'],$tproject_info['name']),
- "ASSIGN",$tproject_id,"testprojects");
- }
- }
- }
- } //function end
-
-
-
- /*
- function: get_by_name
- get custom field definition
-
- args: $name: custom field name
-
- returns: hash
- */
- function get_by_name($name)
- {
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- $my_name=$this->db->prepare_string(trim($name));
-
- $sql="/* $debugMsg */ SELECT CF.*, CFNT.node_type_id,NT.description AS node_type" .
- " FROM {$this->tables['custom_fields']} CF, {$this->tables['cfield_node_types']} CFNT," .
- " {$this->tables['node_types']} NT" .
- " WHERE CF.id=CFNT.field_id " .
- " AND CFNT.node_type_id=NT.id " .
- " AND name='{$my_name}' ";
- return($this->db->fetchRowsIntoMap($sql,'id'));
- }
-
- /*
- function: get_by_id
- get custom field definition
-
- args: $id: custom field id
-
- returns: hash
-
- */
- function get_by_id($id)
- {
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- $sql="/* $debugMsg */ SELECT CF.*, CFNT.node_type_id" .
- " FROM {$this->tables['custom_fields']} CF, {$this->tables['cfield_node_types']} CFNT" .
- " WHERE CF.id=CFNT.field_id " .
- " AND CF.id={$id} ";
- return($this->db->fetchRowsIntoMap($sql,'id'));
- }
-
- /*
- function: get_available_item_type
- get information about what item type (testcase,testplan, etc)
- can use this custom field
-
- args: $id: custom field id
-
- returns:
-
- */
- function get_available_item_type($id)
- {
- $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
- $sql="/* $debugMsg */ SELECT CFNT.field_id,CFNT.node_type_id ".
- " FROM {$this->tables['cfield_node_types']} CFNT, " .
- " {$this->tables['nodes_types']} NT " .
- " WHERE NT.id=CFNT.node_type_id " .
- " CFNt.field_id={$id} ";
-
- return($this->db->fetchRowsIntoMap($sql,'field_id'));
- }
-
-
- /*
- function: create a custom field
-
- args: $hash:
- keys name
- label
- type
- possible_values
- show_on_design
- enable_on_design
- show_on_execute
- enable_on_execute
- show_on_testplan_design
- enable_on_testplan_design
- node_type_id
-
- returns: -
-
- rev: 20080810 - franciscom - BUGID 1650
-
- */
- function create($cf)
- {
- $ret = array('status_ok' => 0, 'id' => 0, 'msg' => 'ko');
-
- $my_name=$this->db->prepare_string($cf['name']);
- $my_label=$this->db->prepare_string($cf['label']);
- $my_pvalues=$this->db->prepare_string($cf['possible_values']);
-
-
- $sql="INSERT INTO {$this->object_table} " .
- " (name,label,type,possible_values, " .
- " show_on_design,enable_on_design, " .
- " show_on_testplan_design,enable_on_testplan_design, " .
- " show_on_execution,enable_on_execution) " .
- " VALUES('{$my_name}','{$my_label}',{$cf['type']},'{$my_pvalues}', " .
- " {$cf['show_on_design']},{$cf['enable_on_design']}," .
- " {$cf['show_on_testplan_design']},{$cf['enable_on_testplan_design']}," .
- " {$cf['show_on_execution']},{$cf['enable_on_execution']})";
- $result=$this->db->exec_query($sql);
-
- if ($result)
- {
- // at least for Postgres DBMS table name is needed.
- $field_id=$this->db->insert_id($this->object_table);
-
- $sql="INSERT INTO {$this->tables['cfield_node_types']} " .
- " (field_id,node_type_id) " .
- " VALUES({$field_id},{$cf['node_type_id']}) ";
- $result=$this->db->exec_query($sql);
- }
-
- if ($result)
- {
- $ret = array('status_ok' => 1, 'id' => $field_id, 'msg' => 'ok');
- }
- return($ret);
- } //function end
-
-
- /*
- function: update a custom field
-
- args: $hash:
- keys name
- label
- type
- possible_values
- show_on_design
- enable_on_design
- show_on_execute
- enable_on_execute
- show_on_testplan_design
- enable_on_testplan_design
- node_type_id
-
- returns: -
- */
- function update($cf)
- {
- $my_name = $this->db->prepare_string($cf['name']);
- $my_label = $this->db->prepare_string($cf['label']);
- $my_pvalues = $this->db->prepare_string($cf['possible_values']);
-
- $sql ="UPDATE {$this->tables['custom_fields']} " .
- " SET name='{$my_name}',label='{$my_label}'," .
- " type={$cf['type']},possible_values='{$my_pvalues}'," .
- " show_on_design={$cf['show_on_design']}," .
- " enable_on_design={$cf['enable_on_design']}," .
- " show_on_testplan_design={$cf['show_on_testplan_design']}," .
- " enable_on_testplan_design={$cf['enable_on_testplan_design']}," .
- " show_on_execution={$cf['show_on_execution']}," .
- " enable_on_execution={$cf['enable_on_execution']}" .
- " WHERE id={$cf['id']}";
- $result = $this->db->exec_query($sql);
-
- if ($result)
- {
- $sql = "UPDATE {$this->tables['cfield_node_types']} " .
- " SET node_type_id={$cf['node_type_id']}" .
- " WHERE field_id={$cf['id']}";
- $result = $this->db->exec_query($sql);
- }
- return $result ? 1 : 0;
- } //function end
-
-
- /**
- * delete()
- * Will delete custom field definition and also ALL assigned values
- * If custom field is linked to test projects, these links must be removed
- *
- */
- function delete($id)
- {
- // Before deleting definition I need to remove values
- if( $this->is_used($id) )
- {
- $this->remove_all_scopes_values($id);
- }
- $linked_tprojects = $this->get_linked_testprojects($id);
- if( !is_null($linked_tprojects) && count($linked_tprojects) > 0 )
- {
- $target=array_keys($linked_tprojects);
- foreach($target as $tproject_id)
- {
- $this->unlink_from_testproject($tproject_id,(array)$id);
- }
- }
-
- $sql="DELETE FROM {$this->tables['cfield_node_types']} WHERE field_id={$id}";
- $result=$this->db->exec_query($sql);
- if($result)
- {
- $sql="DELETE FROM {$this->tables['custom_fields']} WHERE id={$id}";
- $result=$this->db->exec_query($sql);
- }
- return $result ? 1 : 0;
- }
-
-
- /*
- function: is_used
-
- args: $id: custom field id
-
- returns: 1/0
-
- rev: 20080810 - franciscom - BUGID 1650
- */
- function is_used($id)
- {
- $sql="SELECT field_id FROM {$this->tables['cfield_design_values']} " .
- "WHERE field_id={$id} " .
- "UNION " .
- "SELECT field_id FROM {$this->tables['cfield_testplan_design_values']} " .
- "WHERE field_id={$id} " .
- "UNION " .
- "SELECT field_id FROM {$this->tables['cfield_execution_values']} " .
- "WHERE field_id={$id} ";
- $result=$this->db->exec_query($sql);
- return($this->db->num_rows( $result ) > 0 ? 1 : 0);
- } //function end
-
- /*
- function: whoIsUsingMe
-
- args: $id: custom field id
-
- returns:
- */
- function whoIsUsingMe($id)
- {
- $sql=" SELECT field_id,name ".
- " FROM {$this->tables['cfield_design_values']} CFDV, ".
- " {$this->tables['cfield_node_types']} CFNT, " .
- " {$this->tables['nodes_hierarchy']} NH " .
- " WHERE CFDV.field_id=CFNT.field_id " .
- " AND NH.id=CFDV.node_id " .
- " CFDV.field_id={$id} ";
- } //function end
-
-
-
-
- /*
- function: name_is_unique
-
- args: $id
- $name
-
- returns: 1 => name is unique
- */
- function name_is_unique($id,$name)
- {
- $cf=$this->get_by_name($name);
- $status=0;
- if( is_null($cf) || isset($cf[$id]) )
- {
- $status=1;
- }
- return($status);
- } //function end
-
-
-
- # --------------------
- # Adapted from Mantis code
- # Prepare a string containing a custom field value for display
- # $p_field_def definition of the custom field
- # $p_node_id bug id to display the custom field value for
- #
- # [$p_value_field]: field id, to point to the field value in $p_field_def
- function string_custom_field_value( $p_field_def, $p_node_id,$p_value_field='value')
- {
-
- $t_custom_field_value=htmlspecialchars($p_field_def[$p_value_field]);
-
- switch ($this->custom_field_types[$p_field_def['type']])
- {
- case 'email':
- return "<a href=\"mailto:$t_custom_field_value\">$t_custom_field_value</a>";
- break;
-
- case 'enum':
- case 'list':
- case 'multiselection list':
- case 'checkbox':
- return str_replace( '|', ', ', $t_custom_field_value );
- break;
-
- case 'date':
- if ($t_custom_field_value != null)
- {
- // must remove %
- $t_date_format=str_replace("%","",config_get( 'date_format'));
- $xdate=date( $t_date_format, $t_custom_field_value);
- return $xdate;
- }
- break ;
-
- case 'datetime':
- if ($t_custom_field_value != null)
- {
- // must remove %
- // $t_date_format=str_replace("%","",config_get( 'timestamp_format'));
- // $datetime_format=$t_date_format;
- $t_date_format=str_replace("%","",config_get( 'date_format'));
- $cfg=config_get('gui');
- $datetime_format=$t_date_format . " " .$cfg->custom_fields->time_format;
- $xdate=date( $datetime_format, $t_custom_field_value);
- return $xdate;
- }
- break ;
-
-
- case 'text area':
- if ($t_custom_field_value != null)
- {
- return nl2br($t_custom_field_value);
- }
- break;
-
- default:
- // 20071027 - franciscom
- // This code manages URLs
- return string_display_links( $t_custom_field_value );
-
- // return($t_custom_field_value);
- }
- }
-
-
-
- /*
- function: get_linked_cfields_at_execution
- returns information about custom fields that can be used
- at least at executed, with the value assigned (is any has been assigned).
-
-
- $tproject_id: needed because is possible to associate/link
- a differen…
Large files files are truncated, but you can click here to view the full file