Posted on

How to Quickly Integrate aMember and WordPressMU

AMember is a membership management application that can be integrated with many popular projects, including WordPress. However, I have found very little support for WPMU in the realm of member management software. I haven’t tried out many of the WordPress plugins, because I’m just not willing to fork over the cash to see if I can hack it enough to make it WPMU compatible. If anyone already has a popular paid plugin (ie Your Members, WP-member…), I’d be happy to take a swing at it.

I chose to start with aMember because I’ve already had experience writing aMember plugins. Before I started into a new aMember plugin for WordPressMU and BuddyPress, I did a quick Google search in hopes of finding the code was already written. Instead, I found a mass of disappointed and frustrated developers and managers. So I resorted to an entirely different method than other aMember plugins use. I simply incorporated all the base WordPress code into aMember, which gave me access to the WordPress hooks and functions. However, renaming two functions in aMember is required in order for this method to work. Although editing core code is not recommended, in this case I found it worth the time and headache it saved.

Step 1: Call the WordPress code.
Add these lines at the beginning of aMember’s config.inc.php:

if ( !defined( 'ABSPATH' ) && !defined( 'XMLRPC_REQUEST' )) {
define( 'WP_USE_THEMES', false );
include_once( '/absolute/path/wordpress/wp-config.php' );
$wp->init();
$wp->register_globals();
remove_action('init', 'wp_widgets_init');
}

You will need to replace ‘/absolute/path/wordpress/wp-config.php’ with the absolute path to that file.

Step 2: Rename duplicate functions.
UPDATE: This change has been made to the aMember core files as of version 3.2.0 (Aug-25-2010)
So far, I have come across two duplicate function/class names: validate_email and PHPMailer. I changed validate_email to validate_amember_email in three places: amember/admin/config.inc.php line 830, amember/admin/config_email.inc.php lines 239 and 245. It is also referenced in three default payment plugins that should be changed if you are using them: moneybookers, nochex, and stormpay. I changed PHPMailer to PHPMailerA on line 21 of amember/includes/phpmailer/class.phpmailer.php, line 62 of amember/admin/email_test.php, and line 1284 of amember/common.inc.php

Step 3: Add a Blog Title field to the aMember signup page
This is referenced below as $member[‘data’][‘blog_title’]

Step 4: Write your aMember plugin
Many of my functions are customized, so the ones listed here may not work for everyone. I didn’t take the time to add admin options either. I only tested this using subdomains. NOTE: not all functions are listed.

function subscription_added($member_id, $product_id, $member){
global $db, $wpdb;
$product = get_product($product_id);
if (!$product->config['wpmu_access'] and !$product->config['wpmu_level']) return;
$id = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_login = '$db->escape($member[login])'");
if (!$id){ //user not exists
$id = wpmu_create_user( $member['login'], $member['pass'], $member['email']);
update_usermeta($id, 'first_name', $member['name_f']);
update_usermeta($id, 'last_name', $member['name_l']);
//add blog
if ($member['data']['blog_title'] != '' ){
$blog_id = add_the_blog($id, $member['data']['blog_title']);
//wpmu_welcome_notification($blog_id, $id, $member['pass'], $member['data']['blog_title']);
}else{
//wpmu_welcome_user_notification($id, $member['pass']);
if ( get_site_option( 'dashboard_blog' ) == false )
add_user_to_blog( '1', $id, get_site_option( 'default_user_role', 'subscriber' ) );
else
add_user_to_blog( get_site_option( 'dashboard_blog' ), $id, get_site_option( 'default_user_role', 'subscriber' ) );
add_new_user_to_blog( $id, $member['email'] );
do_action('wpmu_activate_user', $id, $member['pass']);
}
}else{
$user = '';
$user->ID = $id;
$user->user_email = esc_html( trim( $member['email'] ));
$user->first_name = esc_html( trim( $member['name_f'] ));
$user->last_name = esc_html( trim( $member['name_l'] ));
$user->user_pass = esc_html( trim( $member['pass'] ));
wp_update_user( get_object_vars( $user ));
}
}

function add_the_blog($user_id,$title){
global $wpdb;
$primary_blog = get_usermeta($user_id, 'primary_blog');
switch_to_blog($primary_blog);
$primary_blog_role = get_usermeta($user_id, $wpdb->prefix . 'user_level');
if ($primary_blog == 1 || $primary_blog_role $description, 'lang_id' => 1, 'blog_public' => 1, 'public' => 1) );
$blog_title = substr( strip_tags( $title ), 0, 50 );
$blog_domain = get_unique_domain($blog_title);
$blog_id = wpmu_create_blog($blog_domain, '/', $blog_title, $user_id, $meta, 1);
}
restore_current_blog();
return $blog_id;
}

function get_unique_domain($blogname){
global $wpdb, $domain, $base;
$blogname = preg_replace( "/s+/", '', sanitize_user( $blogname, true ) );
$blogname = sanitize_title($blogname);
$blogname = apply_filters( "newblogname", $blogname );
$illegal_names = get_site_option( "illegal_names" );
$mydomain = "$blogname.$domain";
if (domain_exists($mydomain, $base) || in_array( $blogname, $illegal_names ) == true || strlen( $blogname ))
escape($oldmember['login']);
$id = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_login = '$old_login'");
$user = '';
$user->ID = $id;
$user->user_email = esc_html( trim( $newmember['email'] ));
$user->first_name = esc_html( trim( $newmember['name_f'] ));
$user->last_name = esc_html( trim( $newmember['name_l'] ));
$user->user_pass = esc_html( trim( $newmember['pass'] ));
wp_update_user( get_object_vars( $user ));
}

function subscription_removed($member_id, $member){
global $db, $wpdb;
$login = $db->escape($member['login']);
$id = $wpdb->get_var("SELECT ID from $wpdb->users WHERE user_login = '$login'");
require_once(ABSPATH . 'wp-admin/includes/mu.php');
wpmu_delete_user($id);
}

function subscription_check_uniq_login($login, $email, $pass){
global $db, $wpdb;
$login = $db->escape($login);
$q = $wpdb->get_row("SELECT user_pass, user_email FROM $wpdb->users WHERE user_login = '$login'");
$user_pass = $q->user_pass;
$user_email = $q->user_email;
if (!$user_pass && !$user_email) return true;
$user_name = preg_replace( "/s+/", '', sanitize_user( $login, true ) );
if ( username_exists($user_name) )
return false;

// Check if the email address has been used already.
if ( email_exists($email) )
return false;

if ($user_email != $email)
return false;
else
return true;
}

function after_login($user){
$credentials = array();
$credentials['user_password'] = $user['pass'];
$credentials['user_login'] = $user['login'];
$credentials['remember'] = false;
wp_signon( $credentials);
}

function after_logout(){
wp_logout();
}

Step 5: Make users sign in through aMember
The default BuddyPress theme has a login form in the header.php. I modified the form to submit to aMember. The variables at the top are for testing puposes. The commented out variables were the ones there by default.

<?php if ( !is_user_logged_in() ) : ?>
<?php $login_name = 'amember_login'; // 'log'
$login_id = 'a_login'; //'user_login
$pw_name = 'amember_pass'; //'pwd'
$pw_id = 'a_password'; //'user_pass'
$submit_id = 'amembersubmit'; //'wp-submit'
?>
<form name="login-form" id="login-form" action="/payments/login.php" method="post">
<input type="text" name="<?php echo $login_name ?>" id="<?php echo $login_id ?>" value="<?php _e( 'Username', 'buddypress' ) ?>" onfocus="if (this.value == '<?php _e( 'Username', 'buddypress' ) ?>') {this.value = '';}" onblur="if (this.value == '') {this.value = '<?php _e( 'Username', 'buddypress' ) ?>';}" />
<input type="password" name="<?php echo $pw_name ?>" id="<?php echo $pw_id ?>" class="input" value="" />
<input type="submit" name="<?php echo $submit_id ?>" id="<?php echo $submit_id ?>" value="<?php _e( 'Log In', 'buddypress' ) ?>"/>
<?php if ( 'none' != bp_get_signup_allowed() && 'blog' != bp_get_signup_allowed() ) : ?>
<input type="button" name="signup-submit" id="signup-submit" value="<?php _e( 'Sign Up', 'buddypress' ) ?>" onclick="location.href='<?php echo bp_signup_page() ?>'" />
<?php endif; ?>
<input type="hidden" name="redirect_to" value="<?php echo bp_root_domain() ?>" />
<input type="hidden" name="testcookie" value="1" />
<?php do_action( 'bp_login_bar_logged_out' ) ?>
</form>

<?php else : ?>
<div id="logout-link">
<?php bp_loggedin_user_avatar( 'width=20&height=20' ) ?>   <?php bp_loggedinuser_link() ?> / <?php bp_log_out_link() ?>
<?php do_action( 'bp_login_bar_logged_in' ) ?>
</div>
<?php endif; ?>

I also added a short WordPress plugin to redirect to the aMember login page for those who bypass the first login form displayed above, as well as replace the logout link sitewide. This is a sloppy version. You will need to replace the urls with the correct urls for your aMember setup. Don’t forget to add your admin user through aMember before activating the following code. Otherwise you will not be able to log in.

function switch_wp_to_amember_logout_url($logout_url, $redirect){
$logout_url = get_blog_option(1,'siteurl').'/payments/logout.php';
return $logout_url;
}
add_filter('logout_url', 'switch_wp_to_amember_logout_url', 10, 2);

function redirect_to_amember_login(){
if ($_SERVER["PHP_SELF"] == '/wp-login.php')
wp_redirect(get_blog_option(1,'siteurl').'/payments/member.php');
}
add_action('init','redirect_to_amember_login');

Step 6: Disable WPMU registrations
Make sure users sign up through aMember. In WPMU, go to Site Admin->Options, and set registrations to disabled. Make sure to add a new registration link to your aMember signup page.

The above steps have gotten aMember working well for me, but come with no guarantees. You can add more fields to the signup form or modify this code to whatever fits your needs. I also added the BuddyBar to my aMember template.

After spending two days writing this code, I came across a WordPress plugin called WishList Member. Word on the street is that it will do everything that aMember can, but in the form of a plugin to make setup, maintenance, and development much simpler, faster, and seamless. I will be testing it out today. Stay tuned for the results.