View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004138 | mantisbt | bugtracker | public | 2004-07-19 21:28 | 2004-08-29 02:07 |
Reporter | thraxisp | Assigned To | thraxisp | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Product Version | 0.19.0a2 | ||||
Fixed in Version | 0.19.0rc1 | ||||
Summary | 0004138: Add validation / notifications hooks for issue create/update/delete | ||||
Description | The original subject was: Filling in the fixed_in_version and resolution should be required to resolve an issue. This could be driven by an option. | ||||
Tags | No 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."; 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 ); } } } ?> | ||||
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. |
|
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. |
|
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. |
|
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. |
|
The attached files have been updated to correspond with the latest CVS HEAD (after the changes introduced by 0003772). |
|
thraxisp, I applied your patch with the following modifications:
|
|