PageRenderTime 96ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/functions/cfield_mgr.class.php

https://bitbucket.org/pfernandez/testlink1.9.6
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

  1. <?php
  2. /**
  3. * TestLink Open Source Project - http://testlink.sourceforge.net/
  4. * This script is distributed under the GNU General Public License 2 or later.
  5. *
  6. * @package TestLink
  7. * @author franciscom
  8. * @copyright 2005-2009, TestLink community
  9. * @copyright Mantis BT team (some parts of code was reuse from the Mantis project)
  10. * @version CVS: $Id: cfield_mgr.class.php,v 1.82 2010/08/29 09:26:16 franciscom Exp $
  11. * @link http://www.teamst.org/index.php
  12. *
  13. * @internal Revisions:
  14. *
  15. * 20100829 - franciscom - BUGID 3707,3708 usability issue + browser different behaviour
  16. * 20100825 - eloff - BUGID 3713 - add platform_name to output of get_linked_cfields_at_execution()
  17. * 20100726 - amitkhullar - BUGID 3555 - sort order while displaying custom fields.
  18. * 20100701 - asimon - BUGID 3414: removed a single space character in string_custom_field_input()
  19. * because of an error that was caused by it
  20. * 20100218 - franciscom - string_custom_field_input() changes on checkbox management
  21. * 20100204 - franciscom - getByLinkID() - new method
  22. * 20090823 - franciscom - added logic to remove 255 size limit
  23. * 20090718 - franciscom - buildLocationMap()
  24. * 20090717 - franciscom - get_linked_cfields_at_design() - added filter by location
  25. * get_linked_cfields_at_execution() - location argument
  26. *
  27. * 20090607 - franciscom - refactoring to manage table prefix
  28. * 20090530 - franciscom - execution_values_to_db() added logic to manage insert or update.
  29. * 20090523 - franciscom - changes on show_on, enable_on logics
  30. * 20090426 - franciscom - new method getSizeLimit()
  31. * 20090420 - amitkhullar- BUGID-2410 - get_linked_cfields_at_testplan_design() - added logic to get data
  32. * for custom field values stores at test plan level.
  33. * 20090420 - franciscom - BUGID 2158 - get_linked_cfields_at_design() added filter on custom field id
  34. *
  35. * 20090408 - franciscom - BUGID 2352 - added new method remove_all_scopes_values();
  36. * changes in delete()
  37. *
  38. * 20090321 - franciscom - fixed bug due to missing code on get_linked_cfields_at_design()
  39. * 20090321 - franciscom - exportValueAsXML()
  40. * 20090303 - franciscom - get_linked_cfields_at_execution() - fixed bugs on query
  41. * and added logic to change fetch method.
  42. *
  43. * 20090223 - franciscom - get_linked_cfields_at_execution() - added logic
  44. * to use this method on report created by:
  45. * Amit Khullar - amkhullar@gmail.com
  46. *
  47. * 20080817 - franciscom - added logic give default logic to manage
  48. * new custom field types that have no specific code.
  49. *
  50. * 20080816 - franciscom - new feature: user defined Custom Fields.
  51. * Important:
  52. * solution is a mix of own ideas and Mantis 1.2.0a1 approach.
  53. * string_custom_field_input(), _build_cfield()
  54. *
  55. * added radio type, datetime type.
  56. *
  57. *
  58. * 20080810 - franciscom - documentation improvements
  59. * BUGID 1650 (REQ)
  60. * get_linked_cfields_at_design() - interface changes
  61. *
  62. * 20080304 - franciscom - prepare_string() before insert
  63. * 20080216 - franciscom - added testproject name to logAudit recorded information
  64. * 20071102 - franciscom - BUGID - Feature
  65. * addition and refactoring of contributed code
  66. *
  67. * 20071027 - franciscom - using Mantis (a php based bugtracking system)
  68. * logic, to improve custom field management
  69. * adding support for url on string custom fields.
  70. *
  71. *
  72. * 20070617 - franciscom - BUGID insert_id() problems for Postgres and Oracle?
  73. * 20070501 - franciscom - limiting length of values while writting to db.
  74. * 20070429 - franciscom - added text area custom field
  75. * code contributed by Seweryn Plywaczyk
  76. *
  77. * 20070227 - franciscom - BUGID 677
  78. * 20070110 - franciscom - solved bug set_active()
  79. *
  80. * 20070105 - franciscom -
  81. * 1. solved bugs on design_values_to_db()
  82. * 2. refactoring - design_values_to_db()
  83. * execution_values_to_db()
  84. *
  85. **/
  86. /** load conversion functions */
  87. require_once(dirname(__FILE__) . '/date_api.php');
  88. require_once(dirname(__FILE__) . '/string_api.php');
  89. // Copied from mantis, allow load of user custom implementations
  90. // some sort of poor's man plugin
  91. $cf_files=glob( TL_ABS_PATH . "custom/cf_*.php");
  92. if( count($cf_files) > 0 )
  93. {
  94. foreach($cf_files as $inc)
  95. {
  96. require_once($inc);
  97. }
  98. }
  99. /**
  100. * class is responsible for logic and store Custom Fields functionality
  101. * @package TestLink
  102. */
  103. class cfield_mgr extends tlObject
  104. {
  105. const DEFAULT_INPUT_SIZE = 50;
  106. const MULTISELECTIONLIST_WINDOW_SIZE = 5;
  107. const TEXTAREA_MAX_SIZE = 255;
  108. // EDIT HERE IF YOU CUSTOMIZE YOUR DB
  109. /** for text area custom field 40 x 6 -> 240 chars <= 255 chars table field size */
  110. const TEXTAREA_DEFAULT_COLS = 70;
  111. const TEXTAREA_DEFAULT_ROWS = 4;
  112. const CF_ENABLED = 1;
  113. const ENABLED = 1;
  114. const DISABLED = 0;
  115. /** @var resource the database handler */
  116. var $db;
  117. /** @var object tree class */
  118. var $tree_manager;
  119. /**
  120. * @var array $application_areas
  121. * Holds string keys used on this object and pages that manages CF,
  122. * identifying in what areas/features something will be done
  123. * 'execution' => mainly on test execution pages,
  124. * identifies TL features/pages to record test results
  125. * 'design' => test suites, test cases creation
  126. * identifies TL features/pages to create test specification
  127. * 'testplan_design' => link test cases to test plan (assign testcase option)
  128. *
  129. * IMPORTANT: this values are used as access keys in several properties of this object.
  130. * then if you add one here, remember to update other properties.
  131. */
  132. var $application_areas = array('execution','design','testplan_design');
  133. /**
  134. * @var array Define type of custom fields managed.
  135. * Values will be displayed in "Custom Field Type" combo box when
  136. * users create custom fields. No localization is applied
  137. */
  138. // 20080809 - franciscom
  139. // Added specific type for test automation related custom fields.
  140. // Start at code 500
  141. var $custom_field_types = array(0=>'string',
  142. 1=>'numeric',
  143. 2=>'float',
  144. 4=>'email',
  145. 5=>'checkbox',
  146. 6=>'list',
  147. 7=>'multiselection list',
  148. 8=>'date',
  149. 9=>'radio',
  150. 10=>'datetime',
  151. 20=>'text area',
  152. 500=>'script',
  153. 501=>'server');
  154. /**
  155. * @var array Configures for what type of CF "POSSIBLE_VALUES" field need to be manage at GUI level
  156. * Keys of this map must be the values present in:
  157. * <code>$this->custom_field_types</code>
  158. */
  159. var $possible_values_cfg = array('string' => 0,
  160. 'numeric'=> 0,
  161. 'float'=> 0,
  162. 'email'=> 0,
  163. 'checkbox' => 1,
  164. 'list' => 1,
  165. 'multiselection list' => 1,
  166. 'date' => 0,
  167. 'radio' => 1,
  168. 'datetime' =>0,
  169. 'text area' => 0,
  170. 'script'=> 0,
  171. 'server' => 0);
  172. /** @var array only the types listed here can have custom fields */
  173. var $node_types = array('testsuite','testplan','testcase','requirement_spec','requirement');
  174. /**
  175. * @var map of maps $locations
  176. *
  177. * Location is place on page where to display custom field.
  178. * This concept has been created to implement a user contribution, that allows for
  179. * test cases, display custom fields in a different location (standard location is after
  180. * all test case definition), to implemente Prerequisites using CF.
  181. *
  182. * First map key: node type: 'testcase','testsuite', etc.
  183. * Each element will be a map with following structure:
  184. * key:Holds string keys used on this object and pages that manages CF.
  185. * current options: 1 -> standard location, i.e. work as done before this implementation.
  186. * 2 -> before steps and results, => between summary and steps/results.
  187. *
  188. * value: used to get translated label to use on User Interface.
  189. *
  190. * IMPORTANT: if you add a new key, this values are used as access keys in several properties of this object.
  191. * then if you add one here, remember to update other properties.
  192. */
  193. var $locations = array( 'testcase' =>
  194. array( 1 => 'standard_location', 2 => 'before_steps_results'));
  195. // 20090523 - changes in configuration
  196. //
  197. // Needed to manage user interface, when creating Custom Fields.
  198. // When user choose a item type (test case, etc), a javascript logic
  199. // uses this information to hide/show enable_on, and show_on combos.
  200. //
  201. // 0 => combo will not displayed
  202. //
  203. // BUGID 3707,3708
  204. // May be need a review, because after the changes, seems a little bit silly.
  205. var $enable_on_cfg = array( 'execution' => array('testsuite' => 0,
  206. 'testplan' => 0,
  207. 'testcase' => 1,
  208. 'requirement_spec' => 0,
  209. 'requirement' => 0),
  210. 'design' => array('testsuite' => 0, //
  211. 'testplan' => 0, //
  212. 'testcase' => 1,
  213. 'requirement_spec' => 0,
  214. 'requirement' => 0),
  215. 'testplan_design' => array('testsuite' => 0,
  216. 'testplan' => 0,
  217. 'testcase' => 1,
  218. 'requirement_spec' => 0,
  219. 'requirement' => 0));
  220. // 0 => combo will not displayed
  221. var $show_on_cfg=array('execution'=>array('testsuite' => 1,
  222. 'testplan' => 1,
  223. 'testcase' => 1,
  224. 'requirement_spec' => 0,
  225. 'requirement' => 0 ),
  226. 'design' => array('testsuite' => 1,
  227. 'testplan' => 1,
  228. 'testcase' => 1,
  229. 'requirement_spec' => 0,
  230. 'requirement' => 0 ),
  231. 'testplan_design' => array('testsuite' => 1,
  232. 'testplan' => 1,
  233. 'testcase' => 1,
  234. 'requirement_spec' => 0,
  235. 'requirement' => 0 )
  236. );
  237. // the name of html input will have the following format
  238. // <name_prefix>_<custom_field_type_id>_<progressive>
  239. //
  240. var $name_prefix='custom_field_';
  241. var $sizes = null;
  242. // must be equal to the lenght of:
  243. // value column on cfield_*_values tables
  244. // default_value column on custom_fields table
  245. // 0 -> no limit
  246. // Is used on text area types
  247. var $max_length_value;
  248. // must be equal to the lenght of:
  249. // possible_values column on custom_fields table
  250. // 0 -> no limit
  251. var $max_length_possible_values;
  252. /**
  253. * Class constructor
  254. *
  255. * @param resource &$db reference to the database handler
  256. */
  257. function __construct(&$db)
  258. {
  259. parent::__construct();
  260. $this->db = &$db;
  261. $this->tree_manager = new tree($this->db);
  262. $cfConfig = config_get('custom_fields');
  263. $this->sizes = $cfConfig->sizes;
  264. if( property_exists($cfConfig,'types') &&
  265. !is_null($cfConfig->types) )
  266. {
  267. $this->custom_field_types +=$cfConfig->types;
  268. ksort($this->custom_field_types);
  269. }
  270. if( property_exists($cfConfig,'possible_values_cfg') &&
  271. !is_null($cfConfig->possible_values_cfg) )
  272. {
  273. $this->possible_values_cfg +=$cfConfig->possible_values_cfg;
  274. }
  275. $this->object_table=$this->tables["custom_fields"];
  276. $this->max_length_value = $cfConfig->max_length;
  277. $this->max_length_possible_values = $this->max_length_value;
  278. }
  279. function getSizeLimit()
  280. {
  281. return $this->max_length_value;
  282. }
  283. function get_application_areas()
  284. {
  285. return($this->application_areas);
  286. }
  287. /**
  288. * @return hash with available locatipons
  289. *
  290. *
  291. */
  292. function getLocations()
  293. {
  294. return($this->locations);
  295. }
  296. /**
  297. * @return hash with custom field available types
  298. * key: numeric id
  299. * value: short description
  300. */
  301. function get_available_types()
  302. {
  303. return($this->custom_field_types);
  304. }
  305. /**
  306. * @return string
  307. */
  308. function get_name_prefix()
  309. {
  310. return($this->name_prefix);
  311. }
  312. /**
  313. * @return hash with node types id, that can have custom fields.
  314. * key: short description (node_types.description)
  315. * value: node_type_id (node_types.id)
  316. */
  317. function get_allowed_nodes()
  318. {
  319. $allowed_nodes=array();
  320. $tl_node_types=$this->tree_manager->get_available_node_types();
  321. foreach($this->node_types as $verbose_type )
  322. {
  323. $allowed_nodes[$verbose_type]=$tl_node_types[$verbose_type];
  324. }
  325. return($allowed_nodes);
  326. }
  327. /**
  328. * @return hash with node types id, that can have custom fields with enabled_on_$ui_mode.
  329. * key : node_type_id (node_types.id)
  330. * value: 1 -> enable on exec can be configured by user
  331. */
  332. function get_enable_on_cfg($ui_mode)
  333. {
  334. $mgmt_cfg=array();
  335. $mgmt_cfg=$this->_get_ui_mgtm_cfg_for_node_type($this->enable_on_cfg[$ui_mode]);
  336. return($mgmt_cfg);
  337. }
  338. function get_show_on_cfg($ui_mode)
  339. {
  340. $mgmt_cfg=array();
  341. $mgmt_cfg=$this->_get_ui_mgtm_cfg_for_node_type($this->show_on_cfg[$ui_mode]);
  342. return($mgmt_cfg);
  343. }
  344. /*
  345. function: _get_ui_mgtm_cfg_for_node_type
  346. utility method
  347. returns: hash with node types id.
  348. key : node_type_id (node_types.id)
  349. value: 1 -> enable on exec can be configured by user
  350. */
  351. function _get_ui_mgtm_cfg_for_node_type($map_node_id_cfg)
  352. {
  353. $enabled_mgmt=array();
  354. $tl_node_types=$this->tree_manager->get_available_node_types();
  355. foreach($this->node_types as $verbose_type)
  356. {
  357. $type_id=$tl_node_types[$verbose_type];
  358. if( isset($map_node_id_cfg[$verbose_type]) )
  359. {
  360. $enabled_mgmt[$type_id]=$map_node_id_cfg[$verbose_type];
  361. }
  362. }
  363. return($enabled_mgmt);
  364. }
  365. /*
  366. function: get_possible_values_cfg
  367. returns: hash
  368. key : cf_type_id (see $custom_field_types)
  369. value: 1 -> possible values can be managed on UI.
  370. */
  371. function get_possible_values_cfg()
  372. {
  373. $pv_cfg=array();
  374. $custom_field_types_id=array_flip($this->custom_field_types);
  375. foreach($this->possible_values_cfg as $verbose_cf_type => $use_on_ui)
  376. {
  377. $cf_type_id=$custom_field_types_id[$verbose_cf_type];
  378. $pv_cfg[$cf_type_id]=$use_on_ui;
  379. }
  380. return($pv_cfg);
  381. }
  382. /*
  383. function: get_linked_cfields_at_design
  384. returns information about custom fields that can be used
  385. at least at design time, with the value assigned (is any has been assigned).
  386. $tproject_id: needed because is possible to associate/link
  387. a different set of custom field for every test project
  388. $enabled : 1 -> get custom fields that are has been configured
  389. to be shown during specification design AND are enabled.
  390. Remember that also exist custom fields
  391. that can be only used during TEST CASE EXECUTION.
  392. [$filters]:default: null
  393. map with keys:
  394. [show_on_execution]: 1 -> filter on field show_on_execution=1
  395. 0 or null or not exists -> don't filter
  396. [show_on_testplan_design]: 1 -> filter on field show_on_execution=1
  397. 0 or null or not exists -> don't filter
  398. [cfield_id]: if exists use it's value to filter on custom field id
  399. null or not exists -> don't filter
  400. [location]: new concept used to define on what location on screen
  401. custom field will be designed.
  402. Initally used with CF available for Test cases, to
  403. implement pre-requisites.
  404. null => no filtering
  405. [$node_type]: default: null
  406. verbose id ('testcase', 'testsuite', etc) of a node type.
  407. custom fields are linked also to different node types.
  408. Example:
  409. I can define a custom field "Aspect" with values
  410. Performace, Usability and wnat use it only for test suites.
  411. [$node_id]: default: null
  412. identification of a node/element on node hierarchy.
  413. Needed when I want to get the value of custom fields
  414. linked to a node.
  415. Example:
  416. Have two test cases (ID:9999, ID:89800), and want to get
  417. the value assigned to custom field "Operating System".
  418. I will do two calls to this method.
  419. [$access_key]: default id, field name to use as access key in returned hash
  420. returns: hash
  421. key: custom field id
  422. rev :
  423. 20090420 - franciscom
  424. added new key cfield_id on filters
  425. 20080811 - franciscom
  426. interface changes $show_on_execution -> $filters
  427. 20070526 - franciscom
  428. changed order by clause
  429. 20070101 - franciscom
  430. 1. added filter on cfield_testprojects.active=1
  431. 2. added new argument $show_on_execution
  432. */
  433. function get_linked_cfields_at_design($tproject_id,$enabled,$filters=null,
  434. $node_type=null,$node_id=null,$access_key='id')
  435. {
  436. $additional_join="";
  437. $additional_values="";
  438. $additional_filter="";
  439. if( !is_null($node_type) )
  440. {
  441. $hash_descr_id = $this->tree_manager->get_available_node_types();
  442. $node_type_id=$hash_descr_id[$node_type];
  443. $additional_join .= " JOIN {$this->tables['cfield_node_types']} CFNT ON CFNT.field_id=CF.id " .
  444. " AND CFNT.node_type_id={$node_type_id} ";
  445. }
  446. if( !is_null($node_id) )
  447. {
  448. $additional_values .= ",CFDV.value AS value,CFDV.node_id AS node_id";
  449. $additional_join .= " LEFT OUTER JOIN {$this->tables['cfield_design_values']} CFDV ON CFDV.field_id=CF.id " .
  450. " AND CFDV.node_id={$node_id} ";
  451. }
  452. // 20080811 - franciscom - refactoring for BUGID 1650 (REQ)
  453. if( !is_null($filters) )
  454. {
  455. if( isset($filters['show_on_execution']) && !is_null($filters['show_on_execution']) )
  456. {
  457. $additional_filter .= " AND CF.show_on_execution=1 ";
  458. }
  459. // 20090523 - franciscom
  460. // Probably this piece need to be changed to act on enable_on_ attribute
  461. // due to CF display logic refactoring
  462. // if( isset($filters['show_on_testplan_design']) && !is_null($filters['show_on_testplan_design']) )
  463. // {
  464. // $additional_filter .= " AND CF.show_on_testplan_design=1 ";
  465. // }
  466. if( isset($filters['show_on_testplan_design']) && !is_null($filters['show_on_testplan_design']) )
  467. {
  468. $additional_filter .= " AND CF.enable_on_testplan_design=1 ";
  469. }
  470. if( isset($filters['cfield_id']) && !is_null($filters['cfield_id']) )
  471. {
  472. $additional_filter .= " AND CF.id={$filters['cfield_id']} ";
  473. }
  474. // 20090717 - franciscom
  475. $filterKey='location';
  476. if( isset($filters[$filterKey]) && !is_null($filters[$filterKey]) )
  477. {
  478. $additional_filter .= " AND CFTP.$filterKey={$filters[$filterKey]} ";
  479. }
  480. }
  481. $sql="SELECT CF.*,CFTP.display_order,CFTP.location" .
  482. $additional_values .
  483. " FROM {$this->object_table} CF " .
  484. " JOIN {$this->tables['cfield_testprojects']} CFTP ON CFTP.field_id=CF.id " .
  485. $additional_join .
  486. " WHERE CFTP.testproject_id={$tproject_id} " .
  487. " AND CFTP.active=1 " .
  488. " AND CF.show_on_design=1 " .
  489. " AND CF.enable_on_design={$enabled} " .
  490. $additional_filter .
  491. " ORDER BY display_order,CF.id ";
  492. $map = $this->db->fetchRowsIntoMap($sql,$access_key);
  493. return($map);
  494. }
  495. /*
  496. ====================================================================
  497. ** Very Imporant **
  498. This code is based on Mantis code.
  499. Initial development was based on 1.x.x versions.
  500. file:custom_field_api.php - function:print_custom_field_input()
  501. 20080815: some changes are done to add more flexibility, and idea
  502. was compared with 1.2.0a1 Mantis implementation.
  503. ====================================================================
  504. function: string_custom_field_input
  505. returns an string with the html needed to display the custom field.
  506. If no specific code is found to manage a custom field type,
  507. it will be used code that manage string type.
  508. args: $p_field_def: contains the definition of the custom field
  509. (including it's field id)
  510. [$name_suffix]: if used must start with _.
  511. example _TCID017
  512. returns: html string
  513. rev :
  514. 20080816 - franciscom
  515. added code to manange user defined (and code developed) Custom Fields.
  516. Important: solution is a mix of own ideas and Mantis 1.2.0a1 approach
  517. 20071006 - francisco.mancardi@gruppotesi.com
  518. Added field_size argument
  519. 20070104 - franciscom - added 'multiselection list'
  520. */
  521. function string_custom_field_input($p_field_def,$name_suffix='',$field_size=0)
  522. {
  523. $str_out='';
  524. $t_id = $p_field_def['id'];
  525. $t_type = $p_field_def['type'];
  526. $t_custom_field_value = $p_field_def['default_value'];
  527. if( isset($p_field_def['value']) )
  528. {
  529. $t_custom_field_value = $p_field_def['value'];
  530. }
  531. $verbose_type=trim($this->custom_field_types[$t_type]);
  532. $t_custom_field_value = htmlspecialchars( $t_custom_field_value );
  533. $input_name="{$this->name_prefix}{$t_type}_{$t_id}{$name_suffix}";
  534. $size = isset($this->sizes[$verbose_type]) ? intval($this->sizes[$verbose_type]) : 0;
  535. if( $field_size > 0)
  536. {
  537. $size=$field_size;
  538. }
  539. switch ($verbose_type)
  540. {
  541. case 'list':
  542. case 'multiselection list':
  543. $t_values = explode( '|', $p_field_def['possible_values']);
  544. if( $verbose_type == 'list' )
  545. {
  546. $t_multiple=' ';
  547. $t_list_size = intval($size) > 0 ? $size :1;
  548. // 20100701 - asimon - removed single space in next line,
  549. // it was causing errors in field names on HTML because it somehow gets replaced
  550. // by an underscore somwhere and then the field name doesn't match anymore
  551. //$t_name_suffix=' ';
  552. $t_name_suffix='';
  553. }
  554. else
  555. {
  556. $window_size = intval($size) > 1 ? $size : self::MULTISELECTIONLIST_WINDOW_SIZE;
  557. $t_name_suffix='[]';
  558. $t_multiple=' multiple="multiple" ';
  559. $t_list_size = count( $t_values );
  560. if($t_list_size > $window_size)
  561. {
  562. $t_list_size=$window_size;
  563. }
  564. }
  565. $html_identity=$input_name . $t_name_suffix;
  566. $str_out .="<select name=\"{$html_identity}\" id=\"{$input_name}\" {$t_multiple}";
  567. $str_out .= ' size="' . $t_list_size . '">';
  568. $t_selected_values = explode( '|', $t_custom_field_value );
  569. foreach( $t_values as $t_option ) {
  570. if( in_array( $t_option, $t_selected_values ) ) {
  571. $str_out .='<option value="' . $t_option . '" selected> ' . $t_option . '</option>';
  572. } else {
  573. $str_out .='<option value="' . $t_option . '">' . $t_option . '</option>';
  574. }
  575. }
  576. $str_out .='</select>';
  577. break;
  578. case 'checkbox':
  579. $t_values = explode( '|', $p_field_def['possible_values']);
  580. $t_checked_values = explode( '|', $t_custom_field_value );
  581. foreach( $t_values as $t_option )
  582. {
  583. $str_out .= '<input type="checkbox" name="' . $input_name . '[]"' . " id=\"{$input_name}\"";
  584. // 20100218 - franciscom - added check $t_option != '' to make check box start NOT CHECKED
  585. if( $t_option != '' && in_array($t_option, $t_checked_values) )
  586. {
  587. $str_out .= ' value="' . $t_option . '" checked="checked">&nbsp;' . $t_option . '&nbsp;&nbsp;';
  588. }
  589. else
  590. {
  591. $str_out .= ' value="' . $t_option . '">&nbsp;' . $t_option . '&nbsp;&nbsp;';
  592. }
  593. }
  594. break;
  595. case 'string':
  596. case 'email':
  597. case 'float':
  598. case 'numeric':
  599. $str_out .= $this->string_input_string($p_field_def,$input_name,$t_custom_field_value,$size);
  600. break ;
  601. case 'text area':
  602. $cols = intval($this->sizes['text area']['cols']);
  603. $rows = intval($this->sizes['text area']['rows']);
  604. if($cols <= 0)
  605. {
  606. $cols = self::TEXTAREA_DEFAULT_COLS;
  607. }
  608. if($rows <= 0)
  609. {
  610. $rows = self::TEXTAREA_DEFAULT_ROWS;
  611. }
  612. if( $this->max_length_value > 0 )
  613. {
  614. $counterId = $input_name . '_counter';
  615. $cf_current_size = $this->max_length_value - tlStringLen($t_custom_field_value);
  616. // call JS function for check max. size from validate.js
  617. $js_function = '"textCounter(this.form.' . $input_name .
  618. ',document.getElementById(\''. $counterId.'\'),' . $this->max_length_value .');" ';
  619. $str_out .= '<textarea name="' . $input_name . '" ' . " id=\"{$input_name}\" " .
  620. 'onKeyDown=' . $js_function . ' onKeyUp=' . $js_function . 'cols="' .
  621. $cols . '" rows="' . $rows . '">' . "{$t_custom_field_value}</textarea>\n";
  622. // show character counter
  623. $str_out .= '<br><span style="vertical-align: top; padding: 5px;">' .
  624. sprintf(lang_get('text_counter_feedback'), $this->max_length_value) .
  625. ' <span id="' . $counterId .'">'.$cf_current_size.'</span>.</span><br>';
  626. }
  627. else
  628. {
  629. // unlimited
  630. $str_out .= '<textarea name="' . $input_name . '" ' . " id=\"{$input_name}\" " .
  631. 'cols="' . $cols . '" rows="' . $rows . '">' . "{$t_custom_field_value}</textarea>\n";
  632. }
  633. break;
  634. case 'date':
  635. $str_out .= create_date_selection_set($input_name,config_get('date_format'),
  636. $t_custom_field_value, false, true) ;
  637. break;
  638. case 'datetime':
  639. $cfg=config_get('gui');
  640. // Important
  641. // We can do this mix (get date format configuration from standard variable
  642. // and time format from an specific custom field config) because string used
  643. // for date_format on strftime() has no problem
  644. // on date() calls (that are used in create_date_selection_set() ).
  645. $datetime_format=config_get('date_format') . " " .$cfg->custom_fields->time_format;
  646. $str_out .=create_date_selection_set($input_name,$datetime_format,
  647. $t_custom_field_value, false, true,date( "Y" )-1) ;
  648. break;
  649. default:
  650. $dynamic_call='string_input_' . str_replace(' ', '_', $verbose_type);
  651. if( function_exists($dynamic_call) )
  652. {
  653. $str_out .= $dynamic_call($p_field_def, $input_name, $t_custom_field_value);
  654. }
  655. else if( method_exists($this, $dynamic_call) )
  656. {
  657. $str_out .= $this->$dynamic_call($p_field_def, $input_name, $t_custom_field_value);
  658. }
  659. else
  660. {
  661. // treat it as an simple string
  662. $str_out .= $this->string_input_string($p_field_def,$input_name,$t_custom_field_value,$size);
  663. }
  664. break;
  665. }
  666. return ($str_out);
  667. } //function end
  668. /*
  669. function: design_values_to_db
  670. write values of custom fields that are used at design time.
  671. args: $hash: contains info about CF gathered at user interface.
  672. (normally $_REQUEST variable)
  673. key: custom_field_<field_type_id>_<cfield_id>.
  674. Example custom_field_0_67 -> 0=> string field
  675. $node_id:
  676. [$cf_map]: hash -> all the custom fields linked and enabled
  677. that are applicable to the node type of $node_id.
  678. For the keys not present in $hash, we will write
  679. an appropriate value according to custom field
  680. type.
  681. This is needed because when trying to udpate
  682. with hash being $_REQUEST, $_POST or $_GET
  683. some kind of custom fields (checkbox, list, multiple list)
  684. when has been deselected by user.
  685. rev:
  686. 20070525 - franciscom - added [hash_type], to reuse this method on
  687. class testcase method copy_cfields_design_values()
  688. 20070501 - franciscom - limiting lenght of value before writting
  689. 20070105 - franciscom - added $cf_map
  690. 20070104 - franciscom - need to manage multiselection in a different way
  691. */
  692. function design_values_to_db($hash,$node_id,$cf_map=null,$hash_type=null)
  693. {
  694. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  695. if( is_null($hash) && is_null($cf_map) )
  696. {
  697. return;
  698. }
  699. if( is_null($hash_type) )
  700. {
  701. $cfield=$this->_build_cfield($hash,$cf_map);
  702. }
  703. else
  704. {
  705. $cfield=$hash;
  706. }
  707. if( !is_null($cfield) )
  708. {
  709. //new dBug($cfield);
  710. foreach($cfield as $field_id => $type_and_value)
  711. {
  712. $value = $type_and_value['cf_value'];
  713. // do I need to update or insert this value?
  714. $sql = "/* $debugMsg */ SELECT value FROM {$this->tables['cfield_design_values']} " .
  715. " WHERE field_id={$field_id} AND node_id={$node_id}";
  716. $result = $this->db->exec_query($sql);
  717. // max_length_value = 0 => no limit
  718. if( $this->max_length_value > 0 && tlStringLen($value) > $this->max_length_value)
  719. {
  720. $value = substr($value,0,$this->max_length_value);
  721. }
  722. $safe_value=$this->db->prepare_string($value);
  723. if($this->db->num_rows( $result ) > 0 )
  724. {
  725. $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_design_values']} " .
  726. " SET value='{$safe_value}' " .
  727. " WHERE field_id={$field_id} AND node_id={$node_id}";
  728. }
  729. else
  730. {
  731. # Remark got from Mantis code:
  732. # Always store the value, even if it's the dafault value
  733. # This is important, as the definitions might change but the
  734. # values stored with a bug must not change
  735. $sql = "/* $debugMsg */ INSERT INTO {$this->tables['cfield_design_values']} " .
  736. " ( field_id, node_id, value ) " .
  737. " VALUES ( {$field_id}, {$node_id}, '{$safe_value}' )";
  738. }
  739. $this->db->exec_query($sql);
  740. } //foreach($cfield
  741. } //if( !is_null($cfield) )
  742. } //function end
  743. /*
  744. function: remove_all_design_values_from_node
  745. remove the values of ALL custom fields linked to
  746. a node. (example test case 5555)
  747. args: $node_id: single value or array
  748. returns: -
  749. rev :
  750. 20070102 - franciscom - $node_id can be an array
  751. */
  752. function remove_all_design_values_from_node($node_id)
  753. {
  754. $sql="DELETE FROM {$this->tables['cfield_design_values']} ";
  755. if( is_array($node_id) )
  756. {
  757. $sql .= " WHERE node_id IN(" . implode(",",$node_id) . ") ";
  758. }
  759. else
  760. {
  761. $sql .= " WHERE node_id={$node_id}";
  762. }
  763. $this->db->exec_query($sql);
  764. } //function end
  765. /*
  766. function: get_all
  767. get the definition of all custom field defined in the system,
  768. or all custom fields with id not included in $id2exclude.
  769. args: [$id2exclude]: array with custom field ids
  770. returns: hash:
  771. key: custom field id
  772. */
  773. function get_all($id2exclude=null)
  774. {
  775. $not_in_clause="";
  776. if( !is_null($id2exclude) )
  777. {
  778. $not_in_clause=" AND CF.id NOT IN (" .implode(',',$id2exclude) .") ";
  779. }
  780. $sql="SELECT CF.*,NT.description AS node_description,NT.id AS node_type_id " .
  781. " FROM {$this->object_table} CF, " .
  782. " {$this->tables['cfield_node_types']} CFNT, " .
  783. " {$this->tables['node_types']} NT " .
  784. " WHERE CF.id=CFNT.field_id " .
  785. " AND NT.id=CFNT.node_type_id " .
  786. $not_in_clause .
  787. " ORDER BY CF.name";
  788. // $map = $this->db->fetchArrayRowsIntoMap($sql,'id');
  789. $map = $this->db->fetchRowsIntoMap($sql,'id');
  790. return($map);
  791. }
  792. /*
  793. function: get_linked_to_testproject
  794. get definition of all custom fields linked to a test project.
  795. args: $tproject_id
  796. [$active]: if not null will add the following filter " AND CFTP.active={$active}"
  797. returns: hash:
  798. key: custom field id
  799. internal revision:
  800. 20090717 - franciscom - added location to result recordset
  801. */
  802. function get_linked_to_testproject($tproject_id,$active=null)
  803. {
  804. $sql="SELECT CF.*,NT.description AS node_description,NT.id AS node_type_id, " .
  805. " CFTP.display_order, CFTP.active, CFTP.location " .
  806. " FROM {$this->object_table} CF, " .
  807. " {$this->tables['cfield_testprojects']} CFTP, " .
  808. " {$this->tables['cfield_node_types']} CFNT, " .
  809. " {$this->tables['node_types']} NT " .
  810. " WHERE CF.id=CFNT.field_id " .
  811. " AND CF.id=CFTP.field_id " .
  812. " AND NT.id=CFNT.node_type_id " .
  813. " AND CFTP.testproject_id={$tproject_id} ";
  814. if( !is_null($active) )
  815. {
  816. $sql .= " AND CFTP.active={$active} ";
  817. }
  818. //$sql .= " ORDER BY display_order, CF.name";
  819. // BUGID 3555
  820. $sql .= " ORDER BY CF.enable_on_design desc, " .
  821. "CF.enable_on_execution desc, " .
  822. "CF.enable_on_testplan_design desc,".
  823. "CFTP.display_order, CF.name";
  824. $map = $this->db->fetchRowsIntoMap($sql,'id');
  825. return($map);
  826. }
  827. /*
  828. function: link_to_testproject
  829. args: $tproject_id
  830. $cfields_id: array()
  831. returns: -
  832. */
  833. function link_to_testproject($tproject_id,$cfield_ids)
  834. {
  835. if(is_null($cfield_ids))
  836. {
  837. return;
  838. }
  839. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  840. $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
  841. foreach($cfield_ids as $field_id)
  842. {
  843. $sql = "/* $debugMsg */ INSERT INTO {$this->tables['cfield_testprojects']} " .
  844. " (testproject_id,field_id) " .
  845. " VALUES({$tproject_id},{$field_id})";
  846. if ($this->db->exec_query($sql))
  847. {
  848. $cf = $this->get_by_id($field_id);
  849. if ($cf)
  850. {
  851. logAuditEvent(TLS("audit_cfield_assigned",$cf[$field_id]['name'],$tproject_info['name']),
  852. "ASSIGN",$tproject_id,"testprojects");
  853. }
  854. }
  855. }
  856. } //function end
  857. /*
  858. function: set_active_for_testproject
  859. set the value of active field
  860. args: $tproject_id
  861. $cfields_id: array()
  862. $active_val: 1/0
  863. returns: -
  864. */
  865. function set_active_for_testproject($tproject_id,$cfield_ids,$active_val)
  866. {
  867. if(is_null($cfield_ids))
  868. {
  869. return;
  870. }
  871. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  872. $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
  873. $auditMsg = $active_val ? "audit_cfield_activated" : "audit_cfield_deactivated";
  874. foreach($cfield_ids as $field_id)
  875. {
  876. $sql = "/* $debugMsg */ UPDATE {$this->tables['cfield_testprojects']} " .
  877. " SET active={$active_val} " .
  878. " WHERE testproject_id={$tproject_id} " .
  879. " AND field_id={$field_id}";
  880. if ($this->db->exec_query($sql))
  881. {
  882. $cf = $this->get_by_id($field_id);
  883. if ($cf)
  884. {
  885. logAuditEvent(TLS($auditMsg,$cf[$field_id]['name'],$tproject_info['name']),
  886. "SAVE",$tproject_id,"testprojects");
  887. }
  888. }
  889. }
  890. } //function end
  891. /**
  892. * unlink_from_testproject
  893. * remove custom field links from target test project
  894. * N.B.: following Mantis Bugtracking System model,
  895. * this operation will NOR remove all values assigned to
  896. * these custom fields .
  897. *
  898. * @param int $tproject_id
  899. * @param array $cfield_ids
  900. *
  901. */
  902. function unlink_from_testproject($tproject_id,$cfield_ids)
  903. {
  904. if(is_null($cfield_ids))
  905. {
  906. return;
  907. }
  908. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  909. // just for audit porpouses
  910. $tproject_info = $this->tree_manager->get_node_hierarchy_info($tproject_id);
  911. foreach($cfield_ids as $field_id)
  912. {
  913. // BUGID 0000677
  914. $sql = "/* $debugMsg */ DELETE FROM {$this->tables['cfield_testprojects']} " .
  915. " WHERE field_id = {$field_id} AND testproject_id = {$tproject_id} ";
  916. if ($this->db->exec_query($sql))
  917. {
  918. $cf = $this->get_by_id($field_id);
  919. if ($cf)
  920. {
  921. logAuditEvent(TLS("audit_cfield_unassigned",$cf[$field_id]['name'],$tproject_info['name']),
  922. "ASSIGN",$tproject_id,"testprojects");
  923. }
  924. }
  925. }
  926. } //function end
  927. /*
  928. function: get_by_name
  929. get custom field definition
  930. args: $name: custom field name
  931. returns: hash
  932. */
  933. function get_by_name($name)
  934. {
  935. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  936. $my_name=$this->db->prepare_string(trim($name));
  937. $sql="/* $debugMsg */ SELECT CF.*, CFNT.node_type_id,NT.description AS node_type" .
  938. " FROM {$this->tables['custom_fields']} CF, {$this->tables['cfield_node_types']} CFNT," .
  939. " {$this->tables['node_types']} NT" .
  940. " WHERE CF.id=CFNT.field_id " .
  941. " AND CFNT.node_type_id=NT.id " .
  942. " AND name='{$my_name}' ";
  943. return($this->db->fetchRowsIntoMap($sql,'id'));
  944. }
  945. /*
  946. function: get_by_id
  947. get custom field definition
  948. args: $id: custom field id
  949. returns: hash
  950. */
  951. function get_by_id($id)
  952. {
  953. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  954. $sql="/* $debugMsg */ SELECT CF.*, CFNT.node_type_id" .
  955. " FROM {$this->tables['custom_fields']} CF, {$this->tables['cfield_node_types']} CFNT" .
  956. " WHERE CF.id=CFNT.field_id " .
  957. " AND CF.id={$id} ";
  958. return($this->db->fetchRowsIntoMap($sql,'id'));
  959. }
  960. /*
  961. function: get_available_item_type
  962. get information about what item type (testcase,testplan, etc)
  963. can use this custom field
  964. args: $id: custom field id
  965. returns:
  966. */
  967. function get_available_item_type($id)
  968. {
  969. $debugMsg = 'Class:' . __CLASS__ . ' - Method: ' . __FUNCTION__;
  970. $sql="/* $debugMsg */ SELECT CFNT.field_id,CFNT.node_type_id ".
  971. " FROM {$this->tables['cfield_node_types']} CFNT, " .
  972. " {$this->tables['nodes_types']} NT " .
  973. " WHERE NT.id=CFNT.node_type_id " .
  974. " CFNt.field_id={$id} ";
  975. return($this->db->fetchRowsIntoMap($sql,'field_id'));
  976. }
  977. /*
  978. function: create a custom field
  979. args: $hash:
  980. keys name
  981. label
  982. type
  983. possible_values
  984. show_on_design
  985. enable_on_design
  986. show_on_execute
  987. enable_on_execute
  988. show_on_testplan_design
  989. enable_on_testplan_design
  990. node_type_id
  991. returns: -
  992. rev: 20080810 - franciscom - BUGID 1650
  993. */
  994. function create($cf)
  995. {
  996. $ret = array('status_ok' => 0, 'id' => 0, 'msg' => 'ko');
  997. $my_name=$this->db->prepare_string($cf['name']);
  998. $my_label=$this->db->prepare_string($cf['label']);
  999. $my_pvalues=$this->db->prepare_string($cf['possible_values']);
  1000. $sql="INSERT INTO {$this->object_table} " .
  1001. " (name,label,type,possible_values, " .
  1002. " show_on_design,enable_on_design, " .
  1003. " show_on_testplan_design,enable_on_testplan_design, " .
  1004. " show_on_execution,enable_on_execution) " .
  1005. " VALUES('{$my_name}','{$my_label}',{$cf['type']},'{$my_pvalues}', " .
  1006. " {$cf['show_on_design']},{$cf['enable_on_design']}," .
  1007. " {$cf['show_on_testplan_design']},{$cf['enable_on_testplan_design']}," .
  1008. " {$cf['show_on_execution']},{$cf['enable_on_execution']})";
  1009. $result=$this->db->exec_query($sql);
  1010. if ($result)
  1011. {
  1012. // at least for Postgres DBMS table name is needed.
  1013. $field_id=$this->db->insert_id($this->object_table);
  1014. $sql="INSERT INTO {$this->tables['cfield_node_types']} " .
  1015. " (field_id,node_type_id) " .
  1016. " VALUES({$field_id},{$cf['node_type_id']}) ";
  1017. $result=$this->db->exec_query($sql);
  1018. }
  1019. if ($result)
  1020. {
  1021. $ret = array('status_ok' => 1, 'id' => $field_id, 'msg' => 'ok');
  1022. }
  1023. return($ret);
  1024. } //function end
  1025. /*
  1026. function: update a custom field
  1027. args: $hash:
  1028. keys name
  1029. label
  1030. type
  1031. possible_values
  1032. show_on_design
  1033. enable_on_design
  1034. show_on_execute
  1035. enable_on_execute
  1036. show_on_testplan_design
  1037. enable_on_testplan_design
  1038. node_type_id
  1039. returns: -
  1040. */
  1041. function update($cf)
  1042. {
  1043. $my_name = $this->db->prepare_string($cf['name']);
  1044. $my_label = $this->db->prepare_string($cf['label']);
  1045. $my_pvalues = $this->db->prepare_string($cf['possible_values']);
  1046. $sql ="UPDATE {$this->tables['custom_fields']} " .
  1047. " SET name='{$my_name}',label='{$my_label}'," .
  1048. " type={$cf['type']},possible_values='{$my_pvalues}'," .
  1049. " show_on_design={$cf['show_on_design']}," .
  1050. " enable_on_design={$cf['enable_on_design']}," .
  1051. " show_on_testplan_design={$cf['show_on_testplan_design']}," .
  1052. " enable_on_testplan_design={$cf['enable_on_testplan_design']}," .
  1053. " show_on_execution={$cf['show_on_execution']}," .
  1054. " enable_on_execution={$cf['enable_on_execution']}" .
  1055. " WHERE id={$cf['id']}";
  1056. $result = $this->db->exec_query($sql);
  1057. if ($result)
  1058. {
  1059. $sql = "UPDATE {$this->tables['cfield_node_types']} " .
  1060. " SET node_type_id={$cf['node_type_id']}" .
  1061. " WHERE field_id={$cf['id']}";
  1062. $result = $this->db->exec_query($sql);
  1063. }
  1064. return $result ? 1 : 0;
  1065. } //function end
  1066. /**
  1067. * delete()
  1068. * Will delete custom field definition and also ALL assigned values
  1069. * If custom field is linked to test projects, these links must be removed
  1070. *
  1071. */
  1072. function delete($id)
  1073. {
  1074. // Before deleting definition I need to remove values
  1075. if( $this->is_used($id) )
  1076. {
  1077. $this->remove_all_scopes_values($id);
  1078. }
  1079. $linked_tprojects = $this->get_linked_testprojects($id);
  1080. if( !is_null($linked_tprojects) && count($linked_tprojects) > 0 )
  1081. {
  1082. $target=array_keys($linked_tprojects);
  1083. foreach($target as $tproject_id)
  1084. {
  1085. $this->unlink_from_testproject($tproject_id,(array)$id);
  1086. }
  1087. }
  1088. $sql="DELETE FROM {$this->tables['cfield_node_types']} WHERE field_id={$id}";
  1089. $result=$this->db->exec_query($sql);
  1090. if($result)
  1091. {
  1092. $sql="DELETE FROM {$this->tables['custom_fields']} WHERE id={$id}";
  1093. $result=$this->db->exec_query($sql);
  1094. }
  1095. return $result ? 1 : 0;
  1096. }
  1097. /*
  1098. function: is_used
  1099. args: $id: custom field id
  1100. returns: 1/0
  1101. rev: 20080810 - franciscom - BUGID 1650
  1102. */
  1103. function is_used($id)
  1104. {
  1105. $sql="SELECT field_id FROM {$this->tables['cfield_design_values']} " .
  1106. "WHERE field_id={$id} " .
  1107. "UNION " .
  1108. "SELECT field_id FROM {$this->tables['cfield_testplan_design_values']} " .
  1109. "WHERE field_id={$id} " .
  1110. "UNION " .
  1111. "SELECT field_id FROM {$this->tables['cfield_execution_values']} " .
  1112. "WHERE field_id={$id} ";
  1113. $result=$this->db->exec_query($sql);
  1114. return($this->db->num_rows( $result ) > 0 ? 1 : 0);
  1115. } //function end
  1116. /*
  1117. function: whoIsUsingMe
  1118. args: $id: custom field id
  1119. returns:
  1120. */
  1121. function whoIsUsingMe($id)
  1122. {
  1123. $sql=" SELECT field_id,name ".
  1124. " FROM {$this->tables['cfield_design_values']} CFDV, ".
  1125. " {$this->tables['cfield_node_types']} CFNT, " .
  1126. " {$this->tables['nodes_hierarchy']} NH " .
  1127. " WHERE CFDV.field_id=CFNT.field_id " .
  1128. " AND NH.id=CFDV.node_id " .
  1129. " CFDV.field_id={$id} ";
  1130. } //function end
  1131. /*
  1132. function: name_is_unique
  1133. args: $id
  1134. $name
  1135. returns: 1 => name is unique
  1136. */
  1137. function name_is_unique($id,$name)
  1138. {
  1139. $cf=$this->get_by_name($name);
  1140. $status=0;
  1141. if( is_null($cf) || isset($cf[$id]) )
  1142. {
  1143. $status=1;
  1144. }
  1145. return($status);
  1146. } //function end
  1147. # --------------------
  1148. # Adapted from Mantis code
  1149. # Prepare a string containing a custom field value for display
  1150. # $p_field_def definition of the custom field
  1151. # $p_node_id bug id to display the custom field value for
  1152. #
  1153. # [$p_value_field]: field id, to point to the field value in $p_field_def
  1154. function string_custom_field_value( $p_field_def, $p_node_id,$p_value_field='value')
  1155. {
  1156. $t_custom_field_value=htmlspecialchars($p_field_def[$p_value_field]);
  1157. switch ($this->custom_field_types[$p_field_def['type']])
  1158. {
  1159. case 'email':
  1160. return "<a href=\"mailto:$t_custom_field_value\">$t_custom_field_value</a>";
  1161. break;
  1162. case 'enum':
  1163. case 'list':
  1164. case 'multiselection list':
  1165. case 'checkbox':
  1166. return str_replace( '|', ', ', $t_custom_field_value );
  1167. break;
  1168. case 'date':
  1169. if ($t_custom_field_value != null)
  1170. {
  1171. // must remove %
  1172. $t_date_format=str_replace("%","",config_get( 'date_format'));
  1173. $xdate=date( $t_date_format, $t_custom_field_value);
  1174. return $xdate;
  1175. }
  1176. break ;
  1177. case 'datetime':
  1178. if ($t_custom_field_value != null)
  1179. {
  1180. // must remove %
  1181. // $t_date_format=str_replace("%","",config_get( 'timestamp_format'));
  1182. // $datetime_format=$t_date_format;
  1183. $t_date_format=str_replace("%","",config_get( 'date_format'));
  1184. $cfg=config_get('gui');
  1185. $datetime_format=$t_date_format . " " .$cfg->custom_fields->time_format;
  1186. $xdate=date( $datetime_format, $t_custom_field_value);
  1187. return $xdate;
  1188. }
  1189. break ;
  1190. case 'text area':
  1191. if ($t_custom_field_value != null)
  1192. {
  1193. return nl2br($t_custom_field_value);
  1194. }
  1195. break;
  1196. default:
  1197. // 20071027 - franciscom
  1198. // This code manages URLs
  1199. return string_display_links( $t_custom_field_value );
  1200. // return($t_custom_field_value);
  1201. }
  1202. }
  1203. /*
  1204. function: get_linked_cfields_at_execution
  1205. returns information about custom fields that can be used
  1206. at least at executed, with the value assigned (is any has been assigned).
  1207. $tproject_id: needed because is possible to associate/link
  1208. a differen…

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