Category Archives: CubePoints

CubePoints Modules

Since writing this, development of the CubePoints plugin has slowed to a halt. So I’ve created my own points plugin, WordPoints. It also supports modules. Please give it a try!

 

The CubePoints plugin has some very nice features, and one of those is its modules. CubePoints modules allow you to extend the functionality of the CubePoints plugin. In this tutorial, we’ll take a look at some of the things that you can do with your own CubePoints modules.

What can a CubePoints Module do?

A CubePoints module can do anything that a WordPress plugin can do. The only difference is that is treated like it’s part of CubePoints, not a separate plugin. The main advantage of creating a custom CubePoints module as opposed to writing your own plugin, is that it keeps everything nice and organized. You are just extending the CubePoints plugin, not creating something completely new, so it is more intuitive to write a CubePoints module than to write a separate plugin. Having said that, the two are in most respects identical, so you could really do either.

Registering the Module

When you create your own module, the first thing that it needs to do is register itself with CubePoints. If you don’t, then the module won’t show up on the CubePoints->Modules page. This is done using the cp_module_register() function. This function takes 8 different parameters. It might look something like this:

cp_module_register(
	'My Module',
	'my_module',
	'1.0',
	'Me',
	'http://example.com/me/',
	'http://example.com/my-module/',
	'This is my own module that does my really cool stuff!',
	1
);

Now lets take a look at what each of these parameters is:

  1. The module’s name.
  2. The module’s slug.
  3. The version.
  4. The modules author.
  5. The module author’s URL
  6. The module’s URL
  7. The module’s description.
  8. Can the module be deactivated? (1 = yes, 0 = no)

That’s pretty simple, no? There’s just a couple things to remember. Notice that last parameter. CubePoints looks at this to see whether the module can be deactivated. If its value is 1, then the module can be activated and deactivated via the CubePoints->Modules page. But if you set it to 0, then the module will be activated automatically as soon as it’s installed, and if you try to deactivate it from the CubePoints->Modules page you will get the message: “This module cannot be deactivated through this page. To deactivate this module, remove it manually.”

Performing actions on Module Activation

Maybe you have some things that you want your module to do when it gets activated. Stuff it only needs to do once. Well, for that we do something like this:

function cp_module_my_module_install() {

	// Do stuff here
}
add_action( 'cp_module_my_module_activate', 'cp_module_my_module_install' );

We create a function to do whatever we need to do, and then hook it to the 'cp_module_*_activate' action hook. (Replace the * with your module’s slug). Now the function cp_module_my_module_install() will be run whenever the module is activated. It will also run if you change the module’s version (it will be run when the version changes, whether you increase or decrease it). Beware, that it will not run if your module can’t be deactivated. I guess since the module can’t be deactivated, it really can’t be activated either!

Module Content

Before we talk about what you can do with module, I need to note that the contents of your CubePoints module (except for the registration and activation functions) need to be wrapped in an if statement that checks that the module is actually active:

if ( cp_module_activated( 'my_module_slug' ) ) {

	// The module is activated! Do stuff here.
}

The cp_module_activated() function will check whether the module with that slug is active. If it is, then your module’s functions will get run. If it isn’t, we don’t want to run its functions!

The CubePoints functions

Here is an explanation of all of the most useful functions in CubePoints. These are the ones you are probably going to want to use in your custom module!

cp_currentUser()

You can use this function to get the ID of the current user. It doesn’t take any parameters, so can be called like this:

$current_user = cp_currentUser();
// $current_user now contains the current user's ID!

cp_getPoints()

This function is used to get the number of points a user has. It has only one parameter: a user’s ID. You might use it like this:

// Get the number of points for the user whose ID is 3.
$points = cp_getPoints( 3 );

cp_updatePoints()

You can use this function to update the number of points a particular user has. It takes two parameters: the user’s ID, and the number of points you want the user to have.

// Set user 3's 250 points.
cp_updatePoints( 3, 250 );

cp_alterPoints()

Use this function to alter the number of points a user has. The last function just set the users points to a certain amount, but this function will add (or subtract) a certain number of points from a user.

// Give user 3 ten points.
cp_alterPoints( '3', '10' );

// Subtract ten from user 3's points.
cp_alterPoints( '3', '-10' );

cp_formatPoints()

This function formats the points value with the prefix and suffix. (These are set on the plugin’s settings page.)

$formatted_points = cp_formatPoints( '150' );
// $formatted_points will now look something like '$150points'.

cp_displayPoints()

This function may be used to display the points of a given user. It takes three parameters:

  1. The ID of the user you want to get points for (or you can set this to 0 to display the points of the current user).
  2. Whether to return the points as a string or echo() them immediately (echo()‘s by default).
  3. Whether to format the points with the prefix and suffix (set to true by default).

Examples:

// We can call the function without passing any parameters.
cp_displayPoints();

// The points of the current user will be formatted with prefix and suffix and echo'ed to the browser.

// Or we can set some or all of the parameters.
$points = cp_displayPoints( 3, true, false );

// $points now contains the unformatted number of points for user 3.

cp_getAllPoints()

This function returns an array of information about each user. It takes up to three parameters:

  1. The upper limit to the number of users in the array. (Default: no limit)
  2. An array of user_login names to exclude.
  3. The lower limit to the number of users. (Default: 0)

cp_points()

This function alters the users points, and logs the transaction. It takes 4 parameters:

  1. The transaction type.
  2. The userID of the user who the transaction is affecting.
  3. The number of points to add to (or subtract from) the user’s points.
  4. The log data.

The log data is filtered into a transaction description, based on the transaction type.

// Give user 3 100 points.
cp_points( 'custom', 3, 100, 'Congratulations! You won 100 points!' );
	
// Take 100 points away from user 3.
cp_points( 'custom', 3, -100, 'Thank you for donating!' );

cp_points_set()

This function is the same as the last one, except rather than adding (or subtracting) a given number of points, it resets the user’s points to a given amount.

// Set user 3's points to 250
cp_points_set( 'custom', 3, 250, 'Now you have 250 points!' );

cp_getPostCount()

Get the the number of posts made by a user with a given ID.

// How may posts as user 3 created?
$posts = cp_getPostCount( 3 );

cp_getCommentCount()

Get the number of comments made by a given user.

// How many comments has user 3 created?
$comments = cp_getCommentCount( 3 );

Action hooks

Now lets look at some of the action hooks included with CubePoints, and how to use them.

cp_logs_desciption

You can use this to create your own transaction type, and filter for the log data.

function cp_my_logs_desc( $type, $uid, $points, $data ) {

	if ( $type != 'my_type' )
		return;

	// Filter the log data here.
}
add_action( 'cp_logs_description', 'cp_my_logs_desc', 10, 4 );

This allows you to pass a small piece of data to the when you log a transaction, and then use that data to create a transaction description when the logs are displayed. For example, maybe you want to give user’s points for uploading an image, and want to display the image they uploaded with the logs. You could create a transaction type called 'image_upload'. Then you could just pass the URL of the image as the description data. You could assemble your description, using the ‘cp_logs_description’ filter, something like this:

function cp_image_upload_desc( $type, $uid, $points, $data ) {

	// If it's not an image upload transaction, then we bail out.
	if ( $type != 'image_upload' )
		return;
	
	// Our description would look like 'Image Upload: (image here)'.
	echo( 'Image Upload: <img src="'. $data .'" max-width="20px" max-height="20px" />' );
}
add_action( 'cp_logs_description', 'cp_image_upload_desc', 10, 4 );

Of course, there’s many other things that you could do. This is just an example.

One of the good things about doing it this way, is that you can change exactly how you want your descriptions to look. Just edit your function. If you passed the whole description as the data, there would be no easy way to change it later!

cp_config_form & cp_config_process

You can use these to action hooks in your module to add your own options to the CubePoints->Configure page. cp_config_form lets you add your own inputs to the form, while cp_config_process lets you process the values submitted by the form. An example of their use is below. Basically what this does is let you update the values of any custom transaction types that you create, from the CubePoints->Configure page.

<?php

// Register the module
cp_module_register( __( 'My Module', 'cp' ) , 'my_module' , '1.0', 'Me', 'http://www.example.com', 'http://example.com/' , __( 'My own module!!', 'cp' ), 1 );

// On installation, we set the default values for our custom points transactions.
function cp_my_module_install() {

	add_option( 'cp_my_module_value1', 10 );
	add_option( 'cp_my_module_value2', 25 );
}
add_action( 'cp_module_my_module_activate', 'cp_my_module_install' );

// If the module is active.
if ( cp_module_activated( 'my_module' ) ) {

	// Add a function to display the form inputs.
	function cp_my_module_config() {

		?>

		<br />
		<h3>My Module Config Options</h3>
		<table class="form-table">
			<tr valign="top">
				<th scope="row">
					<label for="cp_my_module_value1">My Value 1:</label>
				</th>
				<td valign="middle">
					<input type="text" id="cp_my_module_value1" name="cp_my_module_value1" value="<?php echo( get_option( 'cp_my_module_value1' ) ); ?>" size="30" />
				</td>
			</tr>
			<tr valign="top">
				<th scope="row">
					<label for="cp_my_module_value2">My Value 2:</label>
				</th>
				<td valign="middle">
					<input type="text" id="cp_my_module_value1" name="cp_my_module_value1" value="<?php echo( get_option( 'cp_my_module_value1' ) ); ?>" size="30" />
				</td>
			</tr>
		</table>

	<?php

	}
	add_action( 'cp_config_form', 'cp_my_module_config' );

	// Create a function to process the form inputs when the form is submitted.
	function cp_my_module_config_process() {

		// We update the options with the submitted values. We cast them as integers.
		update_option( 'cp_my_module_value1', (int) $_POST['cp_my_module_value1'] );
		update_option( 'cp_my_module_value2', (int) $_POST['cp_my_module_value2'] );
	}
	add_action( 'cp_config_process', 'cp_my_module_config_process' );
}

It shouldn’t be too hard to follow that, but I’ll break it down for you anyway:

  • We register the module.
  • We set the default values for our custom transaction types.
  • The rest of the code is only performed when the plugin is active.
  • The first function creates a form table on the CubePoints->Configure page. The id and name attributes of the input tags must match the name of your option. Also, we echo() the current value as the value for the input. The labels could be whatever you want.
  • We create a function to save the values of the out options when the form is submitted.

All that you need to do know is hook your options to a particular action. For example, when a user makes a comment, submits a form, visits a page, or performs any action. Exactly how that happens will depend on what action you are trying to award/subtract points for.

Hooking into other plugins

Okay, now you know how all of the CubePoints functions work. The question is, how are you going to use them? Chances are, you want to award points for some actions user’s perform, that is enabled by another plugin (maybe a custom one you wrote for yourself). So how do you do that?

This is actually the difficult part. There isn’t just one answer; the answer will vary based on the particular situation. But as a general rule, you are probably going to need to hook into an action that the plugin performs; i.e. create a function and call it through some action hook. If that’s “Greek to you”, then keep reading, but realize you may be in above your head.

Here I am going to give a simple example, based on a module by Tosh Hatch, in which he integrated CubePoints with bbPress. The module lets you set the number of points to give user’s when the create a forum topic and when the reply to a topic. A portion of it is shown below.

<?php

// Create a function to call when a user makes a new bbPress topic.
function bbpress_cb_new_topic() {

	// We include the $current_user global.
	global $current_user;

	// We give the current user the number of points set by the custom option cp_bbpress_topic.
	cp_points( 'bbpress_cb_new_topic', $current_user->ID, get_option( 'cp_bbpress_topic' ), '' );
}

/* 
 * This is the really good part. We hook our new function to the bbp_new_topic
 * action, found in bbp-includes/bbp-topic-functions.php. Now each time a user 
 * creates a new topic, they are awarded the number of points that we have set with
 * the cp_bbpress_topic option.
 */
add_action( 'bbp_new_topic', 'bbpress_cb_new_topic' );


// Then we create a function to display the transaction description.
function bbpress_cb_new_topic_log( $type, $uid, $points, $data ) {

	if ( $type != 'bbpress_cb_new_topic' )
		return;
		
	echo 'New Forum Topic';
}
add_action('cp_logs_description','bbpress_cb_new_topic_log', 10, 4);


/*
 * We do the same thing for when a user created a reply. We hook into the
 * bbp_new_reply action found in bbp-includes/bbp-reply-functions.php
 */
function bbpress_cb_new_reply() {

	global $current_user;
	cp_points( 'bbpress_cb_new_reply', $current_user->ID, get_option( 'cp_bbpress_reply' ), '' );
}
add_action( 'bbp_new_reply', 'bbpress_cb_new_reply' );

// And we add a function for the logs descriptions.
function bbpress_cb_new_reply_log( $type, $uid, $points, $data ) {

	if( $type != 'bbpress_cb_new_reply' )
		return;
		
	echo 'New Forum Reply';
}
add_action( 'cp_logs_description','bbpress_cb_new_reply_log', 10, 4 );

Basically, if you want to give a user points for performing an action, you need to find an action hook that’s fired when the user does that, and then create a function like the ones shown above to hook into it. That means you are going to have to look through some code, and find the actions you want to hook into. If none exist where you need one, you might even have to add your own (which is pretty simple to do). Of course, if you created the plugin in the first place, then adding an action hook here and there should be no problem for you.

Conclusion

For those that know how, CubePoints modules are a powerful tool. Up to now, though, there has been very little documentation of how to build them. I hope that you have found this tutorial helpful, and if you have any questions, comments, or suggestions, please leave a comment below. I’d love to hear what you have to say!

How to Display the CubePoints Logs in bbPress User Profiles

I wanted to do create a page in the bbPress user profiles on which to display the CubePoints logs for the user, but I couldn’t find anything on Google about how to go about it. So I had to figure it out myself. Fortunately you don’t have to! It actually isn’t as hard as I though it might be.

Before we get started, let me say that this tutorial is based on bbPress 2.2.3, WordPress 3.5, and CubePoints 3.2.1 (the latest versions as of this writing). I have no idea whether this will work with older versions, but that’s no problem since you always install your updates (for security reasons if nothing else), right? RIGHT? Anyway, if anything changes in future versions I will try to remember to update this.

Also, you will need to install and activate my Front-end User Logs CubePoints module. You’ll find the code in this tutorial. Now lets get started!

Getting Started: Preparing a “Prettified” Link

Before we actually set up the page to display the points logs, we are going to prepare a “prettified” link for it. We can call the page “points”. The link for it will look something like "www.my-site.com/forums/users/someuser/points/" instead of "www.my-site.com/forums/users/someuser/?my_bbp_page=points" (though it might be a little different depending on your settings for the bbPress page slugs). This isn’t actually necessary, but it makes things… well, prettier. The code to do that looks like this:

<?php

/* Rewrite Rules */
function add_custom_rewrite_rules( $wp_rewrite ) 
{
	$new_rules = array(
		bbp_get_user_slug().'/([^/]+)/points/?$' => 'index.php?'.bbp_get_user_rewrite_id().'='.$wp_rewrite->preg_index(1).'&my_bbp_page=points',
	);

	$wp_rewrite->rules = $new_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_custom_rewrite_rules');

/* Query Vars */
function add_custom_page_variables( $vars ) {

	$vars[] = 'my_bbp_page';
	
	return $vars;
}
add_filter( 'query_vars', 'add_custom_page_variables' );

?>

That can go in either a custom plugin, or in your child theme’s functions.php. The function add_custom_rewrite_rules() adds our custom rewrite rule to those already registered with WordPress. That is what enables the pretty links. The function add_custom_page_variables() adds 'my_bbp_page' to the allowed query variables. We must do this, or else WordPress will ignore the 'my_bbp_page' parameter when passed. And we need to be able to pass that parameter, since that is what we’re going to use later to display the points page. We can now call for it like this:

$wp_query->query_vars['my_bbp_page']

But in order for the rewrite to work, you will need to flush WordPress’s rewrite rules. The simplest way to do that is to visit the Settings->Permalinks page in your WordPress dashboard. (Whenever you visit that page, WordPress flushes the rules automatically).

Creating Your Own bbPress Templates

Now that we have prepared our prettified link, we can start to build the custom page in the bbPress user profiles. We will do this by creating our own bbPress templates. Actually, we will only be modifying the default bbPress templates (if you are already using custom bbPress templates, then you will need to modify them instead). The bbPress plugin has a very nice feature built into it: you can create your own templates to override the default ones. So you don’t have to modify any of the bbPress code. You just need to create a folder named “bbpress” in your child theme’s directory (if you aren’t using a child theme, then now is the time to start!). Any template that you put in there will override the default templates included with bbPress (in /wp-content/plugins/bbpress/templates/default/bbpress/). We are going to need to modify two templates; user-profile.php, and user-details.php. You can copy those to the “bbpress” folder you created in your theme directory. Now bbPress will use those files instead of its own.

The user-profile.php Template

Let’s start with the user-profile.php bbPress template. This is the template that bbPress uses when it displays the “Profile” page on the user’s profile. (The default page that shows the user’s biography.) What we are going to do is modify this template so that it can also display the user’s points logs. We’ll place all of the code within an if/else statement, that will display the user’s points logs if the 'my_bbp_page' query_var is set to “points”, or else it will display the user’s biography. The code looks like this (though if you have already made some modifications to the template, it will look different, of course):

<?php

/**
 * User Profile
 *
 * @package bbPress
 * @subpackage Theme
 */

?>

<?php

/* Custom Pages */

// If the my_bbp_page parameter is set...
if ( !empty($wp_query->query_vars['my_bbp_page']) ) {

	// Get the current page.
	$my_bbp_page = $wp_query->query_vars['my_bbp_page'];

	/* Points Page */
	if ($my_bbp_page == 'points'){
		// Styles.
		echo '<style>#bbp-user-body,#cp_logs_table_wrapper,#cp_logs_table,#points-table-clear{clear:right !important;}</style>';
		// Display the user's points logs.
		cp_modules_frontlogs_display();
	}
	
} else {

	/* Default Profile Page */
?>
	<?php do_action( 'bbp_template_before_user_profile' ); ?>

	<div id="bbp-user-profile" class="bbp-user-profile">
		<h2 class="entry-title"><?php _e( 'Profile', 'bbpress' ); ?></h2>
		<div class="bbp-user-section">

			<?php if ( bbp_get_displayed_user_field( 'description' ) ) : ?>

				<p class="bbp-user-description"><?php bbp_displayed_user_field( 'description' ); ?></p>

			<?php endif; ?>

			<p class="bbp-user-forum-role"><?php  printf( __( 'Forum Role: %s',      'bbpress' ), bbp_get_user_display_role()    ); ?></p>
			<p class="bbp-user-topic-count"><?php printf( __( 'Topics Started: %s',  'bbpress' ), bbp_get_user_topic_count_raw() ); ?></p>
			<p class="bbp-user-reply-count"><?php printf( __( 'Replies Created: %s', 'bbpress' ), bbp_get_user_reply_count_raw() ); ?></p>
		</div>
	</div><!-- #bbp-author-topics-started -->

	<?php do_action( 'bbp_template_after_user_profile' ); ?>
<?php } ?>

We check if the 'my_bbp_page' query variable is set. If it is and its value is “points”, then we display the points logs. The styles echo‘ed there may not be necessary for you, but I had to use them to get it to display right. (You can fiddle around with it an see what styles you need.) Then all we need to do is call the cp_modules_frontlogs_display() function (from the Front-end User Logs CubePoints module) and it displays the table with the user’s points logs in it.

If 'my_bbp_page' wasn’t set, then we just do the default stuff (the code below /* Default Profile Page */).

As you can see, all of this could be easily expanded if desired, and you could add more pages to the bbPress user profiles.

The user-details.php Template

Now that we have prepared the page to display the points logs, we need to add a link to it from the navigation menu. The code for that is in the user-details.php bbPress template. By default this displays a link to the user’s subscriptions, favorites, etc., on the left side below the user’s avatar. If you aren’t using the default user-details.php template, then of course the code will look different. But the basic concept is the same. We want to add a link to the /points/ page. And if your template does anything to highlight the various links to indicate the current page (like the default one does), you will need to do that to (if you aren’t sure what I mean, then see the code below). If you are using the default template, then the new code will look something like this:

<?php

/**
 * User Details
 *
 * @package bbPress
 * @subpackage Theme
 */

?>

	<?php do_action( 'bbp_template_before_user_details' ); ?>

	<div id="bbp-single-user-details">
		<div id="bbp-user-avatar">

			<span class='vcard'>
				<a class="url fn n" href="<?php bbp_user_profile_url(); ?>" title="<?php bbp_displayed_user_field( 'display_name' ); ?>" rel="me">
					<?php echo get_avatar( bbp_get_displayed_user_field( 'user_email' ), apply_filters( 'bbp_single_user_details_avatar_size', 150 ) ); ?>
				</a>
			</span>

		</div><!-- #author-avatar -->

		<div id="bbp-user-navigation">
			<ul>
				<li class="<?php if ( bbp_is_single_user_profile() && empty($wp_query->query_vars['my_bbp_page']) ) :?>current<?php endif; ?>">
					<span class="vcard bbp-user-profile-link">
						<a class="url fn n" href="<?php bbp_user_profile_url(); ?>" title="<?php printf( __( "%s's Profile", 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>" rel="me"><?php _e( 'Profile', 'bbpress' ); ?></a>
					</span>
				</li>

				<li class="<?php if ( bbp_is_single_user_topics() ) :?>current<?php endif; ?>">
					<span class='bbp-user-topics-created-link'>
						<a href="<?php bbp_user_topics_created_url(); ?>" title="<?php printf( __( "%s's Topics Started", 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>"><?php _e( 'Topics Started', 'bbpress' ); ?></a>
					</span>
				</li>

				<li class="<?php if ( bbp_is_single_user_replies() ) :?>current<?php endif; ?>">
					<span class='bbp-user-replies-created-link'>
						<a href="<?php bbp_user_replies_created_url(); ?>" title="<?php printf( __( "%s's Replies Created", 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>"><?php _e( 'Replies Created', 'bbpress' ); ?></a>
					</span>
				</li>

				<?php if ( bbp_is_favorites_active() ) : ?>
					<li class="<?php if ( bbp_is_favorites() ) :?>current<?php endif; ?>">
						<span class="bbp-user-favorites-link">
							<a href="<?php bbp_favorites_permalink(); ?>" title="<?php printf( __( "%s's Favorites", 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>"><?php _e( 'Favorites', 'bbpress' ); ?></a>							
						</span>
					</li>
				<?php endif; ?>

				<?php if ( bbp_is_user_home() || current_user_can( 'edit_users' ) ) : ?>

					<?php if ( bbp_is_subscriptions_active() ) : ?>
						<li class="<?php if ( bbp_is_subscriptions() ) :?>current<?php endif; ?>">
							<span class="bbp-user-subscriptions-link">
								<a href="<?php bbp_subscriptions_permalink(); ?>" title="<?php printf( __( "%s's Subscriptions", 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>"><?php _e( 'Subscriptions', 'bbpress' ); ?></a>							
							</span>
						</li>
					<?php endif; ?>

					<li class="<?php if ( $wp_query->query_vars['my_bbp_page'] == "points") :?>current<?php endif; ?>">
						<span class="bbp-user-points-link">
							<a href="<?php bbp_user_profile_url(); ?>points/"><?php _e( 'Points', 'bbpress' ); ?></a>
						</span>
					</li>

					<li class="<?php if ( bbp_is_single_user_edit() ) :?>current<?php endif; ?>">
						<span class="bbp-user-edit-link">
							<a href="<?php bbp_user_profile_edit_url(); ?>" title="<?php printf( __( 'Edit Profile of User %s', 'bbpress' ), esc_attr( bbp_get_displayed_user_field( 'display_name' ) ) ); ?>"><?php _e( 'Edit', 'bbpress' ); ?></a>
						</span>
					</li>

				<?php endif; ?>

			</ul>
		</div><!-- #bbp-user-navigation -->
	</div><!-- #bbp-single-user-details -->

	<?php do_action( 'bbp_template_after_user_details' ); ?>

There are only two changes to the default code. The first is on line 27 where we change this:

				<li class="<?php if ( bbp_is_single_user_profile() ) :?>current<?php endif; ?>">

To this:

				<li class="<?php if ( bbp_is_single_user_profile() && empty($wp_query->query_vars['my_bbp_page']) ) :?>current<?php endif; ?>">

This is the code that adds the HTML class 'current' to the <li> element which contains the link for current page. That will make the link for the current page look different than the others, so you can easily see where you are. This particular piece of code does that for the ‘Profile’ page. This is the page that shows the user’s biography, the one whose template we modified so it could also display the points. All we do here is make sure that we are actually on the ‘Profile’ page, not displaying our custom points page. So we make sure that the 'my_bbp_page' query var is not set ( empty($wp_query->query_vars['my_bbp_page']) ). That way, the ‘Profile’ link won’t be highlighted as the current page when we are actually not displaying the profile, but the points.

The other change is on line 63, where we add the link to the points page:

					<li class="<?php if ( $wp_query->query_vars['my_bbp_page'] == "points") :?>current<?php endif; ?>">
						<span class="bbp-user-points-link">
							<a href="<?php bbp_user_profile_url(); ?>points/"><?php _e( 'Points', 'bbpress' ); ?></a>
						</span>
					</li>

We put that code within the if ( bbp_is_user_home() || current_user_can( 'edit_users' ) ) if statement, so that the link will only be shown to the user when they are logged in, and in their own profile area. Also, note the use of bbp_user_profile_url(), rather than hard-coding the link. This is so that our link will still work, even if the forum slugs change.

And that’s all there is to it. Note that I wrote all of this in a way that makes it easy to extend to create other custom pages for the bbPress user profiles, so you should be able to do that without much trouble. And since you seem to be interested in finding ways to integrate bbPress and CubePoints, maybe you should take a look at this CubePoints module, which allows you to award users points for creating posts in the bbPress forums.

How to Display CubePoints Logs on the Front End

Since writing this, development of the CubePoints plugin has slowed to a halt. So I’ve created my own points plugin, WordPoints. It offers a shortcode that you can use to display logs on the front end of your site. Please give it a try!

 

NOTE: The following tutorial is based on CubePoints 3.2.1 and WordPress 3.4.2 (the latest versions as of this writing). I will try to keep it updated if anything changes in future versions.

In this tutorial we will learn how to show a user a paginated list of recent points transactions from the logs on the front end of WordPress. The CubePoints plugin comes with this functionality already built in, for the admin area. All we have to do is bring it to the front end. We will give ourselves the option of doing it one of two ways:

  1. We can do it on any page or post using shortcode.
  2. Or, for those who are more WordPress savvy, we can also do it through an action hook.

(For those of you who don’t know PHP or WordPress, you may want to skip this explanation and just grab the finished code below.)

Getting Started: Understanding the Built-in Functionality

To get started, we need to first understand the functionality that CubePoints has already built-in. Otherwise we might end up doing a lot of extra work that the CubePoints developers have already done for us. For one thing, CubePoints is a modular plugin. That means that we don’t have to build our own plugin to do this, we just need a custom CubePoints module.

Creating a CubePoints Module

CubePoints modules are not too hard to understand, especially if you know a little about WordPress plugins. To create a CubePoints module, you need to create a new file in the CubePoints modules directory (/wp-content/plugins/cubepoints/modules/). You can name the file whatever you like, and in this case we might call it something like ‘frontend_logs.php’.

Inside the module file, the first thing the module needs to do is register itself, so that CubePoints knows that it exists. That code would look something like this:

<?php
/** Front-end Points Log */
cp_module_register(__('Front-end Points Logs', 'cp'), 'frontlogs', '1.0', 'J.D. Grimes',
   'http://efieldguide.com', 'http://efieldguide.com/how-to-display-cubepoints-logs-on-the-front-end',
   __('Allow users to see a history of their point transactions on the front end.', 'cp'), 1);
?>

Lets take a look at exactly what happens here. The comment (/** Front-end Points Log */) doesn’t really do anything, accept tell us the name of the module. The real meat of this, of course, is the cp_module_register() bit (this function is defined in /plugins/cubepoints/cp_core.php). As you can see, this function takes 8 parameters. Here is what each of them is:

  1. The name of the module (displayed on the CubePoints->Modules page)
  2. The module’s id or slug (the unique name of the module)
  3. The version of the module (displayed on the CubePoints->Modules page)
  4. The module’s Author (displayed on the CubePoints->Modules page)
  5. The module Author’s URL (used on the CubePoints->Modules page)
  6. The module’s URL (used on the CubePoints->Modules page)
  7. The module’s description (displayed on the CubePoints->Modules page)
  8. Whether the module can deactivate (1 = yes, 0 = no)

As you can see, parameters 1 and 7 are wrapped in WordPress’s __() function. This is not absolutely necessary, but it enables translation of the message into different languages, without directly editing the plugin files.

Using the cp_show_logs() Function

Now that we have registered our module, we need to add the code to enable front-end display of the points logs. As I noted above, CubePoints already has the ability to display the logs. All we need to do is bring that functionality to the front end. In order to do that, we need to understand how CubePoints does it. The code that shows a user their recent points transactions is in the My Points module which is included with CubePoints (/cubepoints/modules/my_points.php). If you have this module enabled, you can navigate to the CubePoints->My Points page on your WordPress Dashboard, and see your last 15 point transactions. Here is that module’s code:

<?php

/** My Points Module */

cp_module_register(__('My Points', 'cp') , 'mypoints' , '1.0', 'CubePoints', 'http://cubepoints.com', 'http://cubepoints.com' , __('Allow users to see a history of their point transactions.', 'cp'), 1);

if(cp_module_activated('mypoints')){

	add_action('admin_print_scripts-cubepoints_page_cp_modules_mypoints_admin', 'cp_datatables_script');
	add_action('admin_print_styles-cubepoints_page_cp_modules_mypoints_admin', 'cp_datatables_style');

	function cp_module_mypoints_add_admin_page(){
		add_submenu_page('cp_admin_manage', 'CubePoints - ' .__('My Points','cp'), __('My Points','cp'), 'read', 'cp_modules_mypoints_admin', 'cp_modules_mypoints_admin');
	}
	add_action('cp_admin_pages','cp_module_mypoints_add_admin_page');

	function cp_modules_mypoints_admin(){

		echo '<div class="wrap">';
		echo '<h2>CubePoints - ' . __('My Points', 'cp') . '</h2>';
		echo __('Manage and view information about your points.', 'cp');
		echo '<br /><br />';
		echo '<div style="background:#EFEFEF;display:inline-block;margin-right:25px;"><div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Points', 'cp') . ':</div><div style="float:left;padding:18px;font-size:20px;">' . cp_getPoints(cp_currentUser()) . '</div></div>';
		if(cp_module_activated('ranks')){
			echo '<div style="background:#EFEFEF;display:inline-block;"><div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Rank', 'cp') . ':</div><div style="float:left;padding:18px;font-size:20px;">' . cp_module_ranks_getRank(cp_currentUser()) . '</div></div>';
		}
		echo '<div style="clear:both;"></div><br />';
		
		echo '<p style="font-weight:bold;">' . __('Your recent point transactions:', 'cp') . '</p>';
		
		cp_show_logs(cp_currentUser(), 15 , false);
		
		echo '</div>';
	}
	
}
	
?>

It adds the CubePoints->My Points page, and on that page it displays a table with the last 15 points transactions for the current user. The part of this which is most important is on line 31:

cp_show_logs(cp_currentUser(), 15 , false);

This is the part that actually displays the point logs table. The declaration of the cp_show_logs() function is in /cubepoints/cp_logs.php. As you can see, the function takes three parameters. The first parameter is either 'all', meaning display the logs for all users, or the id of the specific user to show logs for, as in this case. The second parameter is the maximum number of transactions we want to display. In this case, we only display the last 15 logs. The third parameter tells CubePoints whether we want the results paginated or not. In this case, we are only displaying the 15 most recent transactions, so there is no need to paginate the tables.

This is the same function that is used in /cubepoints/cp_admin_logs.php to display all of the logs to the administrator. The only difference is that it uses different parameter values:

cp_show_logs('all', apply_filters('cp_admin_logs_limit', 0 ) , true);

In this case, CubePoints shows transaction logs for all of the users, so the first parameter is 'all'. The second parameter is 0. It is filtered through the 'cp_admin_logs_limit'. This enables compatibility with the Limit Logs Display module that comes with CubePoints, which allows administrators to define a limit to the number of logs displayed on the CubePoints->Logs page. And the third parameter is true, since we are displaying many logs, and want to paginate them.

In a moment we will learn how to use this function with a shortcode to display the logs on the front end of your site. But there is one thing we need to do first.

Bringing the JavaScript and CSS to the front end

The CSS styling is necessary for the tables to display properly. And without the JavaScript, the pagination will not work. The My Points module shown above, does that with this code:

add_action('admin_print_scripts-cubepoints_page_cp_modules_mypoints_admin', 'cp_datatables_script');
add_action('admin_print_styles-cubepoints_page_cp_modules_mypoints_admin', 'cp_datatables_style');

However, that will only work on the Admin side of the site. Here is the code we need to add these scripts to the front end:

       // Adding the necessary JS and CSS files to the front end.
       function cp_frontload_scripts(){
              wp_register_script('datatables', CP_PATH . 'assets/datatables/js/jquery.dataTables.min.js', array('jquery'), '1.7.4', true);
              wp_enqueue_script('datatables');
              wp_register_style('datatables', CP_PATH . 'assets/datatables/css/style.css');
              wp_enqueue_style('datatables');
       }
       add_action( 'wp_enqueue_scripts', 'cp_frontload_scripts' );

This code is based on the code from CubePoints itself, found in cp_admin.php. We can’t just enqueue the scripts, we have to actually register them, because CubePoints only registers them on the Admin side of the site. If you don’t know exactly what’s going on in this code, check out the WordPress Codex. Note that I have the final value of wp_register_script(‘datatables’) set to true. This causes the JavaScript to load at the bottom of the page. I did this because it wasn’t working properly when loaded in the <head>. I don’t know exactly why, perhaps because of a conflict with another script. Anyway, it only worked when loaded at the bottom for me, though I suggest you try setting that to false to see if it will load from the top for you.

Note that if you are only displaying the logs on one or two pages (and you probably are), you could add a conditional statement to only load the CSS and JS on those page(s). Something like if ( is_page($page) )  { /* add scripts here*/ } (see Codex)

Building a Function to Display the Logs

Now we have our CSS and JS ready, our points logs will display properly. We just need to build a function to display them. We can base it on the code from the My Points module above. But we can change it a little to give us the option to set each of the three parameters of the cp_show_logs() function. Then, we can either show all of the logs, or show just the logs for the current user with the same function. We can also specify any limit to the number of recent points transactions to display when we call the function, or ultimately in our shortcode. And we can also set whether we want to paginate the logs or not. This requires a few modifications, but is still fairly straightforward.

	function cp_modules_frontlogs_display($type = 'user', $limit = 0, $paginate = 1){

		echo '<style>.widefat{border-radius:3px 3px 3px 3px;border-width:1px;border-style:solid;border-spacing:0px;
				width:100%;clear:both;margin:0px;border-color:rgb(223,223,223);background-color:rgb(249,249,249);}</style>';
		echo '<div class="wrap"><div style="background:#EFEFEF;display:inline-block;margin-right:25px;">';
		
		if ($type == 'user'){
		
			if ( is_user_logged_in() ){

				echo '<div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Points', 'cp') . ':</div>
					<div style="float:left;padding:18px;font-size:20px;">' . cp_getPoints(cp_currentUser()) . '</div></div>';
		
				// If the 'ranks' module is activated...
				if(cp_module_activated('ranks')){
					echo '<div style="background:#EFEFEF;display:inline-block;">
						<div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Rank', 'cp') . ':</div>
						<div style="float:left;padding:18px;font-size:20px;">' . cp_module_ranks_getRank(cp_currentUser()) . '</div></div>';
				}
		
				echo '<div style="clear:both;"></div><br />';
				echo '<p style="font-weight:bold;">' . __('Your recent point transactions:', 'cp') . '</p>';
			
				$type = cp_currentUser();

			} else {
				echo '<p><b>'.__('You must be logged in to view your points.').'</b><p>';
				echo '</div>';
				return;
			}
			
		} elseif ($type == 'all') {
			$limit = apply_filters('cp_admin_logs_limit', $limit);
		}
		
		cp_show_logs($type, $limit , $paginate);
		
		echo '</div>';
	}
	add_action( 'cp_modules_show_logs_front_end', 'cp_modules_frontlogs_display' );

For clarity, the three parameters are:

  1. The type of log we want to display ('user' for current user only, 'all' for all users)
  2. The maximum number of logs to display (0 = no limit)
  3. Do we want the logs to be paginated? (1 = yes, 0 = no)

If we are loading the logs only for the current user ( if ($type == 'user') ), then we also want to show the user how many points they have. That is what the first if statement does. Inside of that we have to check if the user is logged in. If they aren’t, then we just give them a message that tells them they need to log in to view their points. At the bottom of that if statement, we also do $type = cp_currentUser(); to set the id of the user which we are displaying the logs for. On the other hand, if we are displaying all the logs, we want to filter the $limit through apply_filters('cp_admin_logs_limit', $limit); so that this module is compatible with the Limit Logs Display module. Finally, at the bottom we call the function to display the logs with whatever the parameters are, like this cp_show_logs($type, $limit , $paginate);.

We also have to add one more piece of CSS so that the table will display properly. That’s what this part does:

		echo '<style>.widefat{border-radius:3px 3px 3px 3px;border-width:1px;border-style:solid;border-spacing:0px;
				width:100%;clear:both;margin:0px;border-color:rgb(223,223,223);background-color:rgb(249,249,249);}</style>';

If you want to display the logs in a custom template, then you can do_action( 'cp_modules_show_logs_front_end' ), or if you want to pass parameters other than the default, you can simply call the function like this: cp_modules_frontlogs_display($type, $limit, $paginate). However, we could also do this with a shortcode on any post or page.

Creating the Shortcode

The next thing we need to do is create a function to handle the shortcode. That will look something like this:

function cp_modules_show_logs_shortcode( $atts ){
              extract( shortcode_atts( array(
                     'type' => 'user',
                     'paginate' => '1',
                     'limit' => '0',
              ), $atts ) );

              ob_start();
              cp_modules_frontlogs_display($type, $limit, $paginate);
              $html = ob_get_contents();
              ob_end_clean();

              return $html;
       }
       add_shortcode( 'cp_modules_show_logs', 'cp_modules_show_logs_shortcode' );

If you aren’t familiar with how to add WordPress shortcodes, here is a link to the Codex. All this function does is get any parameters that were set in the shortcode, and filters them through extract( shortcode_atts() ). Then we call the cp_modules_frontlogs_display($type, $limit, $paginate) function. But we need to call that function within PHP output buffering, so that the logs will appear in the right place on the page. If you are familiar with PHP output buffering, you know that this will catch everything that would have otherwise have been echo‘ed directly to the page. We turn output buffering on, execute cp_modules_frontlogs_display(), and then empty all of the stuff we caught into the $html variable, which we then return to WordPress to display on the page in place of the shortcode. Now you can include the shortcode in your WordPress pages and posts like this:

[cp_modules_show_logs]

Or with parameters:

[cp_modules_show_logs type="all" limit="15" paginate="0"]

And that’s all there is to it.

Conclusion

Putting all the code together, our module looks like this:

<?php

/** Front-end Points Log Module */

// Register the module.
cp_module_register(__('Front-end Points Logs', 'cp') , 'frontlogs' , '1.0', 'J.D. Grimes', 'http://efieldguide.com', 'http://efieldguide.com' , __('Allow users to see a history of their point transactions on the front end.', 'cp'), 1);

// If the module is active...
if(cp_module_activated('frontlogs')){
	
	// Adding the necessary JS and CSS files to the front end.
	function cp_frontload_scripts(){
		wp_register_script('datatables', CP_PATH . 'assets/datatables/js/jquery.dataTables.min.js', array('jquery'), '1.7.4', true);
		wp_enqueue_script('datatables');
		wp_register_style('datatables', CP_PATH . 'assets/datatables/css/style.css');
		wp_enqueue_style('datatables');
	}
	add_action( 'wp_enqueue_scripts', 'cp_frontload_scripts' );

	// Function to display the logs...
	function cp_modules_frontlogs_display($type = 'user', $limit = 0, $paginate = 1){

		echo '<style>.widefat{border-radius:3px 3px 3px 3px;border-width:1px;border-style:solid;border-spacing:0px;
				width:100%;clear:both;margin:0px;border-color:rgb(223,223,223);background-color:rgb(249,249,249);}</style>';
		echo '<div class="wrap"><div style="background:#EFEFEF;display:inline-block;margin-right:25px;">';
		
		if ($type == 'user'){
		
			if ( is_user_logged_in() ){

				echo '<div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Points', 'cp') . ':</div>
					<div style="float:left;padding:18px;font-size:20px;">' . cp_getPoints(cp_currentUser()) . '</div></div>';
		
				// If the 'ranks' module is activated...
				if(cp_module_activated('ranks')){
					echo '<div style="background:#EFEFEF;display:inline-block;">
						<div style="float:left;font-size:17px;font-weight:bold;background:#E0E0E0;padding:18px;color:#565656;">' . __('My Rank', 'cp') . ':</div>
						<div style="float:left;padding:18px;font-size:20px;">' . cp_module_ranks_getRank(cp_currentUser()) . '</div></div>';
				}
		
				echo '<div style="clear:both;"></div><br />';
				echo '<p style="font-weight:bold;">' . __('Your recent point transactions:', 'cp') . '</p>';
			
				$type = cp_currentUser();

			} else {
				echo '<p><b>'.__('You must be logged in to view your points.').'</b><p>';
				echo '</div>';
				return;
			}
			
		} elseif ($type == 'all') {
			$limit = apply_filters('cp_admin_logs_limit', $limit);
		}
		
		cp_show_logs($type, $limit , $paginate);
		
		echo '</div>';
	}
	add_action( 'cp_modules_show_logs_front_end', 'cp_modules_frontlogs_display' );

	// Function to add shortcode...
	function cp_modules_show_logs_shortcode( $atts ){
		extract( shortcode_atts( array(
			'type' => 'user',
			'paginate' => '1',
			'limit' => '0',
		), $atts ) );
		
		ob_start();
		cp_modules_frontlogs_display($type, $limit, $paginate);
		$html = ob_get_contents();
		ob_end_clean();
		
		return $html;
	}
	add_shortcode( 'cp_modules_show_logs', 'cp_modules_show_logs_shortcode' );
}

?>

Once you have saved that to a file in the /modules/ directory, you can go to your WordPress Dashboard, and navigate to CubePoints->Modules, and activate the Front-end Points Logs module that you just created. You can then display the logs on the front end using the shortcode, or, if you prefer, with a custom template.

Remember, I am not one of CubePoints’ developers, so I don’t know everything, and what you see here is just the product of a few hours of studying the plugin’s code. If you have any tips or find something I missed, please leave a comment and let me know.

Using the Cubepoints plugin API

Since writing this, development of the CubePoints plugin has slowed to a halt. So I’ve created my own points plugin, WordPoints. Please give it a try!

 

I searched the web, but I couldn’t find any documentation on how to use the built-in API for the WordPress CubePoints plugin. So I took a close look at the code (in the cp_api.php plugin file), and was able to figure it out. It’s actually really simple. Its a shame that there isn’t any documentation of it. The following is based on the latest version of CubePoints as of this writing (3.2.1) and I will try to update it in future if anything changes.

Step 1: Getting Your API Key

Using the API, you can get, update, or reset the points for any user. But in order to use the API, you first have to get your cp_api_key (AKA cp_auth_key). Without it, you can’t access the API. You already have a unique API key, that was generated when you installed the plugin. If you are planning to be using the API inside of the WordPress loop, such as in a custom plugin, you can get the key by simply calling for it in your PHP code, something like this:

<?php
$api_key = get_option('cp_auth_key');
?>

The PHP variable $api_key will now hold your API key. But this will only work if you are calling the script within WordPress. If what you are trying to achieve requires you to have the API key outside of the WordPress loop, then you can use get it using the CubePoints module below. Create a file called ‘api_key.php’ (or whatever you like) in the ‘/wp-content/cubepoints/modules/‘ folder. Copy and paste this code into it:

<?php
/** API Key Module */

cp_module_register(__('API Key', 'cp') , 'authkey' , '1.0', 'J.D. Grimes',
   'http://www.efieldguide.com', 'http://efieldguide.com/using-the-cubepoints-plugin-api/' ,
   __('This module displays your API key on the "Configure" page.', 'cp'), 1);

if(cp_module_activated('authkey')){

function cp_module_authkey_config(){
?>
<br />
<h3><?php _e('API Key','cp'); ?></h3>
<table>
<tr valign="top">
<th scope="row"><label for="cp_authkey"><?php _e('Your API key:', 'cp'); ?>:</label></th>
<td valign="middle"><?php echo get_option('cp_auth_key'); ?></td>
</tr>
</table>
<?php
}
add_action('cp_config_form','cp_module_authkey_config');
}
?>

Once you have saved the file, go to your WordPress dashboard, navigate to the CubePoints->Modules page, and activate the “API Key” module (the one that just created with the code above). Then you can visit the CubePoints->Configuration page, and you will see your API key displayed near the bottom, to the right of where it says “API Key”. Once you have your API key saved in a safe place, you can go back and deactivate the module, if you like.

Be very careful how you use the API key! Using it on the front end of your site will reveal it to your users, and anyone who knows how could change your user’s points any way that they want. Not only that, they can easily get lots of other info about your users, including their encrypted passwords. If you are thinking of integrating CubePoints with something on the front end, it would be much better, safer, and in the long run easier to use use a CubePoints module instead of doing it through the API. (See below).

 Step 2: Constructing the cp_api Parameter

Now that you have your API key, you can start accessing the API. But first you need to understand the second parameter, and how it works.

To use the API, you pass two parameters (your API key, and another string which we will explain in a moment) to your site like this:

http://www.your-site.com/?cp_api_key=Your_API_Key&cp_api=API_Action

(You can send these by either GET or POST method, but I’ll assume you will be using GET, since it is the usual method used with AJAX.) The 'cp_api_key' is your API key. The 'cp_api' is a second parameter that tells the CubePoints plugin what to do. This second parameter is actually up to 9 different parameters strung together, which the API script converts to an array. The delimiter used is the forward slash ‘/’. So this parameter looks something like this: 'cp_api=parameter1/parameter2/parameter3/parameter4/parameter5/...'

Here is an explanation of each (sub-)parameter:

Parameter 1

The first parameter is very easy, because there is only one possible value for it: 'user'. You might be thinking to yourself, “Why even have it if it is the only option? Isn’t that unnecessary?” Well, at first I thought that too, but I guess the developers of the CubePoints plugin where leaving room for the API to expand in the future. It’s possible that  in later versions there will be other options. But for now, your 'cp_api' will always start 'cp_api=user/'. This tells the API what sort of information we are dealing with: information regarding a particular user.

Parameter 2

We know from the first parameter, that we will be dealing with information regarding a particular user. What the API needs to know next, is what user we are dealing with. There are two different ways that you can tell the API this; 1) by passing the user’s id, or 2) by passing the user’s username (or “login”). But the API needs to know which you are using, and that is what this second parameter tells us. Its value is either 'id' or 'login', depending on whether you are using the user’s id or username. So the first two parameters of 'cp_api' will look like this:

cp_api=user/id/

Or this:

cp_api=user/login/

Which you use will depend on which of the two is more readily available. In my case, I will be using the userIDs.

Parameter 3

As might be deduced from parameter 2, the third parameter is the user’s id or username. If you were working with a user with id ‘5’ and username ‘billy’, the cp_api parameter would look like this:

cp_api=user/id/5/

Or this:

cp_api=user/login/billy/

Parameter 4

The fourth parameter tells the API what aspect of the user we are interested in. The expected value is 'points'. If this value is left blank, then the API will just return an array of the user’s information. But I assume the reason you are interested in the API is to manipulate the user’s points, so its safe to say that you will be passing this parameter most of the time. Your cp_api parameter would look something like this:

cp_api=user/id/5/points/

Parameter 5

Now that we’ve told the API what we are interested in (the points of a user with a specific id or username), we need to tell it what we want to do. There are three different actions that you can take: 'get', 'set', or 'add'. This is fairly straightforward. You either want to 'get' the number of points that the user has, or you want to 'set' the user’s points to a certain amount, or you just want to 'add' a certain number of points to what the user already has. If you don’t set this parameter, the API will assume that you want to 'get' the number of points that the user has (the other two possibilities require more parameters). Here’s what cp_api would look like:

To find out how many points billy has:

cp_api=user/login/billy/points/get/ (or cp_api=user/id/5/points/get/)

Parameter 6

Now we know how to tell the API what we want to do, but if we want to 'set' or 'add', we need to tell the API how many points to set the user’s points to, or how many points to add to the user’s points. That is what the sixth parameter does. (Note that you don’t need to pass this parameter if you are just 'get'ting.) Say we want to set billy’s points to 500. We would do this:

cp_api=user/login/billy/points/set/500 (or cp_api=user/id/5/points/set/500)

Now billy will have exactly 500 points. But what if we don’t want to reset billy’s points? What if we just want to give him 500 more points in addition to those he already has? We just use 'add' instead of 'set', like this:

cp_api=user/login/billly/points/add/500 (or cp_api=user/id/5/points/add/500)

If billy had 3105 points to start with, he will now have 3605. If we want to take 500 points away from billy, we can do that too:

cp_api=user/login/billy/points/add/-500

Now billy will have 3105 points again. (Note the minus sign.)

Parameter 7

CubePoints keeps logs of points transactions. Whenever someone’s points change, it gets logged in the database. The rest of the parameters tell the API how to log an 'add' transaction. If you don’t want your adjustment to be logged, then don’t pass the rest of the parameters. If you do want the transaction logged, then just pass the seventh parameter ('log'):

cp_api=user/id/5/points/add/500/log

 This will add the transaction to the logs, but it won’t tell the user anything about the transaction. For that, we need to use the next two parameters.

Parameters 8 and 9

The eighth parameter, when used, tells the API what type of description we want to log. (We tell it what the description should be with the ninth parameter.) There are many different options for the log 'type' built into CubePoints (see cp_hooks.php in /wp-content/plugins/cubepoints/), although others may be defined in any modules that you are using, and you can also create your own with a custom CubePoints module. What type you specify will depend on what sort of description you want for the transaction. Here is a list of the log transaction description types that come built-in, and how they handle the description data:

  • 'misc' – The description data is not processed.
  • 'addpoints' – The description data is not processed.
  •  'comment' – The description data will be a delimited string of different information about the comment, which is processed when the transaction is displayed in the log.
  • 'comment_remove' – Regardless of the description data, ‘Comment Deletion’ is displayed as the description.
  • 'post' – The description data will be a delimited string of different information about the post, which is processed when the transaction is displayed in the log.
  • 'register' – ‘Registration’ will be displayed.
  • 'admin' – ‘Points adjusted by “some_user”‘ (‘some_user’ will be the username of the user whose id is passed as the description data.)
  • 'remote' – ‘Points earned from “some_site”‘ (‘some_site’ will be a link created from the description data, ‘some_site^url’, where ‘url’ is the location of the link.)
  • 'custom' – The description data will not be processed.

As you can see, if you set parameter 8 to 'misc', 'addpoints' or 'custom', whatever you passed as the ninth parameter (the description data) will not be processed when the transaction logs are displayed to the user. It will be displayed ‘as is’. If you had a points donate button and wanted to give the description “Thank you for donating!”, you could do this:

cp_api=user/id/5/points/add/-500/log/custom/Thank+you+for+donating!

Depending on how you plan to use the API, you probably wont be using 'comment', 'comment_remove', 'post', or 'register'. I won’t be using them, and since I don’t think many others will, I wont take the time to explain them here. But some of you might be using the 'remote' or 'admin' transaction types, so I will explain how those work.

The 'admin' transaction type is used by CubePoints when the administrator arbitrarily adjusts someone’s points. It will show the transaction description ‘Points adjusted by “[an administrators username here]”‘. When using this description type, the description data is the adjuster’s userID (the username will not work here, only the userID). When the transaction is displayed in the logs, CubePoints will take the userID and get that user’s username. If it doesn’t find a user with that id, it will just show ‘Points adjusted by “”‘.

The 'remote' transaction type is apparently used when the user earns points from visiting a remote website. As with the ‘admin’ transaction type,  when this type is used, CubePoints processes the description data when it displays the transaction in the logs. But it is a little more complex. It has two parameters, joined by a ‘^’, like this ‘param1^param2’. The first parameter, is the name of the site. It will be used as the text for a link. The second parameter is the location of the link. So you might do something like this:

cp_api=user/id/5/points/add/500/log/remote/My+Site^http://www.mysite.com/

The log description for that transaction will be ‘Points earned from “My Site“‘.

In some situations, like mine, it is simplest to just use the 'custom' (or 'addpoints' or 'misc') type. But in some cases the other types might be useful. Note: If CubePoints doesn’t recognize the transaction type, then no transaction description will be displayed.

In some cases it may be necessary and/or easier to process the description data in some way (as is done in the ‘remote’ transaction type above). If you think that might be the case, you may want to create your own transaction type, and data processing methods. You can do that with your own CubePoints module, but that is currently beyond the scope of this tutorial.

 

Here is a list of the 9 parameters of cp_api, for your reference. Exact values are in quotes. A * means that the value is variable. A short explanation of each parameter is given in parentheses.

 

  1. 'user' (The type of data we are concerned with.)
  2. 'id', 'login' (The way we are passing the identity of the user we are interested in.)
  3. * (The user’s id or login name.)
  4. ”, 'points' (The type of information about the user we are interested in.)
  5. ”, 'get', 'set', 'add' (What action we want to take.)
  6. * (The number of points.)
  7. 'log' (We want to log this transaction.)
  8. * (The log type.)
  9. * (The log data.)

 

 Step 3: Understanding the API’s Returns

You now know how to construct a query to use the API. It might look something like this:

http://www.your-site.com/?cp_api_key=abc123&cp_api=user/login/billy/points/add/25/log/custom/Happy+Birthday!

But now you need to understand the API’s returns. Before I start on this explanation let me say that the CubePoints API, like many, returns JSON encoded objects and arrays, which can be handled with AJAX. The rest of this tutorial will assume that you have a working understanding of JavaScript, and JSON and AJAX in particular. If you don’t, then I suggest you visit W3Schools’ JSON and AJAX tutorials.

The API may return one or more of three different variables. These are 'error', 'points' and 'message'. If there is an error, for example, it will return the ‘error’ variable. It may have any one of the following values, depending on what the error was:

  • ‘Invalid API key’
  • ‘Method not implemented’
  • ‘Invalid user’
  • ‘Points must be integers’
  • ‘Log item must not be empty’

These are fairly straightforward, except perhaps for ‘Method not implemented’. That is returned if you have passed an unknown value for parameters 1, 2, 4, 5 or 7.

When the API doesn’t have an error, then the ‘points’ parameter is returned. Its value is the number of points that the user now has (calculated after any transaction has taken place). If the fifth parameter is 'set' or 'add', the 'message' will also be returned. At present, it has only one value: ‘Points updated’.

For the sake of completeness, an example of what a JavaScript function to add 10 points to a certain user when a button is clicked is seen below. The HTML behind it might look something like this:

<a onclick="addPoints('billy', '10')">Give billy 10 points</a>

The JavaScript function addPoints() might look something like this:

function addPoints(user,points,logData)
{
 // Generating the query...
 var url = '/?cp_api_key=abc123&amp;cp_api=user/id/'+userID+'/points/add/'+points+'/log/custom/'+logData;

 // Calling my_ajax() function (below) to perform the AJAX request.
 my_ajax(url, function(){
  // If the AJAX result is ready and the status is 200 (OK).
  if (xmlhttp.readyState==4 &amp;&amp; xmlhttp.status==200)
   {
      // We want to get the response...   
      var responseTxt = xmlhttp.responseText;
      // And convert the JSON objects to JavaScript objects.
      response = JSON.parse(responseTxt);
      // If there was an error...
      if (response.error){
         // We let ourselves know with an alert popup.
         alert('Error message: '+response.error);
      } else if (response.points) {
         // But if the query was successful, we give an alert popup with the 'message'.
         alert(response.message);
      } else {
         // Otherwise we got some unexpected response, and we give an alert popup like this:
         alert('Unknown server response: "'+responseTxt+'"');
      }
   } else if (xmlhttp.readyState==4) {
     // But if the AJAX is ready and the page didn't load OK...
     alert("Failed to connect to server.");
   }
 });
}

// This function will handle the AJAX call.
function my_ajax(URL, callback, async)
{
 if (window.XMLHttpRequest)
 {// code for IE7+, Firefox, Chrome, Opera, Safari
   xmlhttp=new XMLHttpRequest();
 } else {// code for IE6, IE5
   xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
 }

 xmlhttp.onreadystatechange=callback;

 if (async !== false){
   async = true;
 }
 xmlhttp.open("GET",URL,async);
 xmlhttp.send();
}

 

As you can see, when the button is clicked, the addPoints() function is executed. It builds the query from the variables passed to it, and then uses the my_ajax() function to submit the query via AJAX. It passes the generated URL and a callback function to my_ajax(). After the query has been executed, the function gives a JavaScript alert (like this), which either notifies you of the error, or gives you the success message. Of course, exactly how you handle the different returns will depend on your project.

Conclusion

Now you know how the CubePoints API works. The only question now is how will you use it? In my case, I had some forms that a user could submit. Then I review the submissions in the Dashboard, via a custom plugin. I needed some buttons that would let me accept or reject the submission, and adjust the user’s points based on that. The CubePoints API came to the rescue, and meant that I could do this easily through AJAX, without having to write my own PHP scripts to access the database and update the user’s points, create a log entry, etc. If what you want to achieve is similar to this, then the API will be very helpful for you. But if you are planing on using the API from the front end of your site, you probably should look into creating your own CubePoints module instead. Why? Because like I said above, the using the API on the front end will in most cases require you to use your API key somewhere in your code that would be visible to someone with the knowledge to look for it. And that is a very bad idea; its almost like revealing your password. Although there would be roundabout ways to avoid this, if you were going to go through all the trouble to implement them, you might as well have just created your own CubePoints module.

If you find this helpful let me know. Remember, I am NOT one of CubePoints’ developers, so I don’t know everything about the API. All you see here is the result of an hour of looking at the code behind the CubePoints plugin. If you learn anything in addition to what I’ve shared here, please leave a comment below. If I get time I may write a tutorial on building your own CubePoints module too, since that seems to be in need as well.