Integrating DokuWiki with Mantis

Disclaimer

This document describes the steps needed to integrate DokuWiki with Mantis. This is just for experimenting with the concept, and it is not a supported feature of Mantis. A formal implementation may be available in future releases.

The following description works fine with mantis version 1.1.0rc2 and dokuwiki rc2009-12-02. This mantis version already includes the php-scripts noted in the “Mantis steps” section on this page, so there’s less work to do to integrate dokuwiki to mantis 1.1.0rc2. Find details below.

Integration Functionality

The integration between Mantis and DokuWiki so far achieves the following:

  • Customises DokuWiki to honour Mantis authentication (i.e. single sign-on).
  • Customises DokuWiki authorisation based on Mantis access levels (i.e. groups).
  • Adds a Wiki link on the issue view simple/advanced pages to their corresponding Wiki issue page.
  • Adds a Wiki menu option which maps to the corresponding project Wiki page, or general page in case of “All Projects”.
  • Provides a way for Wiki pages to link to Mantis issues, e.g. ~~Mantis:7075~~.

Tips

Following are some tips that are of interest to Mantis / DokuWiki integration:

  • To define a template for all Wiki pages within a namespace, create _template.txt in the namespace folder (namespace is located into the DOKUWIKI_ROOT/data/mantis directory). All pages created within this namespace will use the contents of the templates as a start point. This will affect the way the Wiki is structure. For example, if all issues within a project have a namespace, then they can all share one template, if there is a namespace per category, then there can be a template per category. The exact structure to be used should be configurable through Mantis configuration.
  • Using different subdomains. eg: mantis lives at: bugs.example.com and doku lives at wiki.exmaple.com. You need to make the cookies accessible to both domains, so in your mantis config_inc.php you will want to set
$g_wiki_engine_url = 'http://wiki.example.com/';
//So wiki and bugs can share cookie info
$g_cookie_domain = '.example.com';

DokuWiki Steps

Installation

Install DokuWiki and make sure it is working properly. This involves making sure that you can create pages, edit them, view them, etc.

Configuration

Modify or add the configuration values in dokuwiki\conf\local.php to match the values below. The default values can be found in dokuwiki\conf\dokuwiki.php and the values you add to local.php will override them.

Using the bundled config plugin will delete the manually added lines! So you should consider placing the “define” lines in dokuwiki\conf\dokuwiki.php although these changes will get lost during a mantis update. In fact a fix is needed to implement the two settings to the config page.

#
# Add the following lines:
#
 
define( 'MANTIS_ROOT', 'c:/inetpub/wwwroot/mantisbt/' );  // file path to Mantis, must terminate with /
define( 'MANTIS_URL', 'http://localhost/mantisbt/' );     // url to Mantis, must terminate with /
 
#
# Modify the following configuration options to match the values below:
#
 
$conf['useacl']       = 1;                // Use Access Control Lists to restrict access?
$conf['authtype']     = 'mantis';         // which authentication backend should be used
$conf['defaultgroup'] = 'VIEWER';         // Default groups new Users are added to
$conf['superuser'] = '@ADMINISTRATOR';    // allows mantis administrator to access dokuwiki admin area

Authentication (Single Sign-On)

Create dokuwiki\inc\auth\mantis.class.php with the code below.

<?php
/**
 * Mantis auth backend
 *
 * Uses external Trust mechanism to check against Mantis'
 * user cookie.
 * 13/12/2009 ~ @Tiago Gomes:
 * added modifications to make possible to set project related user rights.(http://www.mantisbt.org/bugs/view.php?id=8249)
 * added modifications so that mantis support logging in/out from DokuWiki’s login page (http://www.mantisbt.org/bugs/view.php?id=8277)
 * 
 *
 * @author    Victor Boctor (http://www.futureware.biz)
 * 
 */
require_once( MANTIS_ROOT . 'core.php' );
 
#dbg($GLOBALS);
 
class auth_mantis extends auth_basic {
    /**
     * Constructor.
     *
     * Sets additional capabilities and config strings
     */
    function auth_mantis(){
        $this->cando['external'] = true;
 
        $this->cando['logoff' ] = true; // module has a logoff method
    }
    
    /**
     * Authenticates the user using Mantis APIs.
     */
    function trustExternal($user,$pass,$sticky=false){
        global $USERINFO;
        global $conf;
 
        $ValidUser = false;
 
        // Has a user name been provided?
        if ( !empty ( $user ) )
        {   
            // User name provided, so login via form in progress...
            // Are the specified user name and password valid?
            if ( auth_attempt_login ( $user, $pass, $sticky ) )
            {   
                // Credential accepted...
                $_SERVER['REMOTE_USER'] = $user; // Set the user name (makes things work...)
                $ValidUser = true; // Report success.
            }
            else
            {   
                // Invalid credentials              
                        if ( !$silent )
                {   
                    sg ( $lang [ 'badlogin' ], -1 );
                }
                
                $ValidUser = false;
            }
        }
        else
        {   
            // No user name provided.
            // Is a user already logged in?
            if ( auth_is_user_authenticated ( ) )
            {   
                // Yes, a user is logged in, so set the globals...
                // is it a media display or a page?
                if (isset($_REQUEST['media'])) {
                    //media
                    $t_project_name = explode( ':', getNS( getID("media",false) ) );
                } else {
                    // normal page
                    $t_project_name = explode( ':', getNS( getID() ) );
                }
                $t_project_id = project_get_id_by_name( $t_project_name[1] );
                $t_access_level = access_get_project_level( $t_project_id );
                $t_access_level_string = strtoupper( MantisEnum::getLabel( config_get( 'access_levels_enum_string' ),  $t_access_level ) ); // mantis 1.2.0rc
                // $t_access_level_string = strtoupper( get_enum_to_string( config_get( 'access_levels_enum_string' ),  $t_access_level ) ); 
                $t_access_level_string_ex = strtoupper( $t_project_name[1] ) . '_' . $t_access_level_string;
 
                $USERINFO['grps'] = array( $t_access_level_string, $t_access_level_string_ex );
                $USERINFO[ 'pass' ] = current_user_get_field ( 'password' );
                $USERINFO[ 'name' ] = current_user_get_field ( 'username' );
                $USERINFO[ 'mail' ] = current_user_get_field ( 'email' );
                
                $_SERVER[ 'REMOTE_USER' ] = $USERINFO[ 'name' ];
                $_SESSION[ $conf[ 'title' ]][ 'auth' ][ 'user' ] = $USERINFO[ 'name' ];
                $_SESSION[ $conf[ 'title' ]][ 'auth' ][ 'info' ] = $USERINFO;
                
                $ValidUser = true;
            }
            else
            {   
                $ValidUser = false;
            }
        }
        
        // Is there a valid user login?
        if ( true != $ValidUser )
        {   
            // No, so make sure any existing authentication is revoked.
            auth_logoff ( );
        }
        
        return $ValidUser;
    }
    /**
     * Logout from Mantis
     */
    function logOff(){
        auth_logout();
    }
}
?>

This codes already contains the following mods:

  • Issue 8249 which makes it possible to set project related user rights.
  • Support logging in/out from DokuWiki’s login page Issue 8277

If you want the original code, you can see the wiki history

Authorisation Configuration

You can set per project(namespace) user right as follows: for each project the user has access on mantis it will be created a group: PROJECT_USERRIGHT i.e

my_namespace:my_project:* @ALL 0
my_namespace:my_project:* @MYPROJECT_VIEWER 1
my_namespace:my_project:* @MYPROJECT_DEVELOPER 8

and you can still use the defaults. Follows a basic one acl.auth.php

# acl.auth.php
# <?php exit()?>
# 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

Mantis Syntax Plug-in

This plugin is to be placed in dokuwiki\lib\plugins\mantis\syntax.php.

<?php
/**
 * Mantis Plugin: Hyperlinks references to Mantis Issues
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Victor Boctor (http://www.futureware.biz)
 */
 
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * A plug-in that hyper links references to Mantis issues.  References
 * to Mantis issues should use the following format: ~~Mantis:123~~.
 *
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_mantis extends DokuWiki_Syntax_Plugin {
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Victor Boctor',
            'email'  => 'vboctor at users . sourceforge . net',
            'date'   => '2006-05-18',
            'name'   => 'Mantis Issues Plugin',
            'desc'   => 'Support References to Mantis Issues',
            'url'    => 'http://www.futureware.biz',
        );
    }
 
    /**
     * 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( MANTIS_URL . 'view.php?id=' . $data[0], $data[0] );
            return true;
        }
        return false;
    }
}
?>

Mantis Steps

The following steps are already done, if you use mantis 1.1.0rc2 (or later). The only step to do in this mantis version is to add

$g_wiki_enable = ON;

to your config_inc.php and eventually change the other variables from the ‘Wiki Integration’ section shown in the next box.

If you use a mantis version which is older than 1.1.0rc2 please check if any of the changes below still need to be done.

Configuration

Add the following configuration items to config_inc.php. In the proper integration this will be part of config_defaults_inc.php (but with $g_wiki_enable = Off as default)

	#####################
	# 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 . '/%wiki_engine%/';

wiki_api.php

Create mantis/core/wiki_api.php with the following content:

<?php
	# Mantis - a php based bugtracking system
	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
	# Copyright (C) 2002 - 2006  Mantis Team   - mantisbt-dev@lists.sourceforge.net
	# This program is distributed under the terms and conditions of the GPL
	# See the README and LICENSE files for details
 
	# --------------------------------------------------------
	# $Id: $
	# --------------------------------------------------------
 
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'helper_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'utility_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'database_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'authentication_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'gpc_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'access_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'project_api.php' );
	require_once( dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'wiki_' . config_get( 'wiki_engine' ) . '_api.php' );
 
	# ----------------------
	# Calls a function with the specified name (not including prefix) and given the array
	# of parameters supplied.  An example prefix is "wiki_dokuwiki_".
	function wiki_call( $p_function, $p_args_array ) {
		$t_function = 'wiki_' . config_get_global( 'wiki_engine' ) . '_' . $p_function;
		return call_user_func_array( $t_function, $p_args_array );
	}
 
	# ----------------------
	# Checks if the Wiki feature is enabled or not.
	function wiki_is_enabled() {
		return config_get( 'wiki_enable' ) == ON;
	}
 
 	# ----------------------
	# Ensures that the wiki feature is enabled.
	function wiki_ensure_enabled() {
		if ( !wiki_is_enabled() ) {
			access_denied();
		}
	}
 
	# ----------------------
	# Gets the wiki URL for the issue with the specified id.
	function wiki_get_url_for_issue( $p_issue_id ) {
		return wiki_call( 'get_url_for_issue', array( $p_issue_id ) );
	}
 
	# ----------------------
	# Gets the wiki URL for the project with the specified id.  The project id can be ALL_PROJECTS.
	function wiki_get_url_for_project( $p_project_id ) {
		return wiki_call( 'get_url_for_project', array( $p_project_id ) );
	}
?>

wiki_dokuwiki_api.php

Create mantis/core/wiki_dokuwiki_api.php with the following content:

<?php
	# Mantis - a php based bugtracking system
	# Copyright (C) 2000 - 2002  Kenzaburo Ito - kenito@300baud.org
	# Copyright (C) 2002 - 2006  Mantis Team   - mantisbt-dev@lists.sourceforge.net
	# This program is distributed under the terms and conditions of the GPL
	# See the README and LICENSE files for details
 
	# --------------------------------------------------------
	# $Id: $
	# --------------------------------------------------------
 
	# ----------------------
	# Gets the URL for the page with the specified page id.  This function is used
	# internally by this API.
	function wiki_dokuwiki_get_url_for_page_id( $p_page_id ) {
		$t_root_url = config_get_global( 'wiki_engine_url' );
 
		$t_root_namespace = config_get( 'wiki_root_namespace' );
 
		if ( is_blank( $t_root_namespace ) ) {
			$t_page_id = $p_page_id;
		} else {
			$t_page_id = $t_root_namespace . ':' . $p_page_id;
		}
 
		return $t_root_url . 'doku.php?id=' . urlencode( $t_page_id );
	}
 
	# ----------------------
	# Gets the page id for the specified issue.  The page id can then be converted
	# to a URL using wiki_dokuwiki_get_url_for_page_id().
	function wiki_dokuwiki_get_page_id_for_issue( $p_issue_id ) {
		$c_issue_id = db_prepare_int( $p_issue_id );
 
		$t_project_id = bug_get_field( $p_issue_id, 'project_id' );
		$t_project_name = project_get_name( $t_project_id );
 
		# create a namespace for the project to contain all project documentation.
		# create within it a namespace for issues.  This is to allow the creation of a _template.txt
		# file to act as the template for issues belonging to this project.
		return $t_project_name . ':issue:' . $c_issue_id;
 
          # when using a different language you also could use the translation of 'issue' instead
          # but when working in a multilingual environment this will lead to different namespaces for each language 
          # (which may be intentional or not). Maybe one should make it configurable one day
 
          #    return $t_project_name . ':' . lang_get( 'bug' ) . ':' . $c_issue_id;   
 
	}
 
 	# ----------------------
	# Gets the page url for the specified issue id.
	function wiki_dokuwiki_get_url_for_issue( $p_issue_id ) {
		return wiki_dokuwiki_get_url_for_page_id( wiki_dokuwiki_get_page_id_for_issue( $p_issue_id ) );
	}
 
	# ----------------------
	# Gets the page id for the specified project.  The project id can be ALL_PROJECTS
	# The page id can then be converted to URL using wiki_dokuwiki_get_url_for_page_id().
	function wiki_dokuwiki_get_page_id_for_project( $p_project_id ) {
		$t_home = 'start';
		if ( $p_project_id == ALL_PROJECTS ) {
			return $t_home;
		} else {
			$t_project_name = project_get_name( $p_project_id );
			return $t_project_name . ':' . $t_home;
		}
	}
 
 	# ----------------------
	# Get URL for the specified project id.  The project is can be ALL_PROJECTS.
	function wiki_dokuwiki_get_url_for_project( $p_project_id ) {
		return wiki_dokuwiki_get_url_for_page_id( wiki_dokuwiki_get_page_id_for_project( $p_project_id ) );
	}
?>

html_api.php

Add the following with the rest of the includes:

require_once( $t_core_dir . 'wiki_api.php' );

In the print_menu() function, add the following code after the code which prints the Docs button (the block with the “Project Documentation Page” comment).

# Project Wiki
if ( wiki_is_enabled() ) {
	$t_current_project = helper_get_current_project();
	$t_menu_options[] = '<a href="wiki.php?type=project&id=' . $t_current_project . '">' . lang_get( 'wiki' ) . '</a>';
}

Add the following function:

# --------------------
# Print a button to create a wiki page
function html_button_wiki( $p_bug_id ) {
	if ( ON == config_get( 'wiki_enable' ) ) {
		if ( access_has_bug_level( config_get( 'update_bug_threshold' ), $p_bug_id ) ) {
			html_button( 'wiki.php',
						 lang_get_defaulted( 'Wiki' ),
						 array( 'id' => $p_bug_id, 'type' => 'issue' ),
						 'get' );
		}
	}
}

Update html_button() to the following implementation:

# --------------------
# 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 "<form method=\"$t_method\" action=\"$p_action\">\n";
 
	foreach ( $p_fields as $key => $val ) {
		$key = string_attribute( $key );
		$val = string_attribute( $val );
 
		PRINT "	<input type=\"hidden\" name=\"$key\" value=\"$val\" />\n";
	}
 
	PRINT "	<input type=\"submit\" class=\"button\" value=\"$p_button_text\" />\n";
	PRINT "</form>\n";
}

lang/strings_english.txt

Add the following at the end of the file but before the PHP end block (?>):

# wiki related strings
$s_wiki = 'Wiki';

wiki.php

Create wiki.php file in Mantis root folder:

<?php
	require_once( 'core.php' );
 
	$t_core_path = config_get( 'core_path' );
 
	require_once( $t_core_path . 'wiki_api.php' );
 
	$f_id = gpc_get_int( 'id' );
	$f_type = gpc_get_string( 'type', 'issue' );
	
	if ( $f_type == 'project' ) {
		project_ensure_exists( $f_id );
		$t_url = wiki_get_url_for_project( $f_id );
	} else {
		bug_ensure_exists( $f_id );
		$t_url = wiki_get_url_for_issue( $f_id );
	}
 
	print_header_redirect( $t_url );
?>

bug_view_*_page.php

Add the following code before the <td> tag that comes before the “<!– prev/next links –>” comment in both bug_view_page.php and bug_view_advanced_page.php.

<span class="small">
    <?php print_bracket_link( 'wiki.php?id='.$f_bug_id, lang_get( 'wiki' ) ) ?>
</span>
 
Logged in as: anonymous
mantisbt/issue/7075/integration_with_dokuwiki.txt · Last modified: 2009/12/13 19:33 by lvta0909
 
SourceForge Logo