myCRED Hooks 101

Home / Tutorials / 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.

  1. Hey, thanks for this.

    A couple of questions though…

    1 – it suggests in the description that it will deduct points if the user removes their from the field, however it doesn’t do this. How would I add this function?

    2 – I (think) i can confidently add a second (and third etc) box to add points for filling out other fields, say for giving their website address. But as far as I can see it will always trip up at this point if the user has received points previously for filling their name out;

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

    How could I do a separate check for uniqueness without building an entirely separate hook?

    Look forward to hearing your response.

    Thanks!

    1. Hey MadeGood.

      Since the ‘personal_options_update’ and the ” hooks fire before the posted data is saved into the database, you could get the current user object in your hook and make comparisons i.e. if users first and last name is filled out in the current object but not in the posted information, then deduct points.

      You can use get_userdata() function to retreave the current user object. Example:

      $user = get_userdata( $user_id );
      if ( !empty( $user->user_url ) && empty( $_POST[‘url’] ) ) {
      // user has deleted their website url
      }

    1. WooCommerce comes with several actions that you can use to execute custom code.

      One example is the woocommerce_payment_complete action which fires once an order has been paid.
      Example:

      add_action( 'woocommerce_payment_complete', 'reward_users_purchase' );
      function reward_users_purchase( $order_id )
      {
      	// do your thing
      }
      

      I personally found this tutorial helpful.

    2. I tried to add this feature and it resulted in a fatal error message. May I get the full php for adding this option or would you please instruct me on adding it. Thank you.

    3. Please contact us though the “Contact” page with the error message you are receiving. It could that you did not copy the entire code or you pasted <?php inside <?php which will cause an error as well.

    1. Unless otherwise states, code snippets on this website always goes into your themes functions.php file.
      If you want to keep myCRED customizations in a separate file, then that file goes into your themes folder and you would need to include it via your themes functions.php file.

  2. Hello, i have a question.
    What if i want to execute my custom hook before (let’s say) the mycred login hook … what do i have to change ?

    Thanks in advance.

    1. Hi.

      Execute as in running the hook or do you want to insert your hook before another hook on the myCRED > Hooks page?
      Executing a custom hook before another hook does it’s thing can be accomplished by having a higher priority on your hook. So as an example, the Login hook has priority 10 for it’s hook into WordPress. If you want to execute your own code before this hook does, then your priority should be 9 or lower.

      If you on the other hand is looking to insert a hook before the core hooks, you would need to re-organize the hooks when you register yours by adjusting the array containing all the installed hooks.

  3. When working with multiple points types, how all these changes? Adding the point type in the add_creds functions is not working , and points are being duplicated

    1. The biggest change is in the class constructor which has now one more variable passing down the point type in question and you now have to make sure you use $this->core to get the myCRED_Settings class instead of using mycred(); in your hook. If you contact me by email I would be happy to help you out.

  4. Well I’m trying to create a hook that award users that make a transference I’m using the action ‘ mycred_transfer_completed ‘ for this hook. My hook is installed and enabled. But is not working, can you check my hook below, please. Also how can I set the amount awarded to the amount that the user has transfered? There’s a way to do that?

    [code removed – please use a pastebin or gist]

  5. Hi

    Sorry for bumping this post but I’m currently using a plugin called SportsPress Pro and I’m looking to create a custom hook where I can give points to players that play in a football/soccer match and have a status of Starting Lineup next to their player’s name.

    Any help with this would be very welcome 🙂

    Thanks

    AJ

  6. please anyone can help me, im using QAENGINE, i need to create a hook for best answe but i dont know how to know the name of the action in my qaengine plugin,

  7. Hello, I would like to create a Hook to punctuate an indication of registration by active users, that is, a new user register inform the email of the user that sent the indication and this receive a score. What bundles and classes can I use?

Leave a Reply

Last edited February 20, 2017