====== Improved Mantis/DokuWiki integration ====== FIXME I think, the description is a little bit clumsy. Please correct. --- //[[Timo.Falk@neumag.saurer.com|Silbaer]] 2007/11/08 06:44// The following description works with mantis version 1.1.0rc2 and dokuwiki version 2007-06-26b. It based on [[mantisbt:issue:7075:integration_with_dokuwiki|this]] description, but extend the integration. You can get all these files from [[http://www.mantisbt.org/bugs/view.php?id=8277|issue 8253]] too. But save your original files:!: ===== Dokuwiki ===== Grab the latest (2007-06-26b) version and install it. Make sure it is working properly. ==== Mantis Syntax Plug-in ==== If you only want links back to mantis, there is no need for a systax plugin. You can use interwiki shortcuts to create links back to mantis (see [[http://wiki.splitbrain.org/wiki:discussion:bugtracking|here]]). But I used a configuration setting from the syntax plugin in the mantis authentication class and perhaps there are other improvements in the future, so here is it. The syntax plugin based an the plugin from Victor Boctor, but I changed the syntax. Now it uses **{** like almost all other plugins instead of **~**. For the syntax-plugin with support for the dokuwiki admin panel, you have to create several files: === \lib\plugins\mantis\syntax.php === 'Timo Falk', 'email' => 'Timo . Falk at gmx . de', 'date' => '2007-11-01', 'name' => 'Mantis enhanced Issues Plugin', 'desc' => 'Support References to Mantis Issues. Based on Mantis Issues Plugin by Victor Boctor', ); } /** * What kind of syntax are we? */ function getType(){ return 'substition'; # typo is intentional } /** * What about paragraphs? */ function getPType(){ return 'normal'; } /** * Where to sort in? */ function getSort(){ return 156; } /** * Connect pattern to lexer */ function connectTo($mode) { $this->Lexer->addSpecialPattern('\{\{Mantis:[0-9]+\}\}', $mode, 'plugin_mantis'); } /** * Handle the match */ function handle($match, $state, $pos, &$handler){ $match = substr( $match, 9, -2 ); // strip "{{Mantis:" from start and "}}" from end return array( strtolower( $match ) ); } /** * Create output */ function render($format, &$renderer, $data) { if ( $format == 'xhtml' ) { // $renderer->externallink( $this->getConf('mantis_url') . 'view.php?id=' . $data[0], $data[0] ); $link['target'] = $conf['target']['wiki']; $link['style'] = ''; $link['pre'] = ''; $link['suf'] = ''; $link['more'] = ''; $link['class'] = 'mantislink'; $link['url'] = $this->getConf('mantis_url') . 'view.php?id=' . $data[0]; $link['name'] = $this->getConf('LinkPrefix') . $data[0]; $link['title'] = $renderer->_xmlEntities($url); //output formatted $renderer->doc .= $renderer->_formatLink($link); return true; } return false; } } ?> === dokuwiki\lib\plugins\mantis\style.css === div.dokuwiki a.mantislink { background: transparent url(images/bug.gif) 0px 1px no-repeat; padding: 1px 0px 1px 16px; } === dokuwiki\lib\plugins\mantis\conf\default.php === === dokuwiki\lib\plugins\mantis\conf\metadata.php === === dokuwiki\lib\plugins\mantis\images\bug.gif === A [[http://wiki.splitbrain.org/lib/images/interwiki/bug.gif|Picture]] with a little bug, placed in front of the bug links. The file is grabed from [[http://wiki.splitbrain.org/wiki:discussion:bugtracking|this]] dokuwiki page. === dokuwiki\lib\plugins\mantis\lang\en\settings.php === ==== Mantis Template ==== Go to DokuWiki settings and configure mantis URL at the bottom of the setup page. Copy the default template (dokuwiki/lib/tpl/default/) into a new folder called //mantis//. Replace the **main.php** with this one: '; tpl_metaheaders(); html_title( $p_page_title ); html_head_javascript(); html_page_top2() // $t_mantis_dir = dirname( __FILE__ ) . DIRECTORY_SEPARATOR; ?>
 
 
 
==== Authentication (Single Sign-On) ==== Create dokuwiki\inc\auth\mantis.class.php with the code below. cando['external'] = true; } /** * Authenticates the user using Mantis APIs. */ function trustExternal($user,$pass,$sticky=false){ global $USERINFO; global $conf; if ( auth_is_user_authenticated() ) { // okay we're logged in - set the globals $USERINFO['pass'] = current_user_get_field( 'password' ); $USERINFO['name'] = current_user_get_field( 'username' ); $USERINFO['mail'] = current_user_get_field( 'email' ); $t_project_name = getNS( getID() ); $t_project_id = project_get_id_by_name( $t_project_name ); $t_access_level = access_get_project_level( $t_project_id ); $t_access_level_string = strtoupper( get_enum_to_string( config_get( 'access_levels_enum_string' ), $t_access_level ) ); $USERINFO['grps'] = array( $t_access_level_string ); $_SERVER['REMOTE_USER'] = $USERINFO['name']; $_SESSION[$conf['title']]['auth']['user'] = $USERINFO['name']; $_SESSION[$conf['title']]['auth']['info'] = $USERINFO; return true; } // to be sure auth_logoff(); return false; } /** * Logout from Mantis */ function logOff(){ auth_logout(); } } ?> ==== Authorisation Configuration ==== Create ''dokuwiki\conf\acl.auth.php'' with the code below. # acl.auth.php # # Don't modify the lines above # # Access Control Lists # # Editing this file by hand shouldn't be necessary. Use the ACL # Manager interface instead. # # If your auth backend allows special char like spaces in groups # or user names you need to urlencode them (only chars <128, leave # UTF-8 multibyte chars as is) # # none 0 # read 1 # edit 2 # create 4 # upload 8 # delete 16 * @VIEWER 1 * @REPORTER 2 * @DEVELOPER 8 * @MANAGER 8 * @ADMINISTRATOR 8 * @ALL 0 ==== Redirect dokuwiki login/logout ==== If you are using url rewrite, append the following lines in your .htaccess file. See also [[http://www.mantisbt.org/bugs/view.php?id=8277|issue 8277]]. RewriteCond %{QUERY_STRING} do=login RewriteCond %{QUERY_STRING} (id=.*) RewriteRule .* /mantis/login_page.php?return=/mantiswiki/doku.php?%1 [R,L] RewriteCond %{QUERY_STRING} do=logout RewriteRule .* /mantis/logout_page.php [R,L] ===== Mantis ===== In mantis there are changes in two file necessary. ==== code/html_api.php ==== . # -------------------------------------------------------- # $Id: html_api.php,v 1.218.2.3 2007/10/22 07:08:33 vboctor Exp $ # -------------------------------------------------------- ########################################################################### # HTML API # # These functions control the display of each page # # This is the call order of these functions, should you need to figure out # which to modify or which to leave out. # # html_page_top1 # html_begin # html_head_begin # html_css # html_content_type # html_rss_link # (html_meta_redirect) # html_title # html_page_top2 # html_page_top2a # html_head_end # html_body_begin # html_header # html_top_banner # html_login_info # (print_project_menu_bar) # print_menu # # ...Page content here... # # html_page_bottom1 # (print_menu) # html_page_bottom1a # html_bottom_banner # html_footer # html_body_end # html_end # ########################################################################### $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR; require_once( $t_core_dir . 'current_user_api.php' ); require_once( $t_core_dir . 'string_api.php' ); require_once( $t_core_dir . 'bug_api.php' ); require_once( $t_core_dir . 'project_api.php' ); require_once( $t_core_dir . 'helper_api.php' ); require_once( $t_core_dir . 'authentication_api.php' ); require_once( $t_core_dir . 'user_api.php' ); require_once( $t_core_dir . 'rss_api.php' ); require_once( $t_core_dir . 'wiki_api.php' ); $g_rss_feed_url = null; # flag for error handler to skip header menus $g_error_send_page_header = true; # Projax library disabled by default. It will be enabled if projax_api.php # is included. But it must be included after html_api.php $g_enable_projax = false; # -------------------- # Sets the url for the rss link associated with the current page. # null: means no feed (default). function html_set_rss_link( $p_rss_feed_url ) { if ( OFF != config_get( 'rss_enabled' ) ) { global $g_rss_feed_url; $g_rss_feed_url = $p_rss_feed_url; } } # -------------------- # Prints the link that allows auto-detection of the associated feed. function html_rss_link() { global $g_rss_feed_url; if ( $g_rss_feed_url !== null ) { echo ""; } } # -------------------- # Print the part of the page that comes before meta redirect tags should # be inserted function html_page_top1( $p_page_title = null ) { global $g_path; html_begin(); html_head_begin(); html_css(); html_content_type(); include( config_get( 'meta_include_file' ) ); html_rss_link(); echo ''; html_title( $p_page_title ); html_head_javascript(); } # -------------------- # Print the part of the page that comes after meta tags, but before the # actual page content function html_page_top2() { html_page_top2a(); if ( !db_is_connected() ) { return; } if ( auth_is_user_authenticated() ) { html_login_info(); if( ON == config_get( 'show_project_menu_bar' ) ) { print_project_menu_bar(); PRINT '
'; } } print_menu(); } # -------------------- # Print the part of the page that comes after meta tags and before the # actual page content, but without login info or menus. This is used # directly during the login process and other times when the user may # not be authenticated function html_page_top2a() { global $g_error_send_page_header; html_head_end(); html_body_begin(); $g_error_send_page_header = false; html_header(); html_top_banner(); } # -------------------- # Print the part of the page that comes below the page content # $p_file should always be the __FILE__ variable. This is passed to show source function html_page_bottom1( $p_file = null ) { if ( !db_is_connected() ) { return; } if ( config_get( 'show_footer_menu' ) ) { PRINT '
'; print_menu(); } html_page_bottom1a( $p_file ); } # -------------------- # Print the part of the page that comes below the page content but leave off # the menu. This is used during the login process and other times when the # user may not be authenticated. function html_page_bottom1a( $p_file = null ) { if ( null === $p_file ) { $p_file = basename( $_SERVER['PHP_SELF'] ); } html_bottom_banner(); html_footer( $p_file ); html_body_end(); html_end(); } # -------------------- # (1) Print the document type and the opening tag function html_begin() { # @@@ NOTE make this a configurable global. #echo '', "\n"; #echo '', "\n"; echo '', "\n"; echo '', "\n"; } # -------------------- # (2) Begin the section function html_head_begin() { echo '', "\n"; } # -------------------- # (3) Print the content-type function html_content_type() { echo "\t", '', "\n"; } # -------------------- # (4) Print the window title function html_title( $p_page_title = null ) { $t_title = config_get( 'window_title' ); echo "\t", ''; if ( 0 == strlen( $p_page_title ) ) { echo string_display( $t_title ); } else { if ( 0 == strlen( $t_title ) ) { echo $p_page_title; } else { echo $p_page_title . ' - ' . string_display( $t_title ); } } echo '', "\n"; } # -------------------- # (5) Print the link to include the css file function html_css() { $t_css_url = config_get( 'css_include_file' ); echo "\t", '', "\n"; # fix for NS 4.x css echo "\t", '', "\n"; } # -------------------- # (6) Print an HTML meta tag to redirect to another page # This function is optional and may be called by pages that need a redirect. # $p_time is the number of seconds to wait before redirecting. # If we have handled any errors on this page and the 'stop_on_errors' config # option is turned on, return false and don't redirect. function html_meta_redirect( $p_url, $p_time = null, $p_sanitize = false ) { if ( ON == config_get( 'stop_on_errors' ) && error_handled() ) { return false; } if ( null === $p_time ) { $p_time = current_user_get_pref( 'redirect_delay' ); } if ( $p_sanitize ) { $t_url = string_sanitize_url( $p_url ); } else { $t_url = $p_url; } echo "\t\n"; return true; } # --------------------- # (6a) Javascript... function html_head_javascript() { global $g_path; if ( ON == config_get( 'use_javascript' ) ) { echo "\t" . '' . "\n"; echo "\t" . '' . "\n"; global $g_enable_projax; if ( $g_enable_projax ) { echo ''; echo ''; } } } # -------------------- # (7) End the section function html_head_end() { echo '', "\n"; } # -------------------- # (8) Begin the section function html_body_begin() { echo '', "\n"; } # -------------------- # (9) Print the title displayed at the top of the page function html_header() { $t_title = config_get( 'page_title' ); echo '
', string_display( $t_title ), '
', "\n"; } # -------------------- # (10) Print a user-defined banner at the top of the page if there is one. function html_top_banner() { global $g_path; $t_page = config_get( 'top_include_page' ); if ( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) { include( $t_page ); } else { if ( is_page_name( 'login_page' ) ) { $t_align = 'center'; } else { $t_align = 'left'; } echo '
'; echo 'Mantis Bugtracker'; echo '
'; } } # -------------------- # (11) Print the user's account information # Also print the select box where users can switch projects function html_login_info() { global $g_path; $t_username = current_user_get_field( 'username' ); $t_access_level = get_enum_element( 'access_levels', current_user_get_access_level() ); $t_now = date( config_get( 'complete_date_format' ) ); $t_realname = current_user_get_field( 'realname' ); PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT '
'; } # -------------------- # (12) Print a user-defined banner at the bottom of the page if there is one. function html_bottom_banner() { $t_page = config_get( 'bottom_include_page' ); if ( !is_blank( $t_page ) && file_exists( $t_page ) && !is_dir( $t_page ) ) { include( $t_page ); } } # -------------------- # (13) Print the page footer information function html_footer( $p_file ) { global $g_timer, $g_queries_array, $g_request_time; # If a user is logged in, update their last visit time. # We do this at the end of the page so that: # 1) we can display the user's last visit time on a page before updating it # 2) we don't invalidate the user cache immediately after fetching it # 3) don't do this on the password verification or update page, as it causes the # verification comparison to fail if ( auth_is_user_authenticated() && !( is_page_name( 'verify.php' ) || is_page_name( 'account_update.php' ) ) ) { $t_user_id = auth_get_current_user_id(); user_update_last_visit( $t_user_id ); } echo "\t", '
', "\n"; echo "\t", '
', "\n"; echo '
'; if ( ON == config_get( 'show_version' ) ) { echo "\t", 'Mantis ', config_get( 'mantis_version' ), '', '[^]', "\n"; } echo "\t", '
Copyright © 2000 - 2007 Mantis Group
', "\n"; # only display webmaster email is current user is not the anonymous user if ( ! is_page_name( 'login_page.php' ) && !current_user_is_anonymous() ) { echo "\t", '
', config_get( 'webmaster_email' ), '
', "\n"; } # print timings if ( ON == config_get( 'show_timer' ) ) { $g_timer->print_times(); } # print db queries that were run if ( helper_show_queries() ) { $t_count = count( $g_queries_array ); echo "\t", $t_count, ' total queries executed.
', "\n"; $t_unique_queries = 0; $t_shown_queries = array(); for ( $i = 0; $i < $t_count; $i++ ) { if ( ! in_array( $g_queries_array[$i][0], $t_shown_queries ) ) { $t_unique_queries++; $g_queries_array[$i][3] = false; array_push( $t_shown_queries, $g_queries_array[$i][0] ); } else { $g_queries_array[$i][3] = true; } } echo "\t", $t_unique_queries . ' unique queries executed.
', "\n"; if ( ON == config_get( 'show_queries_list' ) ) { echo "\t", '', "\n"; $t_total = 0; for ( $i = 0; $i < $t_count; $i++ ) { $t_time = $g_queries_array[$i][1]; $t_caller = $g_queries_array[$i][2]; $t_total += $t_time; $t_style_tag = ''; if ( true == $g_queries_array[$i][3] ) { $t_style_tag = ' style="color: red;"'; } echo "\t", '', ($i+1), ''; echo '', $t_time , ''; echo '', $t_caller, '
', string_html_specialchars($g_queries_array[$i][0]), '
', "\n"; } # @@@ Note sure if we should localize them given that they are debug info. Will add if requested by users. echo "\t", '', "\n"; echo "\t", '', "\n"; echo "\t", '
', $t_total, 'SQL Queries Total Time
', round( microtime_float() - $g_request_time, 4 ), 'Page Request Total Time
', "\n"; } } echo '
'; echo 'Powered by Mantis Bugtracker'; echo '
'; } # -------------------- # (14) End the section function html_body_end() { echo '', "\n"; } # -------------------- # (15) Print the closing tag function html_end() { echo '', "\n"; } ########################################################################### # HTML Menu API ########################################################################### function prepare_custom_menu_options( $p_config ) { $t_custom_menu_options = config_get( $p_config ); $t_options = array(); foreach( $t_custom_menu_options as $t_custom_option ) { $t_access_level = $t_custom_option[1]; if ( access_has_project_level( $t_access_level ) ) { $t_caption = lang_get_defaulted( $t_custom_option[0] ); $t_link = $t_custom_option[2]; $t_options[] = "$t_caption"; } } return $t_options; } # -------------------- # Print the main menu function print_menu() { global $g_path; if ( auth_is_user_authenticated() ) { $t_protected = current_user_get_field( 'protected' ); $t_current_project = helper_get_current_project(); PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT '
'; } } # -------------------- # Print the menu bar with a list of projects to which the user has access function print_project_menu_bar() { global $g_path; $t_project_ids = current_user_get_accessible_projects(); PRINT ''; PRINT ''; PRINT ''; PRINT ''; PRINT '
'; } # -------------------- # Print the menu bar with a list of projects to which the user has access function print_subproject_menu_bar( $p_project_id, $p_parents = '' ) { global $g_path; $t_subprojects = current_user_get_accessible_subprojects( $p_project_id ); $t_char = ':'; foreach ( $t_subprojects as $t_subproject ) { PRINT "$t_char " . string_display( project_get_field( $t_subproject, 'name' ) ) . ''; print_subproject_menu_bar( $t_subproject, $p_parents . $t_subproject . ';' ); $t_char = ','; } } # -------------------- # Print the menu for the graph summary section function print_menu_graph() { global $g_path; if ( config_get( 'use_jpgraph' ) ) { $t_icon_path = config_get( 'icon_path' ); PRINT '
'; PRINT '' . lang_get( 'synthesis_link' ) . ' | '; PRINT '' . lang_get( 'status_link' ) . ' | '; PRINT '' . lang_get( 'priority_link' ) . ' | '; PRINT '' . lang_get( 'severity_link' ) . ' | '; PRINT '' . lang_get( 'category_link' ) . ' | '; PRINT '' . lang_get( 'resolution_link' ) . ''; } } # -------------------- # Print the menu for the manage section # $p_page specifies the current page name so it's link can be disabled function print_manage_menu( $p_page = '' ) { global $g_path; $t_manage_user_page = '' . $g_path . 'manage_user_page.php'; $t_manage_project_menu_page = '' . $g_path . 'manage_proj_page.php'; $t_manage_custom_field_page = '' . $g_path . 'manage_custom_field_page.php'; $t_manage_config_page = '' . $g_path . 'adm_config_report.php'; $t_manage_prof_menu_page = '' . $g_path . 'manage_prof_menu_page.php'; # $t_documentation_page = '' . $g_path . 'documentation_page.php'; switch ( $p_page ) { case $t_manage_user_page: $t_manage_user_page = ''; break; case $t_manage_project_menu_page: $t_manage_project_menu_page = ''; break; case $t_manage_custom_field_page: $t_manage_custom_field_page = ''; break; case $t_manage_config_page: $t_manage_config_page = ''; break; case $t_manage_prof_menu_page: $t_manage_prof_menu_page = ''; break; # case $t_documentation_page: # $t_documentation_page = ''; # break; } PRINT '
'; if ( access_has_global_level( config_get( 'manage_user_threshold' ) ) ) { print_bracket_link( $t_manage_user_page, lang_get( 'manage_users_link' ) ); } if ( access_has_project_level( config_get( 'manage_project_threshold' ) ) ) { print_bracket_link( $t_manage_project_menu_page, lang_get( 'manage_projects_link' ) ); } if ( access_has_global_level( config_get( 'manage_custom_fields_threshold' ) ) ) { print_bracket_link( $t_manage_custom_field_page, lang_get( 'manage_custom_field_link' ) ); } if ( access_has_global_level( config_get( 'manage_global_profile_threshold' ) ) ) { print_bracket_link( $t_manage_prof_menu_page, lang_get( 'manage_global_profiles_link' ) ); } if ( access_has_project_level( config_get( 'view_configuration_threshold' ) ) ) { print_bracket_link( $t_manage_config_page, lang_get( 'manage_config_link' ) ); } # print_bracket_link( $t_documentation_page, lang_get( 'documentation_link' ) ); PRINT '
'; } # -------------------- # Print the menu for the manage configuration section # $p_page specifies the current page name so it's link can be disabled function print_manage_config_menu( $p_page = '' ) { global $g_path; $t_configuration_report = '' . $g_path . 'adm_config_report.php'; $t_permissions_summary_report = '' . $g_path . 'adm_permissions_report.php'; $t_manage_work_threshold = '' . $g_path . 'manage_config_work_threshold_page.php'; $t_manage_email = '' . $g_path . 'manage_config_email_page.php'; $t_manage_workflow = '' . $g_path . 'manage_config_workflow_page.php'; 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; } PRINT '
'; if ( access_has_project_level( config_get( 'view_configuration_threshold' ) ) ) { print_bracket_link( $t_configuration_report, lang_get_defaulted( 'configuration_report' ) ); print_bracket_link( $t_permissions_summary_report, lang_get( 'permissions_summary_report' ) ); print_bracket_link( $t_manage_work_threshold, lang_get( 'manage_threshold_config' ) ); print_bracket_link( $t_manage_workflow, lang_get( 'manage_workflow_config' ) ); print_bracket_link( $t_manage_email, lang_get( 'manage_email_config' ) ); } PRINT '
'; } # -------------------- # Print the menu for the account section # $p_page specifies the current page name so it's link can be disabled function print_account_menu( $p_page='' ) { global $g_path; $t_account_page = '' . $g_path . 'account_page.php'; $t_account_prefs_page = '' . $g_path . 'account_prefs_page.php'; $t_account_profile_menu_page = '' . $g_path . 'account_prof_menu_page.php'; $t_account_sponsor_page = '' . $g_path . 'account_sponsor_page.php'; switch ( $p_page ) { case $t_account_page : $t_account_page = ''; break; case $t_account_prefs_page : $t_account_prefs_page = ''; break; case $t_account_profile_menu_page : $t_account_profile_menu_page = ''; break; case $t_account_sponsor_page : $t_account_sponsor_page = ''; break; } print_bracket_link( $t_account_page, lang_get( 'account_link' ) ); print_bracket_link( $t_account_prefs_page, lang_get( 'change_preferences_link' ) ); if ( access_has_project_level( config_get( 'add_profile_threshold' ) ) ) { print_bracket_link( $t_account_profile_menu_page, lang_get( 'manage_profiles_link' ) ); } if ( ( config_get( 'enable_sponsorship' ) == ON ) && ( access_has_project_level( config_get( 'view_sponsorship_total_threshold' ) ) ) && !current_user_is_anonymous() ) { print_bracket_link( $t_account_sponsor_page, lang_get( 'my_sponsorship' ) ); } } # -------------------- # Print the menu for the docs section # $p_page specifies the current page name so it's link can be disabled function print_doc_menu( $p_page='' ) { global $g_path; $t_documentation_html = config_get( 'manual_url' ); $t_proj_doc_page = '' . $g_path . 'proj_doc_page.php'; $t_proj_doc_add_page = '' . $g_path . 'proj_doc_add_page.php'; switch ( $p_page ) { case $t_documentation_html : $t_documentation_html = ''; break; case $t_proj_doc_page : $t_proj_doc_page = ''; break; case $t_proj_doc_add_page : $t_proj_doc_add_page = ''; break; } print_bracket_link( $t_documentation_html, lang_get( 'user_documentation' ) ); print_bracket_link( $t_proj_doc_page, lang_get( 'project_documentation' ) ); if ( file_allow_project_upload() ) { print_bracket_link( $t_proj_doc_add_page, lang_get( 'add_file' ) ); } } # -------------------- # Print the menu for the summary section # $p_page specifies the current page name so it's link can be disabled function print_summary_menu( $p_page='' ) { global $g_path; PRINT '
'; print_bracket_link( '' . $g_path . 'print_all_bug_page.php', lang_get( 'print_all_bug_page_link' ) ); if ( config_get( 'use_jpgraph' ) != 0 ) { $t_summary_page = '' . $g_path . 'summary_page.php'; $t_summary_jpgraph_page = '' . $g_path . 'summary_jpgraph_page.php'; switch ( $p_page ) { case $t_summary_page : $t_summary_page = ''; break; case $t_summary_jpgraph_page: $t_summary_jpgraph_page = ''; break; } print_bracket_link( $t_summary_page, lang_get( 'summary_link' ) ); print_bracket_link( $t_summary_jpgraph_page, lang_get( 'summary_jpgraph_link' ) ); } PRINT '
'; } #========================= # Candidates for moving to print_api #========================= # -------------------- # Print the color legend for the status colors function html_status_legend() { PRINT '
'; PRINT ''; PRINT ''; $t_arr = explode_enum_string( config_get( 'status_enum_string' ) ); $enum_count = count( $t_arr ); $width = (int)(100 / $enum_count); for ( $i=0; $i < $enum_count; $i++) { $t_s = explode_enum_arr( $t_arr[$i] ); $t_val = get_enum_element( 'status', $t_s[0] ); $t_color = get_status_color( $t_s[0] ); PRINT ""; } PRINT ''; PRINT '
$t_val
'; if ( ON == config_get( 'status_percentage_legend' ) ) { html_status_percentage_legend(); } } # -------------------- # Print the legend for the status percentage function html_status_percentage_legend() { $t_mantis_bug_table = config_get( 'mantis_bug_table' ); $t_project_id = helper_get_current_project(); $t_user_id = auth_get_current_user_id(); #checking if it's a per project statistic or all projects $t_specific_where = helper_project_specific_where( $t_project_id, $t_user_id ); $query = "SELECT status, COUNT(*) AS number FROM $t_mantis_bug_table WHERE $t_specific_where GROUP BY status"; $result = db_query( $query ); $t_bug_count = 0; $t_status_count_array = array(); while ( $row = db_fetch_array( $result ) ) { $t_status_count_array[ $row['status'] ] = $row['number']; $t_bug_count += $row['number']; } $t_arr = explode_enum_string( config_get( 'status_enum_string' ) ); $enum_count = count( $t_arr ); if ( $t_bug_count > 0 ) { echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; for ( $i=0; $i < $enum_count; $i++) { $t_s = explode_enum_arr( $t_arr[$i] ); $t_color = get_status_color( $t_s[0] ); $t_status = $t_s[0]; if ( !isset( $t_status_count_array[ $t_status ] ) ) { $t_status_count_array[ $t_status ] = 0; } $width = round( ( $t_status_count_array[ $t_status ] / $t_bug_count ) * 100 ); if ($width > 0) { echo ""; } } echo ''; echo '
'.lang_get( 'issue_status_percentage' ).'
$width%
'; } } # -------------------- # Print an html button inside a form function html_button ( $p_action, $p_button_text, $p_fields = null, $p_method = 'post' ) { $p_action = urlencode( $p_action ); $p_button_text = string_attribute( $p_button_text ); if ( null === $p_fields ) { $p_fields = array(); } if ( strtolower( $p_method ) == 'get' ) { $t_method = 'get'; } else { $t_method = 'post'; } PRINT "
\n"; foreach ( $p_fields as $key => $val ) { $key = string_attribute( $key ); $val = string_attribute( $val ); PRINT " \n"; } PRINT " \n"; PRINT "
\n"; } # -------------------- # Print a button to update the given bug function html_button_bug_update( $p_bug_id ) { if ( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { html_button( string_get_bug_update_page(), lang_get( 'update_bug_button' ), array( 'bug_id' => $p_bug_id ) ); } } # -------------------- # Print Change Status to: button # This code is similar to print_status_option_list except # there is no masking, except for the current state function html_button_bug_change_status( $p_bug_id ) { global $g_path; $t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' ); $t_bug_current_state = bug_get_field( $p_bug_id, 'status' ); $t_current_access = access_get_project_level( $t_bug_project_id ); $t_enum_list = get_status_option_list( $t_current_access, $t_bug_current_state, false, ( bug_get_field( $p_bug_id, 'reporter_id' ) == auth_get_current_user_id() && ( ON == config_get( 'allow_reporter_close' ) ) ) ); if ( count( $t_enum_list ) > 0 ) { # resort the list into ascending order after noting the key from the first element (the default) $t_default_arr = each( $t_enum_list ); $t_default = $t_default_arr['key']; ksort( $t_enum_list ); reset( $t_enum_list ); echo "
"; $t_button_text = lang_get( 'bug_status_to_button' ); echo ""; echo " '; $t_bug_id = string_attribute( $p_bug_id ); echo "\n"; echo "
\n"; } } # -------------------- # Print Assign To: combo box of possible handlers function html_button_bug_assign_to( $p_bug_id ) { global $g_path; # 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_assign_threshold', config_get( 'update_bug_threshold' ) ), $p_bug_id ) ) { return; } $t_reporter_id = bug_get_field( $p_bug_id, 'reporter_id' ); $t_handler_id = bug_get_field( $p_bug_id, 'handler_id' ); $t_current_user_id = auth_get_current_user_id(); $t_new_status = ( ON == config_get( 'auto_set_status_to_assigned' ) ) ? config_get( 'bug_assigned_status' ) : $t_status; $t_options = array(); $t_default_assign_to = null; if ( ( $t_handler_id != $t_current_user_id ) && ( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_current_user_id ) ) ) { $t_options[] = array( $t_current_user_id, '[' . lang_get( 'myself' ) . ']' ); $t_default_assign_to = $t_current_user_id; } if ( ( $t_handler_id != $t_reporter_id ) && user_exists( $t_reporter_id ) && ( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_reporter_id ) ) ) { $t_options[] = array( $t_reporter_id, '[' . lang_get( 'reporter' ) . ']' ); if ( $t_default_assign_to === null ) { $t_default_assign_to = $t_reporter_id; } } PRINT "
"; $t_button_text = lang_get( 'bug_assign_to_button' ); PRINT ""; PRINT " "; $t_bug_id = string_attribute( $p_bug_id ); PRINT "\n"; PRINT "
\n"; } # -------------------- # Print a button to move the given bug to a different project function html_button_bug_move( $p_bug_id ) { global $g_path; $t_status = bug_get_field( $p_bug_id, 'status' ); if ( access_has_bug_level( config_get( 'move_bug_threshold' ), $p_bug_id ) ) { html_button( '' . $g_path . 'bug_actiongroup_page.php', lang_get( 'move_bug_button' ), array( 'bug_arr[]' => $p_bug_id, 'action' => 'MOVE' ) ); } } # -------------------- # Print a button to move the given bug to a different project function html_button_bug_create_child( $p_bug_id ) { if ( ON == config_get( 'enable_relationship' ) ) { if ( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { html_button( string_get_bug_report_url(), lang_get( 'create_child_bug_button' ), array( 'm_id' => $p_bug_id ) ); } } } # -------------------- # Print a button to reopen the given bug function html_button_bug_reopen( $p_bug_id ) { global $g_path; $t_status = bug_get_field( $p_bug_id, 'status' ); $t_reopen_status = config_get( 'bug_reopen_status' ); $t_project = bug_get_field( $p_bug_id, 'project_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( '' . $g_path . 'bug_change_status_page.php', lang_get( 'reopen_bug_button' ), array( 'bug_id' => $p_bug_id , 'new_status' => $t_reopen_status, 'reopen_flag' => ON ) ); } } # -------------------- # Print a button to monitor the given bug function html_button_bug_monitor( $p_bug_id ) { global $g_path; if ( access_has_bug_level( config_get( 'monitor_bug_threshold' ), $p_bug_id ) ) { html_button( '' . $g_path . 'bug_monitor.php', lang_get( 'monitor_bug_button' ), array( 'bug_id' => $p_bug_id, 'action' => 'add' ) ); } } # -------------------- # Print a button to unmonitor the given bug # no reason to ever disallow someone from unmonitoring a bug function html_button_bug_unmonitor( $p_bug_id ) { global $g_path; html_button( '' . $g_path . 'bug_monitor.php', lang_get( 'unmonitor_bug_button' ), array( 'bug_id' => $p_bug_id, 'action' => 'delete' ) ); } # -------------------- # Print a button to delete the given bug function html_button_bug_delete( $p_bug_id ) { global $g_path; if ( access_has_bug_level( config_get( 'delete_bug_threshold' ), $p_bug_id ) ) { html_button( '' . $g_path . 'bug_actiongroup_page.php', lang_get( 'delete_bug_button' ), array( 'bug_arr[]' => $p_bug_id, 'action' => 'DELETE' ) ); } } # -------------------- # Print a button to create a wiki page function html_button_wiki( $p_bug_id ) { global $g_path; if ( ON == config_get( 'wiki_enable' ) ) { if ( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) { html_button( '' . $g_path . 'wiki.php', lang_get_defaulted( 'Wiki' ), array( 'id' => $p_bug_id, 'type' => 'issue' ), 'get' ); } } } # -------------------- # Print all buttons for view bug pages function html_buttons_view_bug_page( $p_bug_id ) { $t_resolved = config_get( 'bug_resolved_status_threshold' ); $t_status = bug_get_field( $p_bug_id, 'status' ); $t_readonly = bug_is_readonly( $p_bug_id ); PRINT ''; if ( !$t_readonly ) { # UPDATE button echo ''; # ASSIGN button echo ''; } # Change State button echo ''; # MONITOR/UNMONITOR button echo ''; if ( !$t_readonly ) { # CREATE CHILD button echo ''; } if ( $t_resolved <= $t_status ) { # resolved is not the same as readonly PRINT ''; } if ( !$t_readonly ) { # MOVE button echo ''; } # DELETE button echo ''; helper_call_custom_function( 'print_bug_view_page_custom_buttons', array( $p_bug_id ) ); echo '
'; html_button_bug_update( $p_bug_id ); echo ''; html_button_bug_assign_to( $p_bug_id ); echo ''; html_button_bug_change_status( $p_bug_id ); echo ''; if ( !current_user_is_anonymous() ) { if ( user_is_monitoring_bug( auth_get_current_user_id(), $p_bug_id ) ) { html_button_bug_unmonitor( $p_bug_id ); } else { html_button_bug_monitor( $p_bug_id ); } } echo ''; html_button_bug_create_child( $p_bug_id ); echo ''; # REOPEN button html_button_bug_reopen( $p_bug_id ); PRINT ''; html_button_bug_move( $p_bug_id ); echo ''; html_button_bug_delete( $p_bug_id ); echo '
'; } /** * Print the Update Tag button * @param integer Tag ID */ function html_button_tag_update( $p_tag_id ) { global $g_path; if ( access_has_global_level( config_get( 'tag_edit_threshold' ) ) || ( auth_get_current_user_id() == tag_get_field( $p_tag_id, 'user_id' ) && access_has_global_level( config_get( 'tag_edit_own_threshold' ) ) ) ) { html_button( '' . $g_path . 'tag_update_page.php', lang_get( 'tag_update_button' ), array( 'tag_id' => $p_tag_id ) ); } } /** * Print the Delete Tag button * @param integer Tag ID */ function html_button_tag_delete( $p_tag_id ) { global $g_path; if ( access_has_global_level( config_get( 'tag_edit_threshold' ) ) ) { html_button( '' . $g_path . 'tag_delete.php', lang_get( 'tag_delete_button' ), array( 'tag_id' => $p_tag_id ) ); } } /** * Print all buttons for the Tag View page * @param integer Tag ID */ function html_buttons_tag_view_page( $p_tag_id ) { html_button_tag_update( $p_tag_id ); html_button_tag_delete( $p_tag_id ); } ?>
==== core/string_api.php ==== In this file only two functions are changed, so it is overkill to place the whole file here. Replace the functions with the following === function string_get_bug_update_link === # -------------------- # return an href anchor that links to a bug UPDATE page for the given bug # account for the user preference and site override function string_get_bug_update_link( $p_bug_id, $p_user_id = null ) { global $g_path; $t_summary = string_attribute( bug_get_field( $p_bug_id, 'summary' ) ); return '' . bug_format_id( $p_bug_id ) . ''; } === function string_get_bug_report_link === # -------------------- # return an href anchor that links to a bug REPORT page for the given bug # account for the user preference and site override function string_get_bug_report_link( $p_user_id = null ) { global $g_path; return '' . lang_get( 'report_bug_link' ) . ''; } ===== Configuration ===== ==== Dokuwiki ==== Log in as administrator, go to the admin panel and configure the mantis syntax plugin and the authentication backend. :!: You have to config the filepath and URL to your mantis in the syntax plugin **before** you activate the mantis authentication backend! :!: ==== Mantis ==== Include this in your mantis configuration. Adjust the paths so it match your install. ##################### # Wiki Integration ##################### # Wiki Integration Enabled? $g_wiki_enable = ON; # Wiki Engine $g_wiki_engine = 'dokuwiki'; # Wiki namespace to be used as root for all pages relating to this mantis installation. $g_wiki_root_namespace = 'mantis'; # URL under which the wiki engine is hosted. Must be on the same server. $g_wiki_engine_url = $t_protocol . '://' . $t_host . '/dokuwiki/'; # CSS file $g_css_include_file = '/mantis/css/default.css';