Skip to content

Commit

Permalink
Issue #12253: Implement management page to view workflow graph
Browse files Browse the repository at this point in the history
Bernard de Rubinat contributed a patch to implement a workflow graph
using the existing GraphViz API for rendering. This patch will add a new
page the Manage => Configuration menu to show a graph of the workflow
(status transitions) for the currently selected project.

The proposed functionality was cleaned up and extended in the following
ways:

1) Added workflow_api for functions that are used for working with
workflows. This API is already used by two MantisBT pages.

2) Place the workflow graph on a separate page in the management
console. There wasn't enough space within the
manage_config_workflow_page.php page.

3) Use the 'dot' tool for generating the graph rather than 'neato'. This
new format is more suitable for displaying workflows.

4) Refactored the code used to print the manage configuration menu. This
newer format would be better used as a generic print_menu(...) function
in the future (serving multiple different menus).

Contributed-by: Bernard de Rubinat <bernard.derubinat@gmail.com>
Contributed-by: David Hicks <hickseydr@optusnet.com.au>
  • Loading branch information
davidhicks committed Aug 14, 2010
1 parent 6d6e255 commit 596097f
Show file tree
Hide file tree
Showing 6 changed files with 330 additions and 117 deletions.
101 changes: 50 additions & 51 deletions core/html_api.php
Expand Up @@ -1087,69 +1087,68 @@ function print_manage_menu( $p_page = '' ) {
* @return null
*/
function print_manage_config_menu( $p_page = '' ) {
$t_configuration_report = 'adm_config_report.php';
$t_permissions_summary_report = 'adm_permissions_report.php';
$t_manage_work_threshold = 'manage_config_work_threshold_page.php';
$t_manage_email = 'manage_config_email_page.php';
$t_manage_workflow = 'manage_config_workflow_page.php';
$t_manage_columns = 'manage_config_columns_page.php';
if ( !access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) {
return;
}

switch( $p_page ) {
case $t_configuration_report:
$t_configuration_report = '';
break;
case $t_permissions_summary_report:
$t_permissions_summary_report = '';
break;
case $t_manage_work_threshold:
$t_manage_work_threshold = '';
break;
case $t_manage_email:
$t_manage_email = '';
break;
case $t_manage_workflow:
$t_manage_workflow = '';
break;
case $t_manage_columns:
$t_manage_columns = '';
break;
$t_pages = array();

if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) {
$t_pages['adm_config_report.php'] = array( 'url' => 'adm_config_report.php',
'label' => 'configuration_report' );
}

if ( access_has_project_level( config_get( 'manage_configuration_threshold' ) ) ) {
echo '<div id="manage-config-menu">';
$t_pages['adm_permissions_report.php'] = array( 'url' => 'adm_permissions_report.php',
'label' => 'permissions_summary_report' );

if ( access_has_global_level( config_get( 'view_configuration_threshold' ) ) ) {
print_bracket_link( helper_mantis_url( $t_configuration_report ), lang_get_defaulted( 'configuration_report' ) );
}
$t_pages['manage_config_work_threshold_page.php'] = array( 'url' => 'manage_config_work_threshold_page.php',
'label' => 'manage_threshold_config' );

print_bracket_link( helper_mantis_url( $t_permissions_summary_report ), lang_get( 'permissions_summary_report' ) );
print_bracket_link( helper_mantis_url( $t_manage_work_threshold ), lang_get( 'manage_threshold_config' ) );
print_bracket_link( helper_mantis_url( $t_manage_workflow ), lang_get( 'manage_workflow_config' ) );
print_bracket_link( helper_mantis_url( $t_manage_email ), lang_get( 'manage_email_config' ) );
print_bracket_link( $t_manage_columns, lang_get( 'manage_columns_config' ) );
$t_pages['manage_config_workflow_page.php'] = array( 'url' => 'manage_config_workflow_page.php',
'label' => 'manage_workflow_config' );

# Plugin / Event added options
$t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE_CONFIG' );
$t_menu_options = array();
foreach( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
foreach( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
if( is_array( $t_callback_menu_options ) ) {
$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
} else {
if ( !is_null( $t_callback_menu_options ) ) {
$t_menu_options[] = $t_callback_menu_options;
}
if ( config_get( 'relationship_graph_enable' ) ) {
$t_pages['manage_config_workflow_graph_page.php'] = array( 'url' => 'manage_config_workflow_graph_page.php',
'label' => 'manage_workflow_graph' );
}

$t_pages['manage_config_email_page.php'] = array( 'url' => 'manage_config_email_page.php',
'label' => 'manage_email_config' );

$t_pages['manage_config_columns_page.php'] = array( 'url' => 'manage_config_columns_page.php',
'label' => 'manage_columns_config' );

# Remove the link from the current page
if ( isset( $t_pages[$p_page] ) ) {
$t_pages[$p_page]['url'] = '';
}

echo '<br /><div id="manage-config-menu">';

# Plugin / Event added options
$t_event_menu_options = event_signal( 'EVENT_MENU_MANAGE_CONFIG' );
$t_menu_options = array();
foreach ( $t_event_menu_options as $t_plugin => $t_plugin_menu_options ) {
foreach ( $t_plugin_menu_options as $t_callback => $t_callback_menu_options ) {
if ( is_array( $t_callback_menu_options ) ) {
$t_menu_options = array_merge( $t_menu_options, $t_callback_menu_options );
} else {
if ( !is_null( $t_callback_menu_options ) ) {
$t_menu_options[] = $t_callback_menu_options;
}
}
}
}

// Plugins menu items
foreach( $t_menu_options as $t_menu_item ) {
print_bracket_link_prepared( $t_menu_item );
}
foreach ( $t_pages as $t_page ) {
print_bracket_link( helper_mantis_url( $t_page['url'] ), lang_get( $t_page['label'] ) );
}

echo '</div>';
foreach ( $t_menu_options as $t_menu_item ) {
print_bracket_link_prepared( $t_menu_item );
}

echo '</div>';
}

/**
Expand Down
113 changes: 113 additions & 0 deletions core/workflow_api.php
@@ -0,0 +1,113 @@
<?php
# MantisBT - A PHP based bugtracking system

# MantisBT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MantisBT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MantisBT. If not, see <http://www.gnu.org/licenses/>.

/**
* Workflow API
*
* @package CoreAPI
* @subpackage WorkflowAPI
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2010 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
*
* @uses config_api.php
*/

require_api( 'config_api.php' );

/**
* Determine if there is a transition possible between two workflow states. The
* direction of the transition is factored into this check.
* @param int $p_from_status_id Source status ID
* @param int $p_to_status_id Destination status ID
* @return bool Whether a transition exists in the specified direction
*/
function workflow_transition_edge_exists( $p_from_status_id, $p_to_status_id ) {
if ( $p_from_status_id == $p_to_status_id ) {
return false;
}

$t_project_workflow = workflow_parse( config_get( 'status_enum_workflow' ) );

return isset( $t_project_workflow['exit'][$p_from_status_id][$p_to_status_id] );
}

/**
* Parse a workflow into a graph-like array of workflow transitions.
* @param array The workflow enumeration to parse.
* @return array The parsed workflow graph.
*/
function workflow_parse( $p_enum_workflow ) {
$t_status_arr = MantisEnum::getAssocArrayIndexedByValues( config_get( 'status_enum_string' ) );
if ( count( $p_enum_workflow ) == 0 ) {
# workflow is not set, default it to all transitions
foreach ( $t_status_arr as $t_status => $t_label ) {
$t_temp_workflow = array();
foreach ( $t_status_arr as $t_next => $t_next_label ) {
if ( $t_status != $t_next ) {
$t_temp_workflow[] = $t_next . ':' . $t_next_label;
}
}
$p_enum_workflow[$t_status] = implode( ',', $t_temp_workflow );
}
}

$t_entry = array();
$t_exit = array();

# prepopulate new bug state (bugs go from nothing to here)
$t_submit_status_array = config_get( 'bug_submit_status' );
$t_new_label = MantisEnum::getLabel( lang_get( 'status_enum_string' ), config_get( 'bug_submit_status' ) );
if ( is_array( $t_submit_status_array ) ) {
# @@@ (thraxisp) this is not implemented in bug_api.php
foreach ($t_submit_status_array as $t_access => $t_status ) {
$t_entry[$t_status][0] = $t_new_label;
$t_exit[0][$t_status] = $t_new_label;
}
} else {
$t_status = $t_submit_status_array;
$t_entry[$t_status][0] = $t_new_label;
$t_exit[0][$t_status] = $t_new_label;
}

# add user defined arcs and implicit reopen arcs
$t_reopen = config_get( 'bug_reopen_status' );
$t_reopen_label = MantisEnum::getLabel( lang_get( 'resolution_enum_string' ), config_get( 'bug_reopen_resolution' ) );
$t_resolved_status = config_get( 'bug_resolved_status_threshold' );
$t_default = array();
foreach ( $t_status_arr as $t_status => $t_status_label ) {
if ( isset( $p_enum_workflow[$t_status] ) ) {
$t_next_arr = MantisEnum::getAssocArrayIndexedByValues( $p_enum_workflow[$t_status] );
foreach ( $t_next_arr as $t_next => $t_next_label) {
if ( !isset( $t_default[$t_status] ) ) {
$t_default[$t_status] = $t_next;
}
$t_exit[$t_status][$t_next] = '';
$t_entry[$t_next][$t_status] = '';
}
} else {
$t_exit[$t_status] = array();
}
if ( $t_status >= $t_resolved_status ) {
$t_exit[$t_status][$t_reopen] = $t_reopen_label;
$t_entry[$t_reopen][$t_status] = $t_reopen_label;
}
if ( !isset( $t_entry[$t_status] ) ) {
$t_entry[$t_status] = array();
}
}
return array( 'entry' => $t_entry, 'exit' => $t_exit, 'default' => $t_default );
}
1 change: 1 addition & 0 deletions lang/strings_english.txt
Expand Up @@ -791,6 +791,7 @@ $s_manage_config_link = 'Manage Configuration';
$s_manage_threshold_config = 'Workflow Thresholds';
$s_manage_email_config = 'E-mail Notifications';
$s_manage_workflow_config = 'Workflow Transitions';
$s_manage_workflow_graph = 'Workflow Graph';
$s_manage_tags_link = 'Manage Tags';
$s_create_new_account_link = 'Create New Account';
$s_projects_link = 'Projects';
Expand Down
77 changes: 77 additions & 0 deletions manage_config_workflow_graph_page.php
@@ -0,0 +1,77 @@
<?php
# MantisBT - A PHP based bugtracking system

# MantisBT is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# MantisBT is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with MantisBT. If not, see <http://www.gnu.org/licenses/>.

/**
* @package MantisBT
* @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
* @copyright Copyright (C) 2002 - 2010 MantisBT Team - mantisbt-dev@lists.sourceforge.net
* @link http://www.mantisbt.org
*
* @uses core.php
* @uses authentication_api.php
* @uses config_api.php
* @uses constant_inc.php
* @uses current_user_api.php
* @uses form_api.php
* @uses helper_api.php
* @uses html_api.php
* @uses lang_api.php
* @uses print_api.php
* @uses project_api.php
* @uses string_api.php
* @uses workflow_api.php
*/

require_once( 'core.php' );
require_api( 'access_api.php' );
require_api( 'authentication_api.php' );
require_api( 'config_api.php' );
require_api( 'constant_inc.php' );
require_api( 'helper_api.php' );
require_api( 'html_api.php' );
require_api( 'lang_api.php' );
require_api( 'print_api.php' );
require_api( 'project_api.php' );
require_api( 'string_api.php' );

auth_reauthenticate();

if ( !config_get( 'relationship_graph_enable' ) ) {
access_denied();
}

html_page_top( lang_get( 'manage_workflow_graph' ) );

print_manage_menu( 'adm_permissions_report.php' );
print_manage_config_menu( 'manage_config_workflow_graph_page.php' );

$t_project = helper_get_current_project();

if ( $t_project == ALL_PROJECTS ) {
$t_project_title = lang_get( 'config_all_projects' );
} else {
$t_project_title = sprintf( lang_get( 'config_project' ) , string_display( project_get_name( $t_project ) ) );
}
?>
<br />
<br />
<div class="center">
<p class="bold"><?php echo $t_project_title ?></p>
<br />
<img src="workflow_graph_img.php" />
</div>
<?php
html_page_bottom();

0 comments on commit 596097f

Please sign in to comment.