myCred Hooks 101

The code presented in this tutorial has been updated to bring support for multiple point types.

Description

In this tutorial, I will show you how to reward users for completing their profile using our very own custom hook.

The code snippets presented here should be placed in your theme’s functions.php file or in your plugin.

Requirements

  • myCred installed and setup
  • Basic understanding of the PHP language!

Hooks?

Hooks are instances where myCred might award or charge your user points. A hook can consist of a single instance like the “Points for Registrations” hook or multiple instances like the “Points for Comments” hook where you can award/deduct points for three different instances. You can have an unlimited amount of hooks and each hook can have an unlimited amount of instances, it’s all up to you.

Register Our Hook

The very first thing we will need to do is to register our hook. All hooks in myCred passes through the mycred_setup_hooks filter. You can use this filter to add your own hooks or remove / adjust any existing hooks.

<?php
add_filter( 'mycred_setup_hooks', 'register_my_custom_hook' );
function register_my_custom_hook( $installed )
{
	$installed['hook_id'] = array(
		'title'       => __( 'Hook Title', 'textdomain' ),
		'description' => __( 'Hook description', 'textdomain' ),
		'callback'    => array( 'Hook_Class' )
	);
	return $installed;
}
?>

Each hook needs are passed though with it’s unique id as key and an array as value. There are three values that must be set:

  • title required
    The Hooks Title as it will appear under myCred Hooks.
  • description required
    A hook description. This description will be shown in the accordions body and will be visible once the hook is selected.
  • callback required
    An array containing the Hook Class to call.

The myCred_Hook Class

The myCred_Hook class is an abstract class used by all myCred Hooks. It contains commonly used methods to help you build hooks without to much programming. Below we will create our hook class and extend it with the myCRED_Hook class.

<?php
if ( !class_exists( 'my_custom_hook_class' ) {
	class my_custom_hook_class extends myCRED_Hook {

	}
}
?>

Now that we have created our class we will need to add a few methods. Here are some of the most common:

  • __construct() required
    Class constructor. Will set the hooks id and apply default settings if not set.
  • run() required
    This method is called by myCred and will hold our actions / filters.
  • preferences() optional but recommended
    This method is called by myCred in the admin area and must be included if your hook has any settings.
  • sanitise_preferences() optional but recommended
    Sanitises the hooks preferences before they are saved in the database.

You can find a complete list of available methods on the myCred_Hook’s Codex entry.

Lets start Constructing

For this tutorial, we will award users who fill out their first and last name. The best hook for this would be the personal_options_update action which fires when users update their profile. But if an administrator updated a users profile we will also need to use the edit_user_profile_update action.

First, we will start by adding a constructor to our class where we will use the hook id of “complete_profile” and we will add two settings: the amount users are awarded/charged and the log template.

The constructor has two variables that we need to pass on to the parent constructor: $hook_prefs and $type. The $type variable was added in 1.4 and is required to give the hook multiple point type compatibility. Further more when using add_creds() anywhere in your hook, you must set the point type variable or the user will only receive points for the default point type and nothing else.

<?php
class my_custom_hook_class extends myCRED_Hook {

	/**
	 * Construct
	 */
	function __construct( $hook_prefs, $type ) {
		parent::__construct( array(
			'id'       => 'complete_profile',
			'defaults' => array(
				'creds'   => 1,
				'log'     => '%plural% for completing your profile'
			)
		), $hook_prefs, $type );
	}

	/**
	 * Hook into WordPress
	 */
	public function run() {
		// Since we are running a single instance, we do not need to check
		// if points are set to zero (disable). myCRED will check if this
		// hook has been enabled before calling this method so no need to check
		// that either.
		add_action( 'personal_options_update',  array( $this, 'profile_update' ) );
		add_action( 'edit_user_profile_update', array( $this, 'profile_update' ) );
	}

	/**
	 * Check if the user qualifies for points
	 */
	public function profile_update( $user_id ) {
		// Check if user is excluded (required)
		if ( $this->core->exclude_user( $user_id ) ) return;

		// Check to see if user has filled in their first and last name
		if ( empty( $_POST['first_name'] ) || empty( $_POST['last_name'] ) ) return;

		// Make sure this is a unique event
		if ( $this->has_entry( 'completing_profile', '', $user_id ) ) return;

		// Execute
		$this->core->add_creds(
			'completing_profile',
			$user_id,
			$this->prefs['creds'],
			$this->prefs['log'],
			0,
			'',
			$m
		);
	}
}
?>

So far we have constructed a hook which when enabled will give a user 1 point if they fill out their first and last name. Left like this, the default settings will be applied each time, but if we want to have the option to change this, we will need to add two more methods:

	/**
	 * Add Settings
	 */
	 public function preferences() {
		// Our settings are available under $this->prefs
		$prefs = $this->prefs; ?>

<!-- First we set the amount -->
<label class="subheader"><?php echo $this->core->plural(); ?></label>
<ol>
	<li>
		<div class="h2"><input type="text" name="<?php echo $this->field_name( 'creds' ); ?>" id="<?php echo $this->field_id( 'creds' ); ?>" value="<?php echo esc_attr( $prefs['creds'] ); ?>" size="8" /></div>
	</li>
</ol>
<!-- Then the log template -->
<label class="subheader"><?php _e( 'Log template', 'mycred' ); ?></label>
<ol>
	<li>
		<div class="h2"><input type="text" name="<?php echo $this->field_name( 'log' ); ?>" id="<?php echo $this->field_id( 'log' ); ?>" value="<?php echo esc_attr( $prefs['log'] ); ?>" class="long" /></div>
	</li>
</ol>
<?php
	}

	/**
	 * Sanitize Preferences
	 */
	public function sanitise_preferences( $data ) {
		$new_data = $data;

		// Apply defaults if any field is left empty
		$new_data['creds'] = ( !empty( $data['creds'] ) ) ? $data['creds'] : $this->defaults['creds'];
		$new_data['log'] = ( !empty( $data['log'] ) ) ? sanitize_text_field( $data['log'] ) : $this->defaults['log'];

		return $new_data;
	}

As you can see we start of by adding our two preference fields taking advantage of field_name() and field_id(). Since some use decimals in their points system, we also use format_number() here to make sure we always present values according to our setup.

We also sanatize our settings by making sure there is always an entered value. If either preference fields are empty we use our defaults. Remember to always return what was given to you otherwise you will cause an error. (Errors = Bad)

Done

There you have it. Add this code to your themes functions.php file or include it in your plugin and you have yourself a brand new custom myCred Hook. I have included the code in it’s entirety on the next page and should you have any problems or questions, feel free to post them below.

Note! The way we check if a user has filled out their first and last name is not the ideal way of course. You should add some further checks e.g. checking the length, otherwise a single character in both fields would result in points being awarded.

11