For a project of mine, I needed to bridge MODx with a forum (I wanted only one login for both). After some research and testing, I chose SMF, because it already includes some functions to do the bridge.
What I did is an embedded forum inside one page of MODx, called "forum", and users registration is made using SMF. Then they can login via MODx, and are automatically logged in SMF.
I thought I could share with you what I do.
By the way, I tried it using Revolution Alpha 5 and Alpha 6, and SMF 1.1.5 to 1.1.8.
I still have a few things I’m trying to fix, mostly regarding character encoding (which is a real pain in the ass), and I can’t guarantee this to be perfect, or even good. It just seems to fulfill my needs actually.
So this is completely Alpha, probably bad coded, no parameters, with patches to try to fix bugs, not sure this is the best way, but it might help someone and give a lead to do something really nice.
You’d have to create a snippet and call it in a page called forum (I use friendly urls)
Install SMF in a subfolder from your MODx root called SMF.
If you want, you can create placeholders : SMF_title in the title line on your template and SMF_header in your header section.
<?php
define('EOL', "\r\n");
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
//define the integration functions
define('SMF_INTEGRATION_SETTINGS', serialize(array(
'integrate_change_email' => 'change_email_function',
'integrate_change_member_data' => 'change_member_data_function',
'integrate_reset_pass' => 'reset_pass_function',
'integrate_exit' => 'exit_function',
'integrate_logout' => 'logout_function',
'integrate_outgoing_email' => 'outgoing_email_function',
'integrate_login' => 'login_function',
'integrate_verify_user' => 'verify_user_function',
'integrate_validate_login' => 'validate_login_function',
'integrate_redirect' => 'redirect_function',
'integrate_activate' => 'activate_function',
'integrate_fix_url' => 'fix_url_function',
'integrate_delete_member' => 'delete_member_function',
'integrate_register' => 'register_function',
'integrate_pre_load' => 'pre_load_function',
'integrate_whos_online' => 'whos_online_function',
)));
//pre_load_function() changes SMF settings
function pre_load_function()
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $mbname,$boardurl;
$modSettings['enableCompressedOutput'] = '0'; //Compressed Output needs to be disabled
$modSettings['localCookies'] = '0'; //Locally stored cookies need to be disabled
$modSettings['globalCookies'] = '1'; //Subdomain independent cookies need to be enabled
$modSettings['securityDisable'] = '1'; //Disable admin password
$modSettings['enableVBStyleLogin'] = '0'; //Disable quick login
$cookiename = session_name();//Set SMF Cookie the same as ModX
}
//verify_user_function() logs ModX user in SMF
function verify_user_function()
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx, $table_prefix;
if ($modx->getLoginUserName($modx->context->key))
{
$user= $modx->getUser();
$sql='SELECT ' . $db_prefix . 'members.ID_MEMBER FROM ' . $db_prefix . 'members INNER JOIN ' . $table_prefix . 'users ON ' . $db_prefix . 'members.memberName=' . $table_prefix . 'users.username WHERE ' . $table_prefix . 'users.id=' . $user->get('id');
mysql_connect($db_server, $db_user, $db_passwd);
mysql_select_db($db_name);
$reponse = mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
mysql_close();
return $donnees['ID_MEMBER'];
}
}
//logout_function() : user logs out from SMF -> log im out of ModX
function logout_function($username)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx;
$user = $modx->getObject('modUser', $modx->context->get('key'));
// invoke OnBeforeWebLogout event
$modx->invokeEvent('OnBeforeWebLogout',array(
'userid' => $user->id,
'username' => $user->username,
));
$modx->user->endSession();
// invoke OnWebLogout event
$modx->invokeEvent('OnWebLogout',array(
'userid' => $internalKey,
'username' => $username
));
}
//activate_function() : Activates the user in SMF -> activate him in ModX
function activate_function($username)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx, $table_prefix;
$sql='SELECT `id` FROM `' . $table_prefix . 'users` WHERE `username` = \'' . $username . '\'';
mysql_connect($db_server, $db_user, $db_passwd);
mysql_select_db($db_name);
$reponse = mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
mysql_close();
$user = $modx->getObject('modUser',$donnees['id']);
$user->profile = $user->getOne('modUserProfile');
$user->profile->set('blocked', false);
$user->profile->save();
}
//fix_url_function() : fix url for RSS feed
function fix_url_function($setLocation)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
if ($setLocation == '') $setLocation = '/forum.html';
$setLocation=str_replace('/smf/index.php?', '/forum.html?', $setLocation);
$setLocation=str_replace('/smf/index.php', '/forum.html', $setLocation);
return $setLocation;
}
//reset_pass_function() : user changes its password in SMF -> change it in ModX too
function reset_pass_function($oldusername, $newusername, $password)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx, $table_prefix;
$sql='SELECT `id` FROM `' . $table_prefix . 'users` WHERE `username` = \'' . $oldusername . '\'';
mysql_connect($db_server, $db_user, $db_passwd);
mysql_select_db($db_name);
$reponse = mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
mysql_close();
$user = $modx->getObject('modUser',$donnees['id']);
$user->profile = $user->getOne('modUserProfile');
$user->profile->set('fullname',$newusername);
$user->set('password',md5($password));
$user->profile->save();
$user->save();
}
//delete_member_function() : Delete the member in SMF -> delete him from ModX too
function delete_member_function($user_id)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx, $table_prefix;
$sql='SELECT ' . $table_prefix . 'users.id FROM ' . $db_prefix . 'members INNER JOIN ' . $table_prefix . 'users ON ' . $db_prefix . 'members.memberName=' . $table_prefix . 'users.username WHERE ' . $db_prefix . 'members.ID_MEMBER=' . $user_id;
mysql_connect($db_server, $db_user, $db_passwd);
mysql_select_db($db_name);
$reponse = mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
mysql_close();
$user = $modx->getObject('modUser',$donnees['id']);
if ($user == null) $error->failure($modx->lexicon('user_err_nf'));
// check if we are deleting our own record
if($user->id == $modx->getLoginUserID())
$error->failure($modx->lexicon('user_err_cannot_delete_self'));
// invoke OnBeforeUserFormDelete event
$modx->invokeEvent('OnBeforeUserFormDelete',array(
'id' => $user->id,
));
// get and delete all user group pairs
$user->groups = $user->getMany('modUserGroupMember');
foreach ($user->groups as $group)
$group->remove();
// get and delete user's profile
$user->profile = $user->getOne('modUserProfile');
$user->profile->remove();
// get and delete user's settings
$user->settings = $user->getMany('modUserSetting');
foreach ($user->settings as $setting)
$setting->remove();
// now finally remove user
if (!$user->remove()) $error->failure($modx->lexicon('user_err_remove'));
// invoke OnManagerDeleteUser event
$modx->invokeEvent('OnManagerDeleteUser',array(
'userid' => $user->id,
'username' => $user->username,
));
// invoke OnUserFormDelete event
$modx->invokeEvent('OnUserFormDelete',array('id' => $user->id));
}
//register_function() : registers user in SMF -> register him in ModX too
function register_function($regOptions, $theme_vars)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx;
$_POST['password'] = $regOptions['password'];
$_POST['email'] = $regOptions['email'];
$_POST['fullname'] = $regOptions['username'];
$_POST['username'] = $regOptions['username'];
$_POST['role'] = '1';
$_POST['login_context'] = 'web';
$user = $modx->newObject('modUser');
$user->set('username',$regOptions['username']);
$user->set('password',md5($regOptions['password']));
$user->save();
$user->profile = $modx->newObject('modUserProfile');
$user->profile->fromArray($_POST);
$user->profile->set('internalKey',$user->id);
$user->profile->set('blocked', true);
$user->profile->save();
}
//outgoing_email_function() : Fix Urls in mails
function outgoing_email_function($subject, &$message, $headers)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
if ($message == '') $message = '/forum.html';
$message=str_replace('/smf/index.php?', '/forum.html?', $message);
$message=str_replace('/smf/index.php', '/forum.html', $message);
return true;
}
/*
//change_member_data_function() : change user datas in SMF, change them in ModX too.
//Still to do
function change_member_data_function($memberNames, $var, $data)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
global $modx;
}
*/
//redirect_function() : fixes urls in SMF
function redirect_function(&$setLocation, $refresh)
{
global $modSettings,$forum_version, $time_start, $maintenance, $mtitle, $mmessage, $mbname, $language, $boardurl, $webmaster_email, $cookiename, $db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_persist, $db_error_send, $boarddir, $sourcedir, $db_last_error, $db_connection, $modSettings, $memcached, $cache_hits, $cache_count, $db_cache, $db_count, $board, $topic, $scripturl, $context, $HTTP_SESSION_VARS, $rand_code, $ban, $log_time, $timeOnlineUpdated, $old_url, $USER_AGENT, $login_SMFCookie922, $admin_time, $ID_MSG_LAST_VISIT, $unread_messages, $sc, $settings, $user_info, $user_settings, $ID_MEMBER, $txt, $board_info, $options, $db_show_debug, $language_dir, $forum_copyright;
if ($setLocation == '') $setLocation = '/forum.html';
$setLocation=str_replace('/smf/index.php?', '/forum.html?', $setLocation);
$setLocation=str_replace('/smf/index.php', '/forum.html', $setLocation);
}
function charset_decode_utf_8 ($string) {
/* Only do the slow convert if there are 8-bit characters */
/* avoid using 0xA0 (\240) in ereg ranges. RH73 does not like that */
if (! ereg("[\200-\237]", $string) and ! ereg("[\241-\377]", $string))
return $string;
// decode three byte unicode characters
$string = preg_replace("/([\340-\357])([\200-\277])([\200-\277])/e",
"'&#'.((ord('\\1')-224)*4096 + (ord('\\2')-128)*64 + (ord('\\3')-128)).';'",
$string);
// decode two byte unicode characters
$string = preg_replace("/([\300-\337])([\200-\277])/e",
"'&#'.((ord('\\1')-192)*64+(ord('\\2')-128)).';'",
$string);
$string=str_replace(' ', utf8_encode(' '), $string);
return $string;
}
array_walk($_POST, 'reslash_multi');
function reslash_multi(&$val,$key)
{
if (is_array($val)) array_walk($val,'reslash_multi',$new);
else {
$val = reslash($val);
}
}
function reslash($string)
{
$string = addslashes(charset_decode_utf_8($string));
return $string;
}
$here = getcwd();
ob_start();
chdir("smf/");
require "index.php";
$buffer = ob_get_contents();
ob_end_clean();
chdir($here);
if (!(isset($_GET['preview']) && (isset($_GET['xml']))))
{
$buffer=str_replace($txt['welcome_guest'], '', $buffer);
$buffer=str_replace('/smf/index.php', '/forum.html', $buffer);
$buffer=str_replace('/forum.html?action=helpadmin', '/smf/index.php?action=helpadmin', $buffer);
$buffer=str_replace('<input type="text" name="user" ', '<input type="text" id="SMFusername" name="user"', $buffer);
$buffer=str_replace('<input type="password" name="passwrd"', '<input type="password" id="SMFPassword" name="passwrd"', $buffer);
$buffer=str_replace('<input type="checkbox" name="cookieneverexp"', '<input type="checkbox" id="SMFremember" name="cookieneverexp"', $buffer);
$buffer=str_replace('<input type="submit" value="Login"', '<input id="SMFLoginRequest" type="submit" value="Login"', $buffer);
$buffer=str_replace('action="' . str_replace('\\','/',MODX_SITE_URL) . '/forum.html?action=login2"', '', $buffer);
$buffer=str_replace('<script language="JavaScript" type="text/javascript" src="' . str_replace('\\','/',MODX_SITE_URL) . '/smf/Themes/default/sha1.js"></script>', '', $buffer);
$buffer=preg_replace('`onsubmit="hashLoginPassword\(this, \'[a-z0-9]+\'\);"`m', '', $buffer);
$buffer=preg_replace('`<script\b[^>]*sha1.js\b[^>]*>(.*?)</script>`is', '', $buffer);
$buffer=preg_replace('`<form\b[^>]*action=login2\b[^>]*>(.*?)</form>`is', '', $buffer);
$buffer=preg_replace('`<td\b[^>]*maintab[^>]*>[^>]*<a\b[^>]*action=login\b[^>]*>(.*?)</a>[^<]*</td>`is', '', $buffer);
$test_flag=preg_match('`<head\b[^>]*>(.*?)</head>`is',$buffer, $html_head);
$test_flag=preg_match('`<title\b[^>]*>(.*?)</title>`is',$buffer, $html_title);
$test_flag=preg_match('`<body\b[^>]*>(.*?)</body>`is',$buffer, $html_body);
if (count($html_head)>0) $html_head[1] = preg_replace('`<title\b[^>]*>(.*?)</title>`is','',$html_head[1]);
if (count($html_head)>0) $modx->setPlaceholder('SMF_header',$html_head[1]);
if (count($html_title)>0) $modx->setPlaceholder('SMF_title',' - ' . $html_title[1]);
if (count($html_body)<1) $html_body[1]=$buffer;
return $html_body[1];
}
else
{
return $buffer;
}
?>
Comments and fixes are most welcome !!!