View Issue Details

IDProjectCategoryView StatusLast Update
0003984mantisbtfeaturepublic2004-07-18 11:31
Reporterchristianh Assigned Tothraxisp  
PrioritynormalSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Product Version0.19.0a1 
Fixed in Version0.19.0a2 
Summary0003984: Support definining and enforcing custom workflow
Description

Basically give the ability to force a particular order of states.

Additional Information

From Victor Boctor:
Currently there is no enforcing for the workflow, so there is no way to force them to resolve a bug before closing it. However, I have been thinking about this as a needed feature.

My vision is that a user should be able to use Mantis to define his own states/workflow and enforce it. The challenge is to do that for a user defined workflow rather than a hard-coded one.

Apparently Soren Thomassen (sth_ch at hotmail dot com) submitted a patch for this, but I can't seem to find it in the archives.

TagsNo tags attached.
Attached Files
workflow.diff (9,688 bytes)   
Index: bug_update_advanced_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_advanced_page.php,v
retrieving revision 1.69
diff -c -r1.69 bug_update_advanced_page.php
*** bug_update_advanced_page.php	26 Jun 2004 14:05:42 -0000	1.69
--- bug_update_advanced_page.php	3 Jul 2004 21:58:01 -0000
***************
*** 221,227 ****
  	</td>
  	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
  		<select name="status">
! 			<?php print_enum_string_option_list( 'status', $t_bug->status ) ?>
  		</select>
  	</td>
  
--- 221,227 ----
  	</td>
  	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
  		<select name="status">
! 			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
  		</select>
  	</td>
  
Index: bug_update_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_page.php,v
retrieving revision 1.70
diff -c -r1.70 bug_update_page.php
*** bug_update_page.php	26 Jun 2004 14:05:42 -0000	1.70
--- bug_update_page.php	3 Jul 2004 21:58:02 -0000
***************
*** 153,159 ****
  <?php
  		if ( access_has_project_level( config_get( 'change_view_status_threshold' ) ) ) { ?>
  			<select name="view_state">
! 				<?php print_enum_string_option_list( 'view_state', $t_bug->view_state) ?>
  			</select>
  <?php
  		} else {
--- 153,159 ----
  <?php
  		if ( access_has_project_level( config_get( 'change_view_status_threshold' ) ) ) { ?>
  			<select name="view_state">
! 						<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>	
  			</select>
  <?php
  		} else {
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.170
diff -c -r1.170 config_defaults_inc.php
*** config_defaults_inc.php	28 Jun 2004 10:13:22 -0000	1.170
--- config_defaults_inc.php	3 Jul 2004 21:58:02 -0000
***************
*** 618,623 ****
--- 618,636 ----
  	# the bug is in progress, rather than just put in a person's queue.
  	$g_auto_set_status_to_assigned	= ON;
  
+   # g_status_enum_states defines the workflow, and reflects a simple 
+   #  2-dimensional matrix. For each existing status, you define which
+   #  statuses you can go to from that status, e.g. from NEW_ you might list status 
+   #  '10:new,20:feedback,30:acknowledged' but not higher ones.
+   # The following exexample can be transferred to config_inc.php
+ 	# $g_status_enum_states[NEW_]='10:new,20:feedback,30:acknowledged';
+ 	# $g_status_enum_states[FEEDBACK] ='10:new,20:feedback,30:acknowledged';
+ 	# $g_status_enum_states[ACKNOWLEDGED] ='30:acknowledged,40:confirmed,50:assigned';
+ 	# $g_status_enum_states[CONFIRMED] ='40:confirmed,50:assigned';
+ 	# $g_status_enum_states[ASSIGNED] ='50:assigned,80:resolved,90:closed';
+ 	# $g_status_enum_states[RESOLVED] ='50:assigned,80:resolved,90:closed';
+ 	# $g_status_enum_states[CLOSED] ='40:confirmed';
+ 
  	############################
  	# Bug Attachments Settings
  	############################
Index: core/bug_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/bug_api.php,v
retrieving revision 1.65
diff -c -r1.65 bug_api.php
*** core/bug_api.php	29 Jun 2004 07:05:59 -0000	1.65
--- core/bug_api.php	3 Jul 2004 21:58:03 -0000
***************
*** 256,262 ****
--- 256,287 ----
  
  		return true;
  	}
+ 	# --------------------
+ 	# Validate workflow state to see if bug can be moved to requested state
+ 	function bug_check_workflow( $p_bug_status, $p_wanted_status ) {
+ 
+ 		global $g_status_enum_states;
  
+ 		if (count($g_status_enum_states) < 1) {
+ 			# workflow not defined, use default enum
+ 			return TRUE;
+ 		} else {
+ 			# workflow defined - find allowed states
+ 			$allowed_states = $g_status_enum_states[$p_bug_status];
+ 			$t_arr  = explode_enum_string( $allowed_states );
+ 			$enum_count = count( $t_arr );
+ 
+ 			for ($i=0;$i<$enum_count;$i++) {
+ 				# check if wanted status is allowed
+ 				$t_elem  = explode_enum_arr( $t_arr[$i] );
+ 				if ($p_wanted_status == $t_elem[0]) {
+ 					return TRUE;
+ 				}
+ 			} # end for
+ 		}
+ 		return FALSE;
+ 	}
+ 	
  	#===================================
  	# Creation / Deletion / Updating
  	#===================================
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.105
diff -c -r1.105 html_api.php
*** core/html_api.php	29 Jun 2004 08:23:05 -0000	1.105
--- core/html_api.php	3 Jul 2004 21:58:03 -0000
***************
*** 659,664 ****
--- 659,672 ----
  	# --------------------
  	# Print Assign To: combo box of possible handlers
  	function html_button_bug_assign_to( $p_bug_id ) {
+ 		#make sure status is allowed of assign would cause auto-set-status
+ 		$t_status = bug_get_field( $p_bug_id, 'status' );     # workflow implementation
+ 
+ 		if ( ON == config_get( 'auto_set_status_to_assigned' ) &&
+ 			!bug_check_workflow($t_status, config_get( 'bug_assigned_status' ))) {  # workflow
+ 			return;
+ 		}
+ 
  		# make sure current user has access to modify bugs.
  		if ( !access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) {
  			return;
***************
*** 736,742 ****
  	function html_button_bug_resolve( $p_bug_id ) {
  		$t_status = bug_get_field( $p_bug_id, 'status' );
  
! 		if ( ( $t_status < config_get( 'bug_resolved_status_threshold' ) ) && access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id ) ) {
  			html_button( 'bug_resolve_page.php',
  						 lang_get( 'resolve_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
--- 744,752 ----
  	function html_button_bug_resolve( $p_bug_id ) {
  		$t_status = bug_get_field( $p_bug_id, 'status' );
  
! 		if ( ( $t_status < config_get( 'bug_resolved_status_threshold' ) ) && 
! 				access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id ) &&
! 				bug_check_workflow($t_status, RESOLVED) ) {
  			html_button( 'bug_resolve_page.php',
  						 lang_get( 'resolve_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
***************
*** 758,766 ****
  	# --------------------
  	# Print a button to reopen the given bug
  	function html_button_bug_reopen( $p_bug_id ) {
! 		if ( access_has_bug_level( config_get( 'reopen_bug_threshold' ), $p_bug_id ) ||
! 			 ( bug_get_field( $p_bug_id, 'reporter_id' ) == auth_get_current_user_id() &&
! 			 ( ON == config_get( 'allow_reporter_reopen' ) ) ) ) {
  			html_button( 'bug_reopen_page.php',
  						 lang_get( 'reopen_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
--- 768,779 ----
  	# --------------------
  	# Print a button to reopen the given bug
  	function html_button_bug_reopen( $p_bug_id ) {
! 		if ( bug_check_workflow( $t_status, config_get( 'bug_reopen_status' ) ) &&
! 				( access_has_bug_level( config_get( 'reopen_bug_threshold' ), $p_bug_id ) ||
! 			  ( ( bug_get_field( $p_bug_id, 'reporter_id' ) == auth_get_current_user_id() ) &&
! 			 		( ON == config_get( 'allow_reporter_reopen' ) ) 
! 			 	) )
! 			 ) {
  			html_button( 'bug_reopen_page.php',
  						 lang_get( 'reopen_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
***************
*** 772,778 ****
  	function html_button_bug_close( $p_bug_id ) {
  		$t_status = bug_get_field( $p_bug_id, 'status' );
  
! 		if ( access_can_close_bug ( $p_bug_id ) && ( $t_status < CLOSED ) ) {
  			html_button( 'bug_close_page.php',
  						 lang_get( 'close_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
--- 785,793 ----
  	function html_button_bug_close( $p_bug_id ) {
  		$t_status = bug_get_field( $p_bug_id, 'status' );
  
! 		if ( access_can_close_bug ( $p_bug_id ) && 
! 				( $t_status < CLOSED ) && 
! 				bug_check_workflow($t_status, CLOSED) ) {
  			html_button( 'bug_close_page.php',
  						 lang_get( 'close_bug_button' ),
  						 array( 'bug_id' => $p_bug_id ) );
Index: core/print_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/print_api.php,v
retrieving revision 1.88
diff -c -r1.88 print_api.php
*** core/print_api.php	26 Jun 2004 12:30:38 -0000	1.88
--- core/print_api.php	3 Jul 2004 21:58:04 -0000
***************
*** 586,591 ****
--- 586,618 ----
  		} # end for
  	}
  	# --------------------
+ 	# Select the proper enum values for status based on workflow
+   # or the input parameter if workflows are not used
+ 	# we use variable variables in order to achieve this
+ 	function print_enum_string_option_list_workflow( $p_enum_name, $p_val=0 ) {
+ 		$g_var = 'g_'.$p_enum_name.'_enum_string';
+ 		global $$g_var;
+ 		global $g_status_enum_states;
+ 
+ 		if (count($g_status_enum_states) < 1) {
+ 			# workflow not defined, use default enum
+ 			$t_arr  = explode_enum_string( $$g_var );
+ 		} else {
+ 			# workflow defined - find allowed states
+ 			$allowed_states = $g_status_enum_states[$p_val];
+ 			$t_arr  = explode_enum_string( $allowed_states );
+ 		}
+ 		$enum_count = count( $t_arr );
+ 
+ 		for ($i=0;$i<$enum_count;$i++) {
+ 			$t_elem  = explode_enum_arr( $t_arr[$i] );
+ 			$t_elem2 = get_enum_element( $p_enum_name, $t_elem[0] );
+ 			PRINT "<option value=\"$t_elem[0]\"";
+ 			check_selected( $t_elem[0], $p_val );
+ 			PRINT ">$t_elem2</option>";
+ 		} # end for
+ 	}
+ 	# --------------------
  	# prints the list of a project's users
  	# if no project is specified uses the current project
  	function print_project_user_option_list( $p_project_id=null ) {
workflow.diff (9,688 bytes)   
2workflow.tar.gz (75,837 bytes)
workflow_vboctor.zip (47,137 bytes)

Relationships

has duplicate 0003986 closedmasc Force user to resolve/close bug using the appropriate form 
related to 0004270 closedthraxisp Change status in mass treatment ignore defined workflow rules 

Activities

thraxisp

thraxisp

2004-07-03 17:09

reporter   ~0005878

I applied these changes against the current CVS HEAD. The diff file is attached (workflow.diff). I also attached copies of the affected files. The default is off for the changes.

Information on applying the workflow is in config_defaults_inc.php.

thraxisp

thraxisp

2004-07-06 07:41

reporter   ~0005886

Apparently, the original workflow.tar.gz file is empty. I've uploaded a new version (2workflow.tar.gz).

masc

masc

2004-07-13 03:14

reporter   ~0006009

Is it foreseen to add this very nice enhancement to the 0.19.0 version?
I guess it's really interesting and has not a great impact on the current implementation.

vboctor

vboctor

2004-07-13 07:17

manager   ~0006011

I reviewed your patch, and applied it including my own modifications. Please see my patch to see the actual applied code. I consider this the start of workflow support in Mantis. However, more work is needed in order to make this a robust feature. One thing I can think of at the moment is enforncing of workflow rules in group actions.

Once you implement this feature, please post the patch here and I will apply it.

thraxisp

thraxisp

2004-07-13 10:12

reporter   ~0006022

Another issue I ran into was adding another state to the flow. We need a generic way of creating new panels for state transitions.

We may also want to specify any fields that MUST be filled in to advance to a new state. Someone added this for custom fields.

vboctor

vboctor

2004-07-13 16:55

manager   ~0006026

My original thought about this was to you custom functions. A custom function is to take an issue before change and after change, and approve/disapprove the change. The default implementation will accept everything, but the user may override this to only accept according to a complex workflow criteria. For more details about custom functions see core/custom_function_api.php.

vboctor

vboctor

2004-07-18 10:20

manager   ~0006117

I will resolve this issue now so that it appears in Changelog for 0.19.0a2. Any related issues should be reported against the new release.