版权申明:本文为龙吟疯参照英语原文撰写(代码当然不是咯),任何机构或个人如需转载请先征得我的同意:ufoian@gmail.com,违反者将受到最大限度的追究。同时欢迎添加本文链接,永久链接地址:http://zhouyou.org/a/vanilla-wordpress/。
最近看到很多朋友在论坛上wordpress与vanilla怎么整合的问题,虽然有一篇官方教程,但一则是英文,二则写这篇文章的时间已经是几个世纪前的事情了,现在两者的版本都有所变化,给中文用户带来不少麻烦。龙吟疯通过对照英语原文,结合新版本特点写出了这个中文教程,希望对大家有所帮助。演示:http://zhouyou.org/ and http://zhouyou.org/bbs。
首先来介绍一下Vanilla,在英语中是”香草”的意思。这个程序兴起时间较wordpress短,特别是国内认知度还不高。但是并不影响她的强大。不是龙吟疯对国内的程序有意见,几年来DZ、PW在激烈的竞争中越来越强大,但令人遗憾的是他们并没有朝着我们希望的方向发展:功能越来越多也越来越华而不实,比如什么银行、QQ头像;风格越来越华丽却越发让人感觉浮躁;安装包越来越庞大而我也越怀念DZ4.0、PW2.23了… …也许这就是商业化的必然结局吧。
反观Vanilla,真是物如其名,她的安装包仅有386Kb,和WP一样,她的许多功能,都需要通过插件来实现,甚至包括编辑器(汗一个先!)。不过不用担心,几乎你想要的功能,都可以在官方网站下载,而且安装方式亦如Wp简单,有时我甚至在想:她就是为WP而生。Vanilla最大的特点当然就是简单了:她的首页显示的是近期发表的最新帖子而不是版块列表,这就非常适用于帖数不多但是质量较高的论坛(这句不是我的原话,谁说的我忘啦),特别适合个人网站和单纯的技术网站使用。曾经有人说:她是所有论坛中最具有2.0像的论坛。还有她默认的色彩配制,让人感到朴素和恬美,就像一位未施粉黛的水摆夷少女,看惯了国内论坛的浓妆艳抹,你也许会感叹:美,原来是可以这样的。
好啦,再说就肉麻啦,还以为我是Vanilla请的网特呢,言归正传:
你可以通过一下7步来整合Vanilla和Wordpress,虽然步骤较多但是并不复杂:
一、下载Vanilla和Wordpress,我下载的时候Wordpress是点点游2.2.3汉化版(最新的2.3我还没有弄过,哪位朋友如果照这个方法成功了麻烦在下面说一下),大家可以通过这里下载。至于Vanilla,这里给大家特别推荐一个版本(虽然我没有用这个安装包,但是看了一下,一样滴!),不仅包括简体中文语言包,而且还有各种常用插件,煎蛋真是个好同志,我们一起来喊:煎蛋好,好煎蛋。
二、当然是安装Vanilla和Wordpress了,怎么安装可以参考相关文章,这已经超出了本文的范围咯,有一点要注意的是二者必须安装在同一个数据库中。
三、修改Vanilla的配制文件,整合两者的用户数据。
大家打开Vanilla目录下的conf/database.php文件,这里要注意啦,在我们刚刚下载的安装包里面,是没有这个文件的,它是安装了Vanilla后自动生成的,所以我们要用FTP软件下载下来。在这个文件的最后(也就是在$DatabaseTables['User'] = ‘LUM_User’;这句话的下面)加上这样的语句[由于我的BLog没有使用PHP代码高亮插件,大家小心些看着,红色的就是代码]:
// Wordpress Integration
// =====================
// Map to the wordpress user table
$DatabaseTables['User'] = 'wp_users';
// Map existing wordpress columns to Vanilla
$DatabaseColumns['User']['UserID'] = 'ID';
$DatabaseColumns['User']['Name'] = 'user_login';
$DatabaseColumns['User']['Password'] = 'user_pass';
$DatabaseColumns['User']['Email'] = 'user_email';
$DatabaseColumns['User']['DateFirstVisit'] = 'user_registered';
// Also map the Wordpress columns into Vanilla
$DatabaseColumns['User']['user_nicename'] = 'user_nicename';
$DatabaseColumns['User']['user_url'] = 'user_url';
$DatabaseColumns['User']['user_activation_key'] = 'user_activation_key';
$DatabaseColumns['User']['user_status'] = 'user_status';
$DatabaseColumns['User']['display_name'] = 'display_name';
记得保存,上传。这代码的意思呢就是两者现在统一使用使用Wordpress的用户表来注册了。
四、升级数据库。大家进入数据库管理页面,运行如下两段SQL代码,将Vanilla的已有的用户添加到Wordpress:
CREATE TABLE `LUM_User` (
`UserID` int(10) NOT NULL AUTO_INCREMENT,
`RoleID` int(2) NOT NULL DEFAULT ‘0′,
`StyleID` int(3) NOT NULL DEFAULT ‘1′,
`CustomStyle` varchar(255) DEFAULT NULL,
`FirstName` varchar(50) NOT NULL DEFAULT ”,
`LastName` varchar(50) NOT NULL DEFAULT ”,
`Name` varchar(20) NOT NULL DEFAULT ”,
`Password` varchar(32) DEFAULT NULL,
`VerificationKey` varchar(50) NOT NULL DEFAULT ”,
`EmailVerificationKey` varchar(50) DEFAULT NULL,
`Email` varchar(200) NOT NULL DEFAULT ”,
`UtilizeEmail` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,
`ShowName` enum(’1′,’0′) NOT NULL DEFAULT ‘1′,
`Icon` varchar(255) DEFAULT NULL,
`Picture` varchar(255) DEFAULT NULL,
`Attributes` text NULL,
`CountVisit` int(8) NOT NULL DEFAULT ‘0′,
`CountDiscussions` int(8) NOT NULL DEFAULT ‘0′,
`CountComments` int(8) NOT NULL DEFAULT ‘0′,
`DateFirstVisit` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00′,
`DateLastActive` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00′,
`RemoteIp` varchar(100) NOT NULL DEFAULT ”,
`LastDiscussionPost` datetime DEFAULT NULL,
`DiscussionSpamCheck` int(11) NOT NULL DEFAULT ‘0′,
`LastCommentPost` datetime DEFAULT NULL,
`CommentSpamCheck` int(11) NOT NULL DEFAULT ‘0′,
`UserBlocksCategories` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,
`DefaultFormatType` varchar(20) DEFAULT NULL,
`Discovery` text,
`Preferences` text,
`SendNewApplicantNotifications` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,
PRIMARY KEY (`UserID`),
KEY `user_role` (`RoleID`),
KEY `user_style` (`StyleID`),
KEY `user_name` (`Name`)
第二段
ALTER TABLE wp_users
ADD `RoleID` int(2) NOT NULL DEFAULT '3',
ADD `StyleID` int(3) NOT NULL DEFAULT '1',
ADD `CustomStyle` varchar(255) DEFAULT NULL,
ADD `FirstName` varchar(50) NOT NULL DEFAULT '',
ADD `LastName` varchar(50) NOT NULL DEFAULT '',
ADD `VerificationKey` varchar(50) NOT NULL DEFAULT '',
ADD `EmailVerificationKey` varchar(50) DEFAULT NULL,
ADD `Email` varchar(200) NOT NULL DEFAULT '',
ADD `UtilizeEmail` enum('1','0') NOT NULL DEFAULT '0',
ADD `ShowName` enum('1','0') NOT NULL DEFAULT '1',
ADD `Icon` varchar(255) DEFAULT NULL,
ADD `Picture` varchar(255) DEFAULT NULL,
ADD `Attributes` text NULL,
ADD `CountVisit` int(8) NOT NULL DEFAULT '0',
ADD `CountDiscussions` int(8) NOT NULL DEFAULT '0',
ADD `CountComments` int(8) NOT NULL DEFAULT '0',
ADD `DateLastActive` datetime NOT NULL DEFAULT '2006-06-06 00:00:00',
ADD `RemoteIp` varchar(100) NOT NULL DEFAULT '',
ADD `LastDiscussionPost` datetime DEFAULT NULL,
ADD `DiscussionSpamCheck` int(11) NOT NULL DEFAULT '0',
ADD `LastCommentPost` datetime DEFAULT NULL,
ADD `CommentSpamCheck` int(11) NOT NULL DEFAULT '0',
ADD `UserBlocksCategories` enum('1','0') NOT NULL DEFAULT '0',
ADD `DefaultFormatType` varchar(20) DEFAULT NULL,
ADD `Discovery` text,
ADD `Preferences` text,
ADD `SendNewApplicantNotifications` enum('1','0') NOT NULL DEFAULT '0';
五、统一登录和注销。不能统一登录和退出那还叫整合吗?下面的设置可以帮助我们实现:
- 1, 新建一个文件并命名为People.Class.WordpressAuthenticator.php。
文件内容如下:
<?php
/*
* Copyright 2003 Mark O’Sullivan
* This file is part of People: The Lussumo User Management System.
* Lussumo’s Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
* Lussumo’s Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* The latest source code is available at www.lussumo.com
* Contact Mark O’Sullivan at mark [at] lussumo [dot] com
*
* Description: Default interface for user authentication. This class may be
* replaced with another using the “AUTHENTICATION_MODULE” configuration setting.
* Applications utilizing this file: Vanilla;
*/
class Authenticator {
var $Context;
var $WordpressSettingsRetrieved;
var $CookiePath;
var $SiteCookiePath;
var $CookieHash;
var $UserCookieName;
var $PassCookieName;
function AssignSessionData($user_login, $user_pass, $PersistentSession = ‘0′) {
$this->GetWordpressSettings();
$Expire = $PersistentSession ? time() + 31536000 : 0;
$user_pass = md5($user_pass); // Double hash the password in the cookie.
// Set the cookies
setcookie($this->UserCookieName, $user_login, $Expire, $this->CookiePath, false);
setcookie($this->PassCookieName, $user_pass, $Expire, $this->CookiePath, false);
if ($this->CookiePath != $this->SiteCookiePath ) {
setcookie($this->UserCookieName, $user_login, $Expire, $this->SiteCookiePath, false);
setcookie($this->PassCookieName, $user_pass, $Expire, $this->SiteCookiePath, false);
}
}
// This method is used in various places in Vanilla to sign someone into a session
function AssignSessionUserID($UserID) {
// Get the login_name and password for session assignment
$s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);
$s->SetMainTable(’User’, ‘u’);
$s->AddSelect(array(’Name’, ‘Password’), ‘u’);
$s->AddWhere(’u', ‘UserID’, ”, $UserID, ‘=’);
$Result = $this->Context->Database->Select($s,
‘WordpressAuthenticator’,
‘AssignSessionUserID’,
‘An error occurred while attempting to assign session data’);
if ($Result) {
$user_login = ”;
$user_pass = ”;
while ($rows = $this->Context->Database->GetRow($Result)) {
$user_login = ForceString($rows['Name'], ”);
$user_pass = ForceString($rows['Password'], ”);
}
$this->AssignSessionData($user_login, $user_pass);
}
}
// Returning ‘0′ indicates that the username and password combination weren’t found.
// Returning ‘-1′ indicates that the user does not have permission to sign in.
// Returning ‘-2′ indicates that a fatal error has occurred while querying the database.
function Authenticate($Username, $Password, $PersistentSession) {
// Validate the username and password that have been set
$Username = FormatStringForDatabaseInput($Username);
$Password = FormatStringForDatabaseInput($Password);
$UserID = 0;
$user_login = ”;
$user_pass = ”;
// Retrieve matching username/password values
$s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);
$s->SetMainTable(’User’, ‘u’);
$s->AddJoin(’Role’, ‘r’, ‘RoleID’, ‘u’, ‘RoleID’, ‘inner join’);
$s->AddSelect(array(’UserID’, ‘Name’, ‘Password’), ‘u’);
$s->AddSelect(’PERMISSION_SIGN_IN’, ‘r’);
$s->AddWhere(’u', ‘Name’, ”, $Username, ‘=’);
$s->AddWhere(’u', ‘Password’, ”, md5($Password), ‘=’, ‘and’, ”, 1, 1);
$s->AddWhere(’u', ‘Password’, ”, $Password, ‘=’, ‘or’);
$s->EndWhereGroup();
$UserResult = $this->Context->Database->Select($s,
‘WordpressAuthenticator’,
‘Authenticate’,
‘An error occurred while attempting to validate your credentials’);
if (!$UserResult) {
$UserID = -2;
} elseif ($this->Context->Database->RowCount($UserResult) > 0) {
$CanSignIn = 0;
$VerificationKey = ”;
while ($rows = $this->Context->Database->GetRow($UserResult)) {
$UserID = ForceInt($rows['UserID'], 0);
$user_login = ForceString($rows['Name'], ”);
$user_pass = ForceString($rows['Password'], ”);
$CanSignIn = ForceBool($rows['PERMISSION_SIGN_IN'], 0);
}
if (!$CanSignIn) {
$UserID = -1;
} else {
// Update the user’s information
$this->UpdateLastVisit($UserID);
// Assign the session value
$this->AssignSessionData($user_login, $user_pass, $PersistentSession);
// Log the person’s ip
$this->LogIp($UserID);
}
}
return $UserID;
}
function Authenticator(&$Context) {
$this->Context = &$Context;
$this->WordpressSettingsRetrieved = ‘0′;
$this->CookiePath = ”;
$this->SiteCookiePath = ”;
$this->CookieHash = ”;
}
function DeAuthenticate() {
if (session_id()) session_destroy();
$this->GetWordpressSettings();
setcookie($this->UserCookieName, ‘ ‘, time() - 31536000, $this->CookiePath, false);
setcookie($this->PassCookieName, ‘ ‘, time() - 31536000, $this->CookiePath, false);
setcookie($this->UserCookieName, ‘ ‘, time() - 31536000, $this->SiteCookiePath, false);
setcookie($this->PassCookieName, ‘ ‘, time() - 31536000, $this->SiteCookiePath, false);
return true;
}
function GetIdentity() {
$this->GetWordpressSettings();
// Examine the cookie values for session info
$login = ForceIncomingCookieString($this->UserCookieName, ”);
$pass = ForceIncomingCookieString($this->PassCookieName, ”);
$dbpass = ”;
$UserID = 0;
if ($login != ” && $pass != ”) {
$s = “select id, user_pass from wp_users where user_login = ‘”.FormatStringForDatabaseInput($login).”‘”;
$Result = $this->Context->Database->Execute($s,
‘WordpressAuthenticator’,
‘GetIdentity’,
‘An error occurred while attempting to retrieve session data.’);
if ($Result) {
while ($rows = $this->Context->Database->GetRow($Result)) {
$UserID = ForceInt($rows['id'], 0);
$dbpass = ForceString($rows['user_pass'], ”);
}
// If the double-md5d password doesn’t match the one in the cookie - don’t authenticate
if (md5($dbpass) != $pass) {
$UserID = 0;
}
}
}
else {
if (session_id()) session_destroy();
}
if (!session_id()) {
session_set_cookie_params(0, $this->CookiePath);
}
return $UserID;
}
function GetWordpressSettings() {
if ($this->WordpressSettingsRetrieved == ‘0′) {
$siteurl = ”;
$home = ”;
$s = “select option_name, option_value from wp_options where option_name = ’siteurl’ or option_name = ‘home’”;
$DataSet = $this->Context->Database->Execute($s,
‘WordpressAuthenticator’,
‘GetCookieName’,
‘An error occurred while retrieving cookie names.’);
if ($DataSet) {
while ($rows = $this->Context->Database->GetRow($DataSet)) {
if ($rows['option_name'] == ’siteurl’) {
$siteurl = ForceString($rows['option_value'], ”);
} else if ($rows['option_name'] == ‘home’) {
$home = ForceString($rows['option_value'], ”);
}
}
}
$this->CookiePath = preg_replace(’|https?://[^/]+|i’, ”, $home . ‘/’ );
$this->SiteCookiePath = preg_replace(’|https?://[^/]+|i’, ”, $siteurl . ‘/’ );
$this->CookieHash = md5($siteurl);
$this->UserCookieName = ‘wordpressuser_’.$this->CookieHash;
$this->PassCookieName = ‘wordpresspass_’.$this->CookieHash;
$this->WordpressSettingsRetrieved = ‘1′;
}
}
function LogIp($UserID) {
if ($this->Context->Configuration['LOG_ALL_IPS']) {
$s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);
$s->SetMainTable(’IpHistory’, ‘i’);
$s->AddFieldNameValue(’UserID’, $UserID);
$s->AddFieldNameValue(’RemoteIp’, GetRemoteIp(1));
$s->AddFieldNameValue(’DateLogged’, MysqlDateTime());
$this->Context->Database->Insert($s,
‘WordpressAuthenticator’,
‘LogIp’,
’An error occurred while logging your IP address.’,
false); // fail silently
}
}
function UpdateLastVisit($UserID) {
$s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);
$s->SetMainTable(’User’, ‘u’);
$s->AddFieldNameValue(’DateLastActive’, MysqlDateTime());
$s->AddFieldNameValue(’CountVisit’, ‘CountVisit + 1′, 0);
$s->AddWhere(’u', ‘UserID’, ”, $UserID, ‘=’);
$this->Context->Database->Update($s,
’WordpressAuthenticator’,
‘UpdateLastVisit’,
‘An error occurred while updating your profile.’,
false); // fail silently
}
保存好,上传到你的Vanilla安装目录下的library/People/下面。
2、找到Vanilla安装目录的conf/settings.php,下载下来,这个文件也和上面的/database.php一样:安装包里没有,是安装时自动生成的。打开它,在任何一个可以的地方加上下面这段话:
// Wordpress Authenticator
$Configuration['AUTHENTICATION_MODULE'] = ‘People/People.Class.WordpressAuthenticator.php’;
3、管理员用户的统一。进入数据库管理页面,运行SQl语句:
UPDATE wp_users SET RoleID = 4 WHERE id = 1
就此,同步登录退出及管理员都统一了。不管是Wordpress还是vaniila的老用户都可以畅游你的网站无阻了,但是还有一个小问题,那就是新用户注册的问题:Wordpress的用户表wp_users,不允许有空字段,因此如果在vaniila注册的新用户与Wordpress不兼容,那么怎么处理这个问题呢?在Vaniila官方的英文帮助文档上给出了两种方案,一是禁止在Vaniila注册:直接删除Vanilla的注册文件people.php,虽然简单,但是用起来不爽。下面就给大家介绍第二种方法:
六、新注册用户文件配置。
1、新建一个PHP文件,内容如下:
<?php
/*
Extension Name: Wordpress Integration
Extension Url: http://lussumo.com/docs/
Description: Makes it so that new users can be added via the Vanilla registration form and it won’t mess up the wordpress user table.
Version: 1.0
Author: Mark O’Sullivan
Author Url: http://markosullivan.ca/
*/
if ($Context->SelfUrl == ‘people.php’) {
function UserManager_AddWordpressFieldsToCreateUser(&$UserManager) {
$User = &$UserManager->DelegateParameters['User'];
$SafeUser = clone ($User);
$SafeUser->FormatPropertiesForDatabaseInput();
$s = &$UserManager->DelegateParameters['SqlBuilder'];
// Since Vanilla and Wordpress encode their passwords differently, I need
// to make Vanilla’s CreateUser method save it’s password in the same way.
// So, I’ll have to rebuild this sql object with the proper password.
$s->Clear();
$s->SetMainTable(’User’, ‘u’);
$s->AddFieldNameValue(’FirstName’, $SafeUser->FirstName);
$s->AddFieldNameValue(’LastName’, $SafeUser->LastName);
$s->AddFieldNameValue(’Name’, $SafeUser->Name);
$s->AddFieldNameValue(’Email’, $SafeUser->Email);
$s->AddFieldNameValue(’Password’, md5($SafeUser->NewPassword));
$s->AddFieldNameValue(’DateFirstVisit’, MysqlDateTime());
$s->AddFieldNameValue(’DateLastActive’, MysqlDateTime());
$s->AddFieldNameValue(’CountVisit’, 0);
$s->AddFieldNameValue(’CountDiscussions’, 0);
$s->AddFieldNameValue(’CountComments’, 0);
$s->AddFieldNameValue(’RoleID’, $UserManager->Context->Configuration['DEFAULT_ROLE']);
$s->AddFieldNameValue(’StyleID’, 0);
$s->AddFieldNameValue(’UtilizeEmail’, $UserManager->Context->Configuration['DEFAULT_EMAIL_VISIBLE']);
$s->AddFieldNameValue(’Attributes’, ”);
$s->AddFieldNameValue(’RemoteIp’, GetRemoteIp(1));
$s->AddFieldNameValue(’user_nicename’, $SafeUser->Name);
$s->AddFieldNameValue(’user_url’, ‘http://’);
$s->AddFieldNameValue(’user_activation_key’, ”);
$s->AddFieldNameValue(’user_status’, ‘0′);
$s->AddFieldNameValue(’display_name’, $SafeUser->Name);
}
$Context->AddToDelegate(’UserManager’,
‘PreDataInsert’,
‘UserManager_AddWordpressFieldsToCreateUser’);
}
将其命名为default.php,并放在一个名为WordpressIntegration的文件夹里,上传到你的Vanilla安装目录下的extensions/目录里。(extensions是Vanilla的插件目录,所有的插件都要放在里面——龙吟疯注)
2、到Vanilla后台设置里开启这个插件(这个时候你就要用Wordpress的管理账号登录了哦,因为刚才已经整合了嘛)。解决了新用户注册的问题。
七、还想要?没有啦。你的Vanilla已经和Wordpress完美整合了。哈哈,怎么样?是不是很有成功感?别忘了到下面回复一下哦,没事的时候来我的周游记(zhouyou.org)赠个IP,谢谢啦。
写的好。我以前也弄过,以后有什么问题就来你这里探讨探讨。呵呵。
好的,谢谢了。
我也是最近在网上转的时候发现VANILLA的.下了一下,感觉确实清爽.但我下的版本有个BUG,如果密码为空(一般是本机测试),那就会出现错误.
还没有真正玩.
如果密码为空(一般是本机测试),那就会出现错误.
是吗?那我倒还没有发现的。没有试过。
学习了!讲得很详细!
修改源代码太不友好了。
可以考虑用bbpress
修改源代码太不友好了。
可以考虑用bbpress。
其实只是涉及到增加代码,没有修改。
用过香草,正在用WP,但是因为买的虚拟主机是win2003+PHP的,所以觉得wp在这个环境下很多功能有问题,比如注册用户的邮件问题,但是香草对外部SMTP支持很完美!!我用的163的邮箱设置的,效果很好。
我现在的问题是,如果WP+香草,那么邮件系统和注册用户的管理,整合以后是香草的?还是WP的?谢谢。请邮件回复我。感激!
wp类型的真是太多了,弄的都有不足了
文章中错误百出。按照这个装法很难成功
不对啊,我都装成功了啊。你看看zhouyou.org/bbs