From c4507fdbe00b0a7a496fa12d21ca3708a8a865e2 Mon Sep 17 00:00:00 2001
From: Vincent Sels <vincent_sels@hotmail.com>
Date: Sun, 5 Feb 2012 18:52:19 +0100
Subject: [PATCH] Added custom field 'Template'

When choosing custom field type 'Template', you can define a template value with
a placeholder ({0}) in the 'Default value' field. Upon entering a
value for this custom field, it will be inserted in the template's
placeholder. Links will be interpreted.
---
 config_defaults_inc.php        |    2 +-
 core/cfdefs/cfdef_standard.php |   44 ++++++++++++++++++++++++++++++++++++++++
 core/constant_inc.php          |    1 +
 core/custom_field_api.php      |   32 +++++++++++++---------------
 core/email_api.php             |    2 +-
 core/gpc_api.php               |    1 +
 lang/strings_dutch.txt         |    2 +-
 lang/strings_english.txt       |    2 +-
 8 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/config_defaults_inc.php b/config_defaults_inc.php
index 7087dab..cd59cb1 100644
--- a/config_defaults_inc.php
+++ b/config_defaults_inc.php
@@ -3019,7 +3019,7 @@
 	 *
 	 * @global string $g_custom_field_type_enum_string
 	 */
-	$g_custom_field_type_enum_string    = '0:string,1:numeric,2:float,3:enum,4:email,5:checkbox,6:list,7:multiselection list,8:date,9:radio';
+	$g_custom_field_type_enum_string    = '0:string,1:numeric,2:float,3:enum,4:email,5:checkbox,6:list,7:multiselection list,8:date,9:radio,10:template';
 
 	/*********************************
 	 * MantisBT Javascript Variables *
diff --git a/core/cfdefs/cfdef_standard.php b/core/cfdefs/cfdef_standard.php
index f358d3b..c1ea092 100644
--- a/core/cfdefs/cfdef_standard.php
+++ b/core/cfdefs/cfdef_standard.php
@@ -158,6 +158,20 @@ $g_custom_field_type_definition[ CUSTOM_FIELD_TYPE_DATE ] = array (
 	'#function_string_value_for_email' => 'cfdef_prepare_date_value_for_email',
 );
 
+$g_custom_field_type_definition[ CUSTOM_FIELD_TYPE_TEMPLATE ] = array (
+	'#display_possible_values' => FALSE,
+	'#display_valid_regexp' => TRUE,
+	'#display_length_min' => TRUE,
+	'#display_length_max' => TRUE,
+	'#display_default_value' => TRUE,
+	'#function_return_distinct_values' => null,
+	'#function_value_to_database' => null,
+	'#function_database_to_value' => null,
+	'#function_print_input' => 'cfdef_input_textbox',
+	'#function_string_value' => 'cfdef_prepare_template_value',
+	'#function_string_value_for_email' => 'cfdef_prepare_template_value_for_email',
+);
+
 function cfdef_prepare_list_database_to_value($p_value) {
 	return rtrim( ltrim( $p_value, '|' ), '|' );
 }
@@ -224,6 +238,36 @@ function cfdef_prepare_date_value($p_value) {
 	}
 }
 
+/**
+ * Replaces the wildcard '{0}' from the field's 'default value' with the specified $p_value.
+ * Also converts the resulting string to a link if applicable.
+ * @param $p_value The value to be inserted in the template
+ * @return string replaces the wildcard '{0}' from the 'default value' with the specified $p_value
+ */
+function cfdef_prepare_template_value($p_value, $p_field_def) {
+	$t_template = $p_field_def['default_value'];
+
+	if ( empty( $p_value ) ) {
+		return '';
+	}
+
+	return string_display_line_links(str_replace('{0}', $p_value, $t_template));
+}
+
+/**
+ * Replaces the wildcard '{0}' from the field's 'default value' with the specified $p_value
+ * @param $p_value The value to be inserted in the template
+ * @return string replaces the wildcard '{0}' from the 'default value' with the specified $p_value
+ */
+function cfdef_prepare_template_value_for_email($p_value, $p_field_def) {
+	$t_template = $p_field_def['default_value'];
+
+	if ( empty( $p_value ) ) {
+		return '';
+	}
+
+	return str_replace('{0}', $p_value, $t_template);
+}
 
 #print_custom_field_input
 
diff --git a/core/constant_inc.php b/core/constant_inc.php
index a10a54b..149ec5e 100644
--- a/core/constant_inc.php
+++ b/core/constant_inc.php
@@ -416,6 +416,7 @@ define( 'CUSTOM_FIELD_TYPE_LIST', 6 );
 define( 'CUSTOM_FIELD_TYPE_MULTILIST', 7 );
 define( 'CUSTOM_FIELD_TYPE_DATE', 8 );
 define( 'CUSTOM_FIELD_TYPE_RADIO', 9 );
+define( 'CUSTOM_FIELD_TYPE_TEMPLATE', 10 );
 
 # Meta filter values
 define( 'META_FILTER_MYSELF', -1 );
diff --git a/core/custom_field_api.php b/core/custom_field_api.php
index a6faa8a..4e6d8c4 100644
--- a/core/custom_field_api.php
+++ b/core/custom_field_api.php
@@ -53,6 +53,7 @@ $g_custom_field_types[CUSTOM_FIELD_TYPE_CHECKBOX] = 'standard';
 $g_custom_field_types[CUSTOM_FIELD_TYPE_LIST] = 'standard';
 $g_custom_field_types[CUSTOM_FIELD_TYPE_MULTILIST] = 'standard';
 $g_custom_field_types[CUSTOM_FIELD_TYPE_DATE] = 'standard';
+$g_custom_field_types[CUSTOM_FIELD_TYPE_TEMPLATE] = 'standard';
 
 foreach( $g_custom_field_types as $type ) {
 	require_once( 'cfdefs' . DIRECTORY_SEPARATOR . 'cfdef_' . $type . '.php' );
@@ -380,9 +381,9 @@ function custom_field_has_write_access( $p_field_id, $p_bug_id, $p_user_id = nul
 }
 
 /**
- * create a new custom field with the name $p_name
- * the definition are the default values and can be changes later
- * return the ID of the new definition
+ * create a new custom field with the name $p_name.
+ * the definition are the default values and can be changed later.
+ * return the ID of the new definition.
  * @param string $p_name custom field name
  * @return int custom field id
  * @access public
@@ -413,7 +414,7 @@ function custom_field_create( $p_name ) {
 }
 
 /**
- * Update the field definition
+ * Update the field definition.
  * return true on success, false on failure
  * @param int $p_field_id custom field id
  * @param array custom field definition
@@ -984,9 +985,6 @@ function custom_field_get_value( $p_field_id, $p_bug_id ) {
 
 	$row = custom_field_cache_row( $p_field_id );
 
-	$t_access_level_r = $row['access_level_r'];
-	$t_default_value = $row['default_value'];
-
 	if( !custom_field_has_read_access( $p_field_id, $p_bug_id, auth_get_current_user_id() ) ) {
 		return false;
 	}
@@ -1148,6 +1146,7 @@ function custom_field_validate( $p_field_id, $p_value ) {
 	$t_length = utf8_strlen( $p_value );
 	switch ($t_type) {
 		case CUSTOM_FIELD_TYPE_STRING:
+		case CUSTOM_FIELD_TYPE_TEMPLATE:
 			# Regular expression string validation
 			if( !is_blank( $t_valid_regexp ) && !is_blank( $p_value ) ) {
 				$t_valid &= preg_match( "/$t_valid_regexp/", $p_value );
@@ -1243,7 +1242,6 @@ function custom_field_prepare_possible_values( $p_possible_values ) {
 function custom_field_distinct_values( $p_field_def, $p_project_id = ALL_PROJECTS ) {
 	global $g_custom_field_type_definition;
 	$c_field_id = $p_field_def['id'];
-	$c_project_id = db_prepare_int( $p_project_id );
 	$t_custom_field_string_table = db_get_table( 'mantis_custom_field_string_table' );
 	$t_mantis_bug_table = db_get_table( 'mantis_bug_table' );
 	$t_return_arr = array();
@@ -1414,10 +1412,10 @@ function custom_field_set_sequence( $p_field_id, $p_project_id, $p_sequence ) {
 
 /**
  * Print an input field
- * $p_field_def contains the definition of the custom field (including it's field id
+ * $p_field_def contains the definition of the custom field (including its field id)
  * $p_bug_id    contains the bug where this field belongs to. If it's left
- * away, it'll default to 0 and thus belongs to a new (i.e. non-existant) bug
- * NOTE: This probably belongs in the print_api.php
+ * away, it'll default to 0 and thus belong to a new (i.e. non-existant) bug
+ * @todo This probably belongs in the print_api.php
  * @param array $p_field_def custom field definition
  * @param int $p_bug_id bug id
  * @access public
@@ -1461,14 +1459,14 @@ function string_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
 	}
 	global $g_custom_field_type_definition;
 	if( isset( $g_custom_field_type_definition[$p_def['type']]['#function_string_value'] ) ) {
-		return call_user_func( $g_custom_field_type_definition[$p_def['type']]['#function_string_value'], $t_custom_field_value );
+		return call_user_func( $g_custom_field_type_definition[$p_def['type']]['#function_string_value'], $t_custom_field_value , $p_def );
 	}
 	return string_display_links( $t_custom_field_value );
 }
 
 /**
  * Print a custom field value for display
- * NOTE: This probably belongs in the print_api.php
+ * @todo This probably belongs in the print_api.php
  * @param array  $p_def contains the definition of the custom field
  * @param int $p_field_id contains the id of the field
  * @param int $p_bug_id contains the bug id to display the custom field value for
@@ -1481,16 +1479,16 @@ function print_custom_field_value( $p_def, $p_field_id, $p_bug_id ) {
 
 /**
  * Prepare a string containing a custom field value for email
- * NOTE: This probably belongs in the string_api.php
+ * @todo This probably belongs in the string_api.php
  * @param string $p_value value of custom field
  * @param int $p_type	type of custom field
  * @return string value ready for sending via email
  * @access public
  */
-function string_custom_field_value_for_email( $p_value, $p_type ) {
+function string_custom_field_value_for_email( $p_value, $p_def ) {
 	global $g_custom_field_type_definition;
-	if( isset( $g_custom_field_type_definition[$p_type]['#function_string_value_for_email'] ) ) {
-		return call_user_func( $g_custom_field_type_definition[$p_type]['#function_string_value_for_email'], $p_value );
+	if( isset( $g_custom_field_type_definition[$p_def['type']]['#function_string_value_for_email'] ) ) {
+		return call_user_func( $g_custom_field_type_definition[$p_def['type']]['#function_string_value_for_email'], $p_value, $p_def );
 	}
 	return $p_value;
 }
diff --git a/core/email_api.php b/core/email_api.php
index 59bb51c..a947560 100644
--- a/core/email_api.php
+++ b/core/email_api.php
@@ -1240,7 +1240,7 @@ function email_format_bug_message( $p_visible_bug_data ) {
 	# custom fields formatting
 	foreach( $p_visible_bug_data['custom_fields'] as $t_custom_field_name => $t_custom_field_data ) {
 		$t_message .= utf8_str_pad( lang_get_defaulted( $t_custom_field_name, null ) . ': ', $t_email_padding_length, ' ', STR_PAD_RIGHT );
-		$t_message .= string_custom_field_value_for_email( $t_custom_field_data['value'], $t_custom_field_data['type'] );
+		$t_message .= string_custom_field_value_for_email( $t_custom_field_data['value'], $t_custom_field_data );
 		$t_message .= " \n";
 	}
 
diff --git a/core/gpc_api.php b/core/gpc_api.php
index a08205a..7ae01bc 100644
--- a/core/gpc_api.php
+++ b/core/gpc_api.php
@@ -182,6 +182,7 @@ function gpc_isset_custom_field( $p_var_name, $p_custom_field_type ) {
 		case CUSTOM_FIELD_TYPE_FLOAT:
 		case CUSTOM_FIELD_TYPE_ENUM:
 		case CUSTOM_FIELD_TYPE_EMAIL:
+		case CUSTOM_FIELD_TYPE_TEMPLATE:
 			return gpc_isset( $t_field_name ) && !is_blank( gpc_get_string( $t_field_name ) );
 		default:
 			return gpc_isset( $t_field_name );
diff --git a/lang/strings_dutch.txt b/lang/strings_dutch.txt
index 438a89e..5d5b221 100644
--- a/lang/strings_dutch.txt
+++ b/lang/strings_dutch.txt
@@ -1006,7 +1006,7 @@ $s_link_custom_field_to_project_title = 'Gebruikersveld aan project koppelen';
 $s_link_custom_field_to_project_button = 'Gebruikersveld koppelen';
 $s_linked_projects = 'Gekoppelde projecten';
 $s_custom_field_sequence = 'Volgorde';
-$s_custom_field_type_enum_string = '0:String,1:Numeriek,2:Drijvende komma,3:Enumeratie,4:E-mail,5:Checkbox,6:Lijst,7:Multiselectie lijst,8:Datum,9:Keuzerondje';
+$s_custom_field_type_enum_string = '0:String,1:Numeriek,2:Drijvende komma,3:Enumeratie,4:E-mail,5:Checkbox,6:Lijst,7:Multiselectie lijst,8:Datum,9:Keuzerondje,10:Template';
 $s_confirm_used_custom_field_deletion = 'Op dit moment is dit veld verbonden met tenminste één project.  Als u doorgaat, worden alle waarden voor dit veld permanent verwijderd. Deze handeling kan niet ongedaan gemaakt worden. Als u dit veld niet wilt verwijderen, klik dan op de knop "Vorige" in uw browser. Klik op onderstaande knop om door te gaan.';
 $s_confirm_custom_field_deletion = 'Weet u zeker dat u dit gebruikersveld en alle bijbehorende waarden wilt verwijderen?';
 $s_field_delete_button = 'Gebruikersveld verwijderen';
diff --git a/lang/strings_english.txt b/lang/strings_english.txt
index bf638cb..f166eaa 100644
--- a/lang/strings_english.txt
+++ b/lang/strings_english.txt
@@ -1304,7 +1304,7 @@ $s_link_custom_field_to_project_button = 'Link Custom Field';
 $s_linked_projects = 'Linked Projects';
 
 $s_custom_field_sequence = 'Sequence';
-$s_custom_field_type_enum_string = '0:String,1:Numeric,2:Float,3:Enumeration,4:E-mail,5:Checkbox,6:List,7:Multiselection list,8:Date,9:Radio';
+$s_custom_field_type_enum_string = '0:String,1:Numeric,2:Float,3:Enumeration,4:E-mail,5:Checkbox,6:List,7:Multiselection list,8:Date,9:Radio,10:Template';
 
 $s_confirm_used_custom_field_deletion = 'This field is currently linked to at least one project. If you continue all values for this field will be permanently deleted. This action cannot be undone. If you do not want to delete this field, hit the Back button in your browser. To proceed, click the button below';
 $s_confirm_custom_field_deletion = 'Are you sure you want to delete this custom field and all associated values?';
-- 
1.7.6.msysgit.0

