DokuWiki

It's better when it's simple

User Tools

Site Tools


Sidebar

Translations of this page?:

Learn about DokuWiki

Advanced Use

Corporate Use

Our Community


Follow us on Facebook, Twitter and other social networks.

tips:integrate_with_smf

SMF Integration

This is a little bridge between DokuWiki and the Simplemachines Forum Software (1.1 RC2).First, the configuration to use the SMF user data and groups (IIRC that has been done before). Then a little template-level code, to allow the use of the forum to discuss wiki pages. This is done by automagically creating a topic when an user clicks on the “discuss” button. The bridge part is experimental, feedback would be much appreciated.

Steps

  • Configure dokuWiki to use the SMF users and groups
  • Create a Board in SMF to hold the discussions
  • Configure the bridge
  • Adapt the template

Requirements

  • A working installation of SMF
  • A working installation of dokuWiki

Using the Auth System

A fully functional way to integrate the authorization system of DokuWiki with SMF database described here:

The original author's method

:!: This method willn't work with non-ASCII usernames

This code assumes that the SMF tables in the database have the prefix “smf_”. You will also have to configure acl2.

$conf['openregister']= 0;                //Should users to be allowed to register?
 
$conf['useacl']      = 1;                //Use Access Control Lists to restrict access?
$conf['superuser']   = '@Administrator'; // admin group is superuser
$conf['authtype']    = 'mysql';
 
$conf['auth']['mysql']['server']   = 'localhost';              // mySQL host, usually localhost
$conf['auth']['mysql']['database'] = 'smf';          // mySQL database that is used by SMF
$conf['auth']['mysql']['user']     = '';     // mySQL database user for   SMF
$conf['auth']['mysql']['password'] = '';    // mySQL database password for  SMF
 
$conf['auth']['mysql']['forwardClearPass'] = 1;
$conf['defaultgroup']                      = 'user';
$conf['auth']['mysql']['checkPass']= "SELECT memberName AS name 
                                      FROM smf_members
                                      WHERE memberName = '%{user}'
                                      AND passwd = SHA1( CONCAT( LOWER(memberName), '%{pass}' ) ) ";
 
//SMF stores realnames, but for login purposes the username is the way to go.
$conf['auth']['mysql']['getUserInfo'] = "SELECT passwd AS pass, memberName AS name, emailAddress AS mail
                                        FROM smf_members
                                        WHERE memberName='%{user}'";
//Workaround for a MySQL Bug.
$conf['auth']['mysql']['getGroups']   = "SELECT CONVERT( '".$conf['defaultgroup']."'
					USING latin1 )
					COLLATE latin1_general_ci AS `group`
					UNION 
					SELECT REPLACE( g.groupName, ' ', '_' ) AS `group`
					FROM smf_membergroups g, smf_members u
                                        WHERE (
                                          g.ID_GROUP = u.ID_GROUP
                                        OR (
                                          FIND_IN_SET(g.ID_GROUP , u.additionalGroups)
                                        )
                                        )
                                        AND u.memberName='%{user}'";

This uses the SMF groups for the ACL system. However, whitespaces in the group names will be replaced with underscores.

Alternatives

:!: This method also willn't work with non-ASCII usernames

There is a community-developed SMF auth module for less experienced users. see this thread for discussion

Setting up the Bridge

This is about setting up the discuss add-on. The add-on is hooked into the template, hence it is somewhat limited.

First, it needs a new table in the SMF database to link Wiki to discussions (not vice-versa).

CREATE TABLE `wiki_discussions` (
`ID_MSG` MEDIUMINT( 10 ) NOT NULL ,
`ID_TOPIC` MEDIUMINT( 8 ) NOT NULL ,
`page` VARCHAR( 50 ) NOT NULL ,
PRIMARY KEY ( `page` ) ,
UNIQUE (
`ID_MSG` ,
`ID_TOPIC`
)
)

Then, create a new subdirectory 'discuss' in your template's dir. (example: “dokuwiki/lib/tpl/default/discuss”).

In that new dir, copy this into a file “smf_discuss.php”

<?php
 
/*
A small script to  allow the creation of Discussion  topics in an SMF.
By hsudhof
 
 
To install, first create a table:
CREATE TABLE `wiki_discussions` (
`ID_MSG` MEDIUMINT( 10 ) NOT NULL ,
`ID_TOPIC` MEDIUMINT( 8 ) NOT NULL ,
`page` VARCHAR( 50 ) NOT NULL ,
PRIMARY KEY ( `page` ) ,
UNIQUE (
`ID_MSG` ,
`ID_TOPIC`
)
 
Then, configure the MySQL conncetion.
 
Now you can adopt youtr template to include the discuss link.
 
Finally, configure the add-on in smf_config.php
*/
 if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__)).'/../../../../');
 
require_once(DOKU_INC.'inc/init.php');
require_once(DOKU_INC.'inc/common.php');
 
require_once DOKU_INC.'inc/auth/mysql.class.php';
$db = new auth_mysql();
 
$conf['smf'] =array();
include_once("smf_config.php");
 
if (isset($_GET['discuss'])){
	global $ID, $INFO, $info;
	require_once(DOKU_INC.'inc/auth.php');
	require_once(DOKU_INC.'inc/template.php');
 
	$page = $_GET['discuss'];
 
	$ID = $page;
	$INFO = pageinfo();
	//$INFO['perm']= auth_aclcheck($page,'Test',null);
 
	if (!discussion_exists($page))
	{
		create_discussion($page);		
	}
	$topic_id =get_discussion_id($page);
	//echo 'Location: http://'.$conf['smf']['location']."index.php?topic=$topic_id"."\n";
 
	header('Location: http://'.$conf['smf']['location']."index.php?topic=$topic_id");
	exit;
 
}
 
 
/**
 * Create Link
 *
 * Returns a String to create a link leading to the discussion topic. Does not print the string on its own.
 *
 * @author   hsudhof
 * @param    string $name The  text
 * @returns  string the HTML for a link
 */
function get_discussion_link($name1){
	global  $INFO, $ID, $conf, $db;
 
	 $ret = '<a href="'.DOKU_TPL.'discuss/smf_discuss.php?discuss='.$ID.'">';	
 
	 return $ret.$name1.'</a>';
 
}
 
/**
 * Create Button
 *
 * Returns a String to create a button leading to the discussion topic. Does not print the string on its own.
 *
 * @author   hsudhof
 * @param    string $name The button text
 * @returns  string theHTML for a form 
 */
function get_discussion_button($name){
	global  $INFO, $ID, $con, $db;
	require_once(DOKU_INC.'inc/common.php');
	$ret = '<form class="button" method="get" action="'.DOKU_TPL.'discuss/smf_discuss.php"><div class="no">';
	$ret .= '<input type="hidden" name="discuss", value="'.$ID.'"/> ';
	$ret.= '<input type="submit" value="'.htmlspecialchars($name).'" class="button" accesskey="d"/></div></form>';
 
 
 
	return $ret;
}
 
 
/**
 * Check for existence
 *
 * Checks if there is an entry in the database for the given page.
 *
 * @author   hsudhof
 * @param    string $page The page to discuss
 * @returns  bool true, if there is an entry in the database,
 */
function discussion_exists($page){
	global  $conf, $db;
 
	$page = addslashes($page);
	$db->_openDB();
	$sql = "SELECT * FROM wiki_discussions WHERE page LIKE '$page'";
 
	$result = $db ->_queryDB($sql);
 
	$db->_closeDB();
 
	return $result != null;
}
 
 
 
/**
 * Creates Discussion
 *
 * Inserts a new topic in the SMF database. Does not update board stats, nor manual search tables.
 *
 * @author   hsudhof
 * @param    string $page The page to discuss
 * @returns  void
 */
function create_discussion($page){
	global $db, $INFO, $conf, $ID;
	$page= addslashes($page); //This goes into the database: be careful.
	if($INFO['perm'] >= AUTH_EDIT)
	{
		$db->_openDB();
		$board_id = $conf['smf']['wikiboard'];
		$topic_id = 0;
		$member_id = $conf['smf']['wikibotid'];
		$subject = $conf['smf']['topic_title'].': '. $page;
		$link = 'http://'.$_SERVER['SERVER_NAME'].'/'.$conf['smf']['wiki_path'].'/doku.php?id='.$ID ; //Problem: we did not start out from doku.php, hence all constants are off.
		$body = $conf['smf']['wikibody'] . $link;
		$poster_name   = $conf['smf']['wikibotname'];
		$poster_email  = $conf['smf']['wikibotmail'];
		$poster_time  = time();
		$poster_ip  = '127.0.0.1';
 
		$modified_name ='';
 
		// First insert the post
		$post_sql  = "INSERT INTO ".$conf['smf']['table_prefix']."messages
			(ID_BOARD, ID_MEMBER, subject, body, posterName, posterEmail, posterTime,	posterIP, modifiedName)
			VALUES ($board_id ,$member_id, '$subject', '$body', '$poster_name', '$poster_email', $poster_time, '$poster_ip','')";
 
 
		$post_id = $db->_modifyDB($post_sql );
 
		//then the topic
		$topic_sql = "INSERT INTO ".$conf['smf']['table_prefix']."topics
				(ID_BOARD, ID_MEMBER_STARTED,  ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG)
				VALUES ($board_id, $member_id, $member_id, $post_id, $post_id )";
 
 
		$topic_id = $db->_modifyDB($topic_sql );
 
		//update the post
		$post_sql2  = "UPDATE ".$conf['smf']['table_prefix']."messages
			SET ID_TOPIC = $topic_id
			WHERE ID_MSG = $post_id
			LIMIT 1	";
 
		//and finally leave a note about what was done
		$db->_modifyDB($post_sql2 );
		$wikisql= "INSERT INTO wiki_discussions 
					(ID_MSG, ID_TOPIC, page)
					VALUES
					($post_id, $topic_id, '$page')";
 
 
		$db->_modifyDB($wikisql);
		$db->_closeDB();
	}
}
 
 
 
 
/**
 * Returns the topic id of the  discussion
 *
 * If the page has an entry in the discussion table, this function will return the associated topic ID. 
 * The check for the existence has to be done before calling this function. If the topic is not found, the function will remove the entry from the database and redirect to the Wiki.
 *
 * @author   hsudhof
 * @param    string $page The page to discuss
 * @returns  Int: the id, or 0(false)
 */
function get_discussion_id($page){
	global $db, $INFO, $conf;
 
	$page = addslashes($page);
	$db->_openDB();
	$sql = "SELECT d.ID_TOPIC as topic FROM wiki_discussions d LEFT JOIN ".$conf['smf']['table_prefix']."topics t ON d.ID_TOPIC = t.ID_TOPIC WHERE page = '$page' LIMIT 1";
	$result = $db ->_queryDB($sql);
	if (!$result){ //oopsie: somebody deleted our topic. Let's clean up the database.
		$wikisql= "DELETE FROM wiki_discussions WHERE page LIKE'$page'";
		$result = $db ->_queryDB($sql);		 
		$db->_modifyDB($wikisql);
		$db->_closeDB();
		header("location: $HTTP_REFERER");
		exit;
	}
 
	return $result[0]['topic'];
 
	$db->_closeDB();
	return $result != false;
}
 
 
?>

And your configuration like this in “smf_config.php”:

<?php
/**
The Config and Language Keys for the SMF bridge.
 
*/
$conf['smf']['wikiboard']    = 2;                                   //The SMF board to hold the discussions
$conf['smf']['wikibotid']    = 0;                                   //The Wiki posts as guest (can post as an user)
$conf['smf']['wikibotname']  = 'wikibot';                           //the name to display
$conf['smf']['wikibotmail']  = '';                                  //enter your email addy here
$conf['smf']['table_prefix'] = 'smf_';                              //prefix of the smf tables in the database (uses the auth config)
$conf['smf']['location']     = 'www.yourhost.com/smf/';             //to assemble links to your SMF board. (can use $_SERVER.)
$conf['smf']['topic_title']  = 'Wiki';                              //Topic title to use. Remember to escape quotes for the database.
$conf['smf']['wikibody']     = 'The Wiki-Page can be found at: ';   //Text for inside the topic. Remember to escape quotes for the database.
$conf['smf']['wiki_path']    = 'dokuwiki';                          //path to doku.php
?>

Finally, it is time to adapt your template:

//This inserts a button 
<?php include_once('discuss/smf_discuss.php'); echo get_discussion_button('Discuss');?>
 
//and this a link.
<?php include_once('discuss/smf_discuss.php');echo get_discussion_link('Discuss'); ?>

Update about non-ASCII usernames

Unfortunatelly, this method doesn't work with non-ASCII logins in SMF database because of incorrect work of PHP function strtolower() with utf8 strings.

To fix this problem you can use auth module from here:

Or you need to change checkPass request to this one:

$conf['auth']['mysql']['checkPass']= "SELECT memberName AS name 
                                      FROM smf_members
                                      WHERE memberName = '%{user}'
                                      AND passwd = '%{encpass}' ";

And modify DokuWiki auth file inc/auth/mysql.class.php. You should add two strings to function checkPass so it should begin with:

function checkPass($user,$pass){
      $rc  = false;
 
      $encpass = sha1(strtolower($this->_escape($user)) . $this->_escape($pass));
 
      if($this->_openDB()) {
        $sql    = str_replace('%{user}',$this->_escape($user),$this->cnf['checkPass']);
        $sql    = str_replace('%{pass}',$this->_escape($pass),$sql);
        $sql    = str_replace('%{encpass}',$encpass,$sql);
        $sql    = str_replace('%{dgroup}',$this->_escape($this->defaultgroup),$sql);
        $result = $this->_queryDB($sql);
 
...

Comments

I have gotten this to work successfully with SMF 1.1.11 and Dokuwiki (2009-12-25c).
- Antoris, Leader of Legacy of Hdoe Clan Consortium LoH Website

tips/integrate_with_smf.txt · Last modified: 2010-10-16 12:00 by Malamut