View Issue Details

IDProjectCategoryView StatusLast Update
0004138mantisbtbugtrackerpublic2004-08-29 02:07
Reporterthraxisp Assigned Tothraxisp  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Version0.19.0a2 
Fixed in Version0.19.0rc1 
Summary0004138: Add validation / notifications hooks for issue create/update/delete
Description

The original subject was:
"Add option to make fields mandatory on resolve"

Filling in the fixed_in_version and resolution should be required to resolve an issue. This could be driven by an option.

TagsNo tags attached.
Attached Files
resolve_hook.diff (13,213 bytes)   
Index: bug_report.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_report.php,v
retrieving revision 1.33
diff -u -r1.33 bug_report.php
--- bug_report.php	1 Aug 2004 22:24:58 -0000	1.33
+++ bug_report.php	4 Aug 2004 14:22:45 -0000
@@ -25,32 +25,33 @@
 <?php
 	access_ensure_project_level( config_get('report_bug_threshold' ) );
 
-	$f_build				= gpc_get_string( 'build', '' );
-	$f_platform				= gpc_get_string( 'platform', '' );
-	$f_os					= gpc_get_string( 'os', '' );
-	$f_os_build				= gpc_get_string( 'os_build', '' );
-	$f_product_version		= gpc_get_string( 'product_version', '' );
-	$f_profile_id			= gpc_get_int( 'profile_id', 0 );
-	$f_handler_id			= gpc_get_int( 'handler_id', 0 );
-	$f_view_state			= gpc_get_int( 'view_state', config_get( 'default_bug_view_status' ) );
-
-	$f_category				= gpc_get_string( 'category', '' );
-	$f_reproducibility		= gpc_get_int( 'reproducibility' );
-	$f_severity				= gpc_get_int( 'severity' );
-	$f_priority				= gpc_get_int( 'priority', NORMAL );
-	$f_summary				= gpc_get_string( 'summary' );
-	$f_description			= gpc_get_string( 'description' );
-	$f_steps_to_reproduce	= gpc_get_string( 'steps_to_reproduce', '' );
-	$f_additional_info		= gpc_get_string( 'additional_info', '' );
+	$t_bug_data = new BugData;
+	$t_bug_data->build				= gpc_get_string( 'build', '' );
+	$t_bug_data->platform				= gpc_get_string( 'platform', '' );
+	$t_bug_data->os					= gpc_get_string( 'os', '' );
+	$t_bug_data->os_build				= gpc_get_string( 'os_build', '' );
+	$t_bug_data->product_version		= gpc_get_string( 'product_version', '' );
+	$t_bug_data->profile_id			= gpc_get_int( 'profile_id', 0 );
+	$t_bug_data->handler_id			= gpc_get_int( 'handler_id', 0 );
+	$t_bug_data->view_state			= gpc_get_int( 'view_state', config_get( 'default_bug_view_status' ) );
+
+	$t_bug_data->category				= gpc_get_string( 'category', '' );
+	$t_bug_data->reproducibility		= gpc_get_int( 'reproducibility' );
+	$t_bug_data->severity				= gpc_get_int( 'severity' );
+	$t_bug_data->priority				= gpc_get_int( 'priority', NORMAL );
+	$t_bug_data->summary				= gpc_get_string( 'summary' );
+	$t_bug_data->description			= gpc_get_string( 'description' );
+	$t_bug_data->steps_to_reproduce	= gpc_get_string( 'steps_to_reproduce', '' );
+	$t_bug_data->additional_info		= gpc_get_string( 'additional_info', '' );
 
 	$f_file					= gpc_get_file( 'file', null );
 	$f_report_stay			= gpc_get_bool( 'report_stay' );
-	$f_project_id			= gpc_get_int( 'project_id' );
+	$t_bug_data->project_id			= gpc_get_int( 'project_id' );
 
-	$t_reporter_id		= auth_get_current_user_id();
+	$t_bug_data->reporter_id		= auth_get_current_user_id();
 	$t_upload_method	= config_get( 'file_upload_method' );
 
-	$f_summary			= trim( $f_summary );
+	$t_bug_data->summary			= trim( $f_summary );
 
 	# If a file was uploaded, and we need to store it on disk, let's make
 	#  sure that the file path for this project exists
@@ -66,22 +67,24 @@
 
 
 	# if a profile was selected then let's use that information
-	if ( 0 != $f_profile_id ) {
+	if ( 0 != $t_bug_data->profile_id ) {
 		$row = user_get_profile_row( $t_reporter_id, $f_profile_id );
 
-		if ( is_blank( $f_platform ) ) {
-			$f_platform = $row['platform'];
+		if ( is_blank( $t_bug_data->platform ) ) {
+			$t_bug_data->platform = $row['platform'];
 		}
-		if ( is_blank( $f_os ) ) {
-			$f_os = $row['os'];
+		if ( is_blank( $t_bug_data->os ) ) {
+			$t_bug_data->os = $row['os'];
 		}
-		if ( is_blank( $f_os_build ) ) {
-			$f_os_build = $row['os_build'];
+		if ( is_blank( $t_bug_data->os_build ) ) {
+			$t_bug_data->os_build = $row['os_build'];
 		}
 	}
 
+	helper_call_custom_function( 'issue_create_validate', array( $t_bug_data ) );
+
 	# Validate the custom fields before adding the bug.
-	$t_related_custom_field_ids = custom_field_get_linked_ids( $f_project_id );
+	$t_related_custom_field_ids = custom_field_get_linked_ids( $t_bug_data->project_id );
 	foreach( $t_related_custom_field_ids as $t_id ) {
 		$t_def = custom_field_get_definition( $t_id );
 		if ( $t_def['require_report'] && ( gpc_get_custom_field( "custom_field_$t_id", $t_def['type'], '' ) == '' ) ) {
@@ -95,16 +98,7 @@
 	}
 
 	# Create the bug
-	$t_bug_id = bug_create( $f_project_id,
-					$t_reporter_id, $f_handler_id,
-					$f_priority,
-					$f_severity, $f_reproducibility,
-					$f_category,
-					$f_os, $f_os_build,
-					$f_platform, $f_product_version,
-					$f_build,
-					$f_profile_id, $f_summary, $f_view_state,
-					$f_description, $f_steps_to_reproduce, $f_additional_info );
+	$t_bug_id = bug_create( $t_bug_data );
 
 
 	# Handle the file upload
@@ -130,6 +124,7 @@
 	}
 
 	email_new_bug( $t_bug_id );
+	helper_call_custom_function( 'issue_create_notify', array( $t_bug_id ) );
 
 	html_page_top1();
 
Index: bug_update.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update.php,v
retrieving revision 1.66
diff -u -r1.66 bug_update.php
--- bug_update.php	4 Aug 2004 01:38:06 -0000	1.66
+++ bug_update.php	4 Aug 2004 14:22:46 -0000
@@ -63,6 +63,8 @@
 		$t_bug_data->status = config_get( 'bug_assigned_status' );
 	}
 
+  helper_call_custom_function( 'issue_update_validate', array( $f_bug_id, $t_bug_data, $f_bug_note_text ) );
+  
 	$t_custom_status_label = "update"; # default info to check
 	if ( $t_bug_data->status == config_get( 'bug_resolved_status_threshold' ) ) {
 		$t_custom_status_label = "resolved";
@@ -105,5 +107,7 @@
 	# Update the bug entry
 	bug_update( $f_bug_id, $t_bug_data, true );
 
+  helper_call_custom_function( 'issue_update_notify', array( $f_bug_id ) );
+  
 	print_successful_redirect_to_bug( $f_bug_id );
 ?>
Index: core/bug_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/bug_api.php,v
retrieving revision 1.76
diff -u -r1.76 bug_api.php
--- core/bug_api.php	1 Aug 2004 17:28:58 -0000	1.76
+++ core/bug_api.php	4 Aug 2004 14:22:46 -0000
@@ -294,36 +294,26 @@
 	# --------------------
 	# Create a new bug and return the bug id
 	#
-	# @@@ pass in a bug object instead of all these params
-	function bug_create( $p_project_id,
-				$p_reporter_id, $p_handler_id,
-				$p_priority,
-				$p_severity, $p_reproducibility,
-				$p_category,
-				$p_os, $p_os_build,
-				$p_platform, $p_version,
-				$p_build,
-				$p_profile_id, $p_summary, $p_view_state,
-				$p_description, $p_steps_to_reproduce, $p_additional_info ) {
-
-		$c_summary				= db_prepare_string( $p_summary );
-		$c_description			= db_prepare_string( $p_description );
-		$c_project_id			= db_prepare_int( $p_project_id );
-		$c_reporter_id			= db_prepare_int( $p_reporter_id );
-		$c_handler_id			= db_prepare_int( $p_handler_id );
-		$c_priority				= db_prepare_int( $p_priority );
-		$c_severity				= db_prepare_int( $p_severity );
-		$c_reproducibility		= db_prepare_int( $p_reproducibility );
-		$c_category				= db_prepare_string( $p_category );
-		$c_os					= db_prepare_string( $p_os );
-		$c_os_build				= db_prepare_string( $p_os_build );
-		$c_platform				= db_prepare_string( $p_platform );
-		$c_version				= db_prepare_string( $p_version );
-		$c_build				= db_prepare_string( $p_build );
-		$c_profile_id			= db_prepare_int( $p_profile_id );
-		$c_view_state			= db_prepare_int( $p_view_state );
-		$c_steps_to_reproduce	= db_prepare_string( $p_steps_to_reproduce );
-		$c_additional_info		= db_prepare_string( $p_additional_info );
+	function bug_create( $p_bug_data ) {
+
+		$c_summary				= db_prepare_string( $p_bug_data->summary );
+		$c_description			= db_prepare_string( $p_bug_data->description );
+		$c_project_id			= db_prepare_int( $p_bug_data->project_id );
+		$c_reporter_id			= db_prepare_int( $p_bug_data->reporter_id );
+		$c_handler_id			= db_prepare_int( $p_bug_data->handler_id );
+		$c_priority				= db_prepare_int( $p_bug_data->priority );
+		$c_severity				= db_prepare_int( $p_bug_data->severity );
+		$c_reproducibility		= db_prepare_int( $p_bug_data->reproducibility );
+		$c_category				= db_prepare_string( $p_bug_data->category );
+		$c_os					= db_prepare_string( $p_bug_data->os );
+		$c_os_build				= db_prepare_string( $p_bug_data->os_build );
+		$c_platform				= db_prepare_string( $p_bug_data->platform );
+		$c_version				= db_prepare_string( $p_bug_data->version );
+		$c_build				= db_prepare_string( $p_bug_data->build );
+		$c_profile_id			= db_prepare_int( $p_bug_data->profile_id );
+		$c_view_state			= db_prepare_int( $p_bug_data->view_state );
+		$c_steps_to_reproduce	= db_prepare_string( $p_bug_data->steps_to_reproduce );
+		$c_additional_info		= db_prepare_string( $p_bug_data->additional_info );
 		$c_sponsorship_total = 0;
 
 		# Summary cannot be blank
Index: core/constant_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/constant_inc.php,v
retrieving revision 1.27
diff -u -r1.27 constant_inc.php
--- core/constant_inc.php	1 Aug 2004 22:24:59 -0000	1.27
+++ core/constant_inc.php	4 Aug 2004 14:22:46 -0000
@@ -214,6 +214,7 @@
 	define( 'ERROR_BUG_DUPLICATE_SELF',				1101 );
 	define( 'ERROR_BUG_RESOLVED_ACTION_DENIED',			1102 );	// @@@ obsolete, remove after lang files are sync'd
 	define( 'ERROR_BUG_READ_ONLY_ACTION_DENIED',			1103 );
+	define( 'ERROR_BUG_VALIDATE_FAILURE',			1104 );
 
 	# ERROR_EMAIL_*
 	define( 'ERROR_EMAIL_INVALID',					1200 );
Index: core/custom_function_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/custom_function_api.php,v
retrieving revision 1.5
diff -u -r1.5 custom_function_api.php
--- core/custom_function_api.php	30 Jul 2004 12:46:09 -0000	1.5
+++ core/custom_function_api.php	4 Aug 2004 14:22:46 -0000
@@ -45,4 +45,64 @@
 			}
 		}
 	}
+	
+	# --------------------
+	# Hook to validate field settings before updating
+	#  verify that the proper fields are set before proceeding to change the status
+	#  returns true, and triggers error if there is something wrong
+	# p_issue_id is the issue number that can be used to get the existing state
+	# p_new_bug is an object (BugData) with the appropriate fields updated
+	function custom_function_default_issue_update_validate( $p_issue_id, $p_new_bug, $p_bug_note_text ) {
+
+		return true;
+	}
+	
+	# --------------------
+	# Hook to notify after a bug has been updated. 
+	#  returns true, and triggers error if there is something wrong
+	# p_issue_id is the issue number that can be used to get the existing state
+	function custom_function_default_issue_update_notify( $p_issue_id ) {
+
+		return true;
+	}
+	
+	# --------------------
+	# Hook to validate field settings before opening
+	#  verify that the proper fields are set before proceeding to change the status
+	#  returns true, and triggers error if there is something wrong
+	# p_new_bug is an object (BugData) with the appropriate fields updated
+	function custom_function_default_issue_create_validate( $p_new_bug ) {
+
+		return true;
+	}
+	
+	# --------------------
+	# Hook to notify after a bug has been opened. 
+	#  returns true, and triggers error if there is something wrong
+	# p_issue_id is the issue number that can be used to get the existing state
+	function custom_function_default_issue_create_notify( $p_issue_id ) {
+
+		return true;
+	}
+	
+	# --------------------
+	# Hook to validate field settings before deleting
+	#  verify that the proper fields are set before proceeding to change the status
+	#  returns true, and triggers error if there is something wrong
+	# p_issue_id is the issue number that can be used to get the existing state
+	function custom_function_default_issue_delete_validate( $p_issue_id ) {
+
+		return true;
+	}
+	
+	# --------------------
+	# Hook to notify after a bug has been deleted. 
+	#  returns true, and triggers error if there is something wrong
+	# p_issue_id is the issue number that can be used to get the existing state
+	function custom_function_default_issue_delete_notify( $p_issue_id ) {
+
+		return true;
+	}
+	
+
 ?>
\ No newline at end of file
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.196
diff -u -r1.196 strings_english.txt
--- lang/strings_english.txt	4 Aug 2004 01:38:07 -0000	1.196
+++ lang/strings_english.txt	4 Aug 2004 14:22:48 -0000
@@ -218,6 +218,7 @@
 $MANTIS_ERROR[ERROR_SPONSORSHIP_SPONSOR_NO_EMAIL] = 'Sponsor has not provided an email address. Please update your profile.';
 $MANTIS_ERROR[ERROR_CONFIG_OPT_INVALID] = 'Configuration option \'%s\' has invalid value \'%s\'';
 $MANTIS_ERROR[ERROR_BUG_READ_ONLY_ACTION_DENIED] = 'The action cannot be performed because issue \'%d\' is read-only';
+$MANTIS_ERROR[ERROR_BUG_VALIDATE_FAILURE] = 'Validation failed: \'%s\'';
 $MANTIS_ERROR[ERROR_RELATIONSHIP_ALREADY_EXISTS] = "There is already a relationship between these two issues.";
 $MANTIS_ERROR[ERROR_RELATIONSHIP_NOT_FOUND] = "Relationship not found.";
 $MANTIS_ERROR[ERROR_RELATIONSHIP_ACCESS_LEVEL_TO_DEST_BUG_TOO_LOW] = "Access denied: The issue %d requires higher access level.";
resolve_hook.diff (13,213 bytes)   
resolve_hook.tar.gz (26,001 bytes)
custom_function_manual.txt (3,297 bytes)   
Custom Functions

Custom functions are used to extend the functionaloty of Mantis by integrating user written 
functions into the processing at strategic places. This allows the system administrator to change 
the functionality without re-writing parts of the internals of the code.

User versions of these functions are placed in a file called "custom_functions_inc.php" in the root 
directory of Mantis. This is the same place that the "config_inc.php" file modifying Mantis
defaults is placed. In normal processing, Mantis will look for override functions and execute them
instead of the provided default functions.

Custom functions have names like "custom_function_override_descriptive_name" where "descriptive name"
described the particular function. The specific functions are described below. The simplest way to 
create a custom function is to copy the default function, named "custom_function_default_descriptive_name"
from the "core/custom_function_api.php" file to your override file ("custom_functions_inc.php"), and
rename it. The specific functionality you need can then be coded into the override function. 



Defined Functions

custom_function_default_changelog_include_issue( $p_issue_id )
  returns true or false if the issue if to be included in the Changelog

custom_function_default_changelog_print_issue( $p_issue_id )
  returns a formatted string to be included for the issue in the Changelog

custom_function_default_checkin( $p_issue_id, $p_comment, $p_file, $p_new_version )
  registers a checkin in source control in Mantis 

custom_function_default_issue_update_validate( $p_issue_id, $p_new_bug, $p_bug_note_text )
	validate bug field settings before an update occurs. It returns true or fails with an error. 

custom_function_default_issue_update_notify( $p_issue_id )
	notify after a bug has been updated

custom_function_default_issue_create_validate( $p_new_bug )
	validate bug field settings before an issue is created. It returns true or fails with an error. 
	
custom_function_default_issue_create_notify( $p_issue_id )
	notify after a bug has been opened

custom_function_default_issue_delete_validate( $p_issue_id )
	validate bug field settings before an issue can be deleted. It returns true or fails with an error. 

custom_function_default_issue_delete_notify( $p_issue_id ) {
		notify after a bug has been deleted


Example Function

  The following function is used to validate an issue before it is resolved.

<?php

	# --------------------
	# Hook to validate Validate field settings before resolving
	#  verify that the resolution is not set to OPEN
	#  verify that the fixed in version is set (if versions of the product exist)
	function custom_function_override_issue_update_validate( $p_issue_id, $p_bug_data, $p_bugnote_text ) {
		if ( $p_bug_data->status == RESOLVED ) {
			if ( $p_bug_data->resolution == OPEN ) {
				error_parameters( 'Resolution cannot be open to resolve' );
				trigger_error( ERROR_BUG_VALIDATE_FAILURE, ERROR );
			}
			
			$t_version_count = count( version_get_all_rows( $t_bug_data->project_id ) ); 
			if ( ( $t_version_count > 0 ) && ( $t_bug_data->fixed_in_version == '' ) ) {
				error_parameters( 'fixed in version must be set to resolve' );
				trigger_error( ERROR_BUG_VALIDATE_FAILURE, ERROR );
			}
		}
	}
?>
 
custom_function_manual.txt (3,297 bytes)   

Relationships

child of 0003987 closedvboctor Mantis 0.19.0 Release 

Activities

vboctor

vboctor

2004-07-19 21:35

manager   ~0006165

At the moment, I some time leave the fixed_in_version field empty when resolving an issue in order to stop it from being included in the Changelog. Till we have another solution, I would like to keep the fixed_in_version as an option field.

thraxisp

thraxisp

2004-07-20 14:14

reporter   ~0006177

I was thinking of adding an option on a per project bases to enforce this. The default would be off. Further, if there were no versions defined, it wouldn't be mandatory.

The resolution seems to default to fixed, so this is okay.

vboctor

vboctor

2004-07-31 08:56

manager   ~0006494

Per project settings will be supported in the next major release (hopefully). However, I think such feature can be achieved by validation of the updated issue via a custom function that can be overriden for a certain installation. Also this method can get the project id from the issue id, then use this to determine what the validation code should do.

As for the resolution field, it always has a value, a new issue will have resolution "open". Using the custom function, we can also add validation for resolution.

thraxisp

thraxisp

2004-08-02 16:48

reporter   ~0006563

Diffs and affected modules attached.

I implemented hooks through custom functions before and after issue creation, update, and delete.

I'll add some documentation on how to implement checks like this later.

thraxisp

thraxisp

2004-08-04 09:49

reporter   ~0006630

The attached files have been updated to correspond with the latest CVS HEAD (after the changes introduced by 0003772).

vboctor

vboctor

2004-08-04 09:55

manager   ~0006631

thraxisp, I applied your patch with the following modifications:

  • Didn't apply change to constant_inc.php since it is not relevant anymore.
  • Didn't apply change to lang/strings_english.txt since it is not relevant anymore.
  • You forgot to attach bug_delete.php, so I modified it myself.
  • bug_resolve.php/bug_close.php were ignored, since they don't exist in CVS anymore.
  • Change the issue_delete_notify to take issue data, since by then the issue is deleted, so issue_id is not of much use.
  • Updated documentation for all new custom methods.
  • Fixed a bug in bug_create() where $f_summary was still used.
  • Fixed some indentation issues where spaces were used rather than tabs.