diff --git a/core/classes/MantisColumn.class.php b/core/classes/MantisColumn.class.php new file mode 100644 index 0000000000..0bb0cd1414 --- /dev/null +++ b/core/classes/MantisColumn.class.php @@ -0,0 +1,44 @@ +. + +/** + * Base class that implements basic column functionality + * and integration with MantisBT. + * @package MantisBT + * @subpackage classes + */ +abstract class MantisColumn { + + /** + * Column title, as displayed to the user. + */ + public $title = null; + + /** + * Column name, as selected in the manage columns interfaces. + */ + public $column = null; + + /** + * Function to display column data for a given bug row. + * @param object Bug object + * @param int Column display target + */ + abstract function display( $p_bug, $p_columns_target ); +} + diff --git a/core/columns_api.php b/core/columns_api.php index cf9694f154..e7babfaf32 100644 --- a/core/columns_api.php +++ b/core/columns_api.php @@ -41,6 +41,36 @@ function columns_get_standard() { return array_keys($t_columns); } +/** + * Allow plugins to define a set of class-based columns, and register/load + * them here to be used by columns_api. + * @return array Mapping of column name to column object + */ +function columns_get_plugin_columns() { + static $s_column_array = null; + + if ( is_null( $s_column_array ) ) { + $s_column_array = array(); + + $t_all_plugin_columns = event_signal( 'EVENT_FILTER_COLUMNS' ); + foreach( $t_all_plugin_columns as $t_plugin => $t_plugin_columns ) { + foreach( $t_plugin_columns as $t_callback => $t_plugin_column_array ) { + if ( is_array( $t_plugin_column_array ) ) { + foreach( $t_plugin_column_array as $t_column_class ) { + if ( class_exists( $t_column_class ) && is_subclass_of( $t_column_class, 'MantisColumn' ) ) { + $t_column_object = new $t_column_class(); + $t_column_name = utf8_strtolower( $t_plugin . '_' . $t_column_object->column ); + $s_column_array[ $t_column_name ] = $t_column_object; + } + } + } + } + } + } + + return $s_column_array; +} + /** * Get all accessible columns for the current project / current user.. * @param int $p_project_id project id @@ -50,6 +80,9 @@ function columns_get_standard() { function columns_get_all( $p_project_id = null ) { $t_columns = columns_get_standard(); + # add plugin columns + $t_columns = array_merge( $t_columns, array_keys( columns_get_plugin_columns() ) ); + # Add project custom fields to the array. Only add the ones for which the current user has at least read access. if( $p_project_id === null ) { $t_project_id = helper_get_current_project(); @@ -67,8 +100,6 @@ function columns_get_all( $p_project_id = null ) { $t_columns[] = 'custom_' . $t_def['name']; } - # foreach - return $t_columns; } @@ -148,6 +179,12 @@ function column_get_title( $p_column ) { return $t_custom_field; } + $t_plugin_columns = columns_get_plugin_columns(); + if ( isset( $t_plugin_columns[ $p_column ] ) ) { + $t_column_object = $t_plugin_columns[ $p_column ]; + return $t_column_object->title; + } + switch( $p_column ) { case 'attachment': return lang_get( 'attachments' ); @@ -719,6 +756,35 @@ function print_column_selection( $p_bug, $p_columns_target = COLUMNS_TARGET_VIEW echo ''; } +/** + * Print column title for a specific custom column. + * @param object Column object + * @param string sort + * @param string direction + * @param int $p_columns_target: see COLUMNS_TARGET_* in constant_inc.php + * @access public + */ +function print_column_title_plugin( $p_column_object, $p_sort, $p_dir, $p_columns_target=COLUMNS_TARGET_VIEW_PAGE ) { + echo '', string_display_line( $p_column_object->title ), ''; +} + +/** + * Print custom column content for a specific bug. + * @param object Column object + * @param array $p_row bug row + * @param int $p_columns_target: see COLUMNS_TARGET_* in constant_inc.php + * @access public + */ +function print_column_plugin( $p_column_object, $p_bug, $p_columns_target = COLUMNS_TARGET_VIEW_PAGE ) { + if ( $p_columns_target != COLUMNS_TARGET_CSV_PAGE ) { + echo ''; + $p_column_object->display( $p_bug, $p_columns_target ); + echo ''; + } else { + $p_column_object->display( $p_bug, $p_columns_target ); + } +} + /** * * @param array $p_row bug row diff --git a/core/custom_function_api.php b/core/custom_function_api.php index 3892cbfa91..bd20401868 100644 --- a/core/custom_function_api.php +++ b/core/custom_function_api.php @@ -263,9 +263,16 @@ function custom_function_default_print_column_title( $p_column, $p_columns_targe echo ''; } } else { + $t_plugin_columns = columns_get_plugin_columns(); + $t_function = 'print_column_title_' . $p_column; if( function_exists( $t_function ) ) { $t_function( $t_sort, $t_dir, $p_columns_target ); + + } else if ( isset( $t_plugin_columns[ $p_column ] ) ) { + $t_column_object = $t_plugin_columns[ $p_column ]; + print_column_title_plugin( $t_column_object, $p_sort, $p_dir, $p_columns_target ); + } else { echo ''; print_view_bug_sort_link( column_get_title( $p_column ), $p_column, $t_sort, $t_dir, $p_columns_target ); @@ -313,6 +320,8 @@ function custom_function_default_print_column_value( $p_column, $p_issue_row, $p } echo $t_column_end; } else { + $t_plugin_columns = columns_get_plugin_columns(); + if( $p_columns_target != COLUMNS_TARGET_CSV_PAGE ) { $t_function = 'print_column_' . $p_column; } else { @@ -325,6 +334,11 @@ function custom_function_default_print_column_value( $p_column, $p_issue_row, $p } else { $t_function( $p_issue_row[$p_column] ); } + + } else if ( isset( $t_plugin_columns[ $p_column ] ) ) { + $t_column_object = $t_plugin_columns[ $p_column ]; + print_column_plugin( $t_column_object, $p_issue_row, $p_columns_target ); + } else { if( isset( $p_issue_row[$p_column] ) ) { echo $t_column_start . $p_issue_row[$p_column] . $t_column_end; diff --git a/core/events_inc.php b/core/events_inc.php index 83065756be..226f0f99c3 100644 --- a/core/events_inc.php +++ b/core/events_inc.php @@ -71,6 +71,7 @@ # Bug filter events 'EVENT_FILTER_FIELDS' => EVENT_TYPE_DEFAULT, + 'EVENT_FILTER_COLUMNS' => EVENT_TYPE_DEFAULT, # Bug report event 'EVENT_REPORT_BUG_FORM_TOP' => EVENT_TYPE_EXECUTE,