LLMS_Engagements
Engagements Class
Description Description
Source Source
File: includes/class.llms.engagements.php
class LLMS_Engagements { /** * Enable debug logging * @var boolean * @since 2.7.9 */ private $debug = false; /** * protected instance of class * @var null */ protected static $_instance = null; /** * Create instance of class * @return object [Instance of engagements class] */ public static function instance() { if ( is_null( self::$_instance ) ) { self::$_instance = new self(); } return self::$_instance; } /** * Constructor * Adds actions to events that trigger engagements */ private function __construct() { if ( defined( 'LLMS_ENGAGEMENT_DEBUG' ) && LLMS_ENGAGEMENT_DEBUG ) { $this->debug = true; } $this->add_actions(); $this->init(); } /** * Register all actions that trigger engagements * * @return void * * @since 2.3.0 * @version 3.11.0 */ private function add_actions() { $actions = apply_filters( 'lifterlms_engagement_actions', array( 'lifterlms_access_plan_purchased', 'lifterlms_course_completed', 'lifterlms_course_track_completed', 'lifterlms_created_person', 'lifterlms_lesson_completed', 'lifterlms_product_purchased', 'lifterlms_quiz_completed', 'lifterlms_quiz_passed', 'lifterlms_quiz_failed', 'lifterlms_section_completed', 'llms_user_enrolled_in_course', 'llms_user_added_to_membership_level', ) ); foreach ( $actions as $action ) { add_action( $action, array( $this, 'maybe_trigger_engagement' ), 777, 3 ); } add_action( 'lifterlms_engagement_send_email', array( $this, 'handle_email' ), 10, 1 ); add_action( 'lifterlms_engagement_award_achievement', array( $this, 'handle_achievement' ), 10, 1 ); add_action( 'lifterlms_engagement_award_certificate', array( $this, 'handle_certificate' ), 10, 1 ); } /** * Include engagement types (excluding email) * @return void */ public function init() { include( 'class.llms.certificates.php' ); include( 'class.llms.achievements.php' ); } /** * Award an achievement * * This is called via do_action() by the 'maybe_trigger_engagement' function in this class * * @param array $args indexed array of args * 0 => WP User ID * 1 => WP Post ID of the email post * 2 => WP Post ID of the related post that triggered the award * * @return void * * @since 2.3.0 */ public function handle_achievement( $args ) { $this->log( '======== handle_achievement() =======' ); $this->log( $args ); $a = LLMS()->achievements(); $a->trigger_engagement( $args[0], $args[1], $args[2] ); } /** * Award a certificate * * This is called via do_action() by the 'maybe_trigger_engagement' function in this class * * @param array $args indexed array of args * 0 => WP User ID * 1 => WP Post ID of the email post * 2 => WP Post ID of the related post that triggered the award * * @return void * * @since 2.3.0 */ public function handle_certificate( $args ) { $this->log( '======== handle_certificate() =======' ); $this->log( $args ); $c = LLMS()->certificates(); $c->trigger_engagement( $args[0], $args[1], $args[2] ); } /** * Send an email engagement * * This is called via do_action() by the 'maybe_trigger_engagement' function in this class * * @param array $args indexed array of args * 0 => WP User ID * 1 => WP Post ID of the email post * 2 => WP Post ID of the triggering post * @return void * * @since 2.3.0 * @version 3.8.0 */ public function handle_email( $args ) { $this->log( '======== handle_email() =======' ); $this->log( $args ); $person_id = $args[0]; $email_id = $args[1]; $related_id = $args[2]; // dupcheck global $wpdb; $res = (int) $wpdb->get_var( $wpdb->prepare( " SELECT count( meta_id ) FROM {$wpdb->prefix}lifterlms_user_postmeta WHERE post_id = %d AND user_id = %d AND meta_value = %d LIMIT 1 ;", array( $related_id, $person_id, $email_id, ) ) ); if ( $res >= 1 ) { llms_log( sprintf( 'Email `#%d` was not sent because of dupcheck', $email_id ) ); return; } // setup the email $email = LLMS()->mailer()->get_email( 'engagement', array( 'person_id' => $args[0], 'email_id' => $args[1], 'related_id' => $args[2], ) ); if ( $email ) { if ( $email->send() ) { $wpdb->insert( $wpdb->prefix . 'lifterlms_user_postmeta', array( 'user_id' => $person_id, 'post_id' => $related_id, 'meta_key' => '_email_sent', 'meta_value' => $email_id, 'updated_date' => current_time( 'mysql' ), ), array( '%d', '%d', '%s', '%d', '%s' ) ); llms_log( sprintf( 'Email `#%d` sent successfully', $email_id ) ); } else { llms_log( sprintf( 'Error: email `#%d` was not sent', $email_id ) ); } } } /** * Log debug data to the WordPress debug.log file * @param mixed $log data to write to the log * @return void * @since 2.7.9 * @version 3.12.0 */ public function log( $log ) { if ( $this->debug ) { llms_log( $log, 'engagements' ); } } /** * Handles all actions that could potentially trigger an engagement * * It will fire or schedule the actions after gathering all necessary data * * @return void * * @since 2.3.0 * @version 3.11.0 */ public function maybe_trigger_engagement() { $action = current_filter(); $args = func_get_args(); $this->log( '======= start maybe_trigger_engagement ========' ); $this->log( '$action: ' . $action ); $this->log( '$args: ' . json_encode( $args ) ); // setup variables used in queries and triggers based on the action switch ( $action ) { case 'lifterlms_created_person' : $user_id = intval( $args[0] ); $trigger_type = 'user_registration'; $related_post_id = ''; break; case 'lifterlms_course_completed' : case 'lifterlms_course_track_completed' : case 'lifterlms_lesson_completed' : case 'lifterlms_section_completed' : $user_id = intval( $args[0] ); $related_post_id = intval( $args[1] ); $trigger_type = str_replace( 'lifterlms_', '', $action ); break; case 'lifterlms_quiz_completed': case 'lifterlms_quiz_passed': case 'lifterlms_quiz_failed': $user_id = absint( $args[0] ); $related_post_id = absint( $args[1] ); $trigger_type = str_replace( 'lifterlms_', '', $action ); break; case 'llms_user_added_to_membership_level': case 'llms_user_enrolled_in_course': $user_id = intval( $args[0] ); $related_post_id = intval( $args[1] ); $trigger_type = str_replace( 'llms_', '', get_post_type( $related_post_id ) ) . '_enrollment'; break; case 'lifterlms_access_plan_purchased' : case 'lifterlms_product_purchased' : $user_id = intval( $args[0] ); $related_post_id = intval( $args[1] ); $trigger_type = str_replace( 'llms_', '', get_post_type( $related_post_id ) ) . '_purchased'; break; // allow extensions to hook into our engagements default : extract( apply_filters( 'lifterlms_external_engagement_query_arguments' , array( 'related_post_id' => null, 'trigger_type' => null, 'user_id' => null, ), $action, $args ) ); }// End switch(). // we need a user and a trigger to proceed, related_post is optional though if ( ! $user_id || ! $trigger_type ) { return; } // gather triggerable engagements matching the supplied criteria $engagements = apply_filters( 'lifterlms_get_engagements' , $this->get_engagements( $trigger_type, $related_post_id ), $trigger_type, $related_post_id ); $this->log( '$engagements: ' . json_encode( $engagements ) ); // only trigger engagements if there are engagements if ( $engagements ) { // loop through the engagements foreach ( $engagements as $e ) { $handler_action = null; $handler_args = null; // do actions based on the event type switch ( $e->event_type ) { case 'achievement' : $handler_action = 'lifterlms_engagement_award_achievement'; $handler_args = array( $user_id, $e->engagement_id, $related_post_id ); break; case 'certificate' : /** * @todo fix this * if there's no related post id we have to send one anyway for certs to work * this would only be for registration events @ version 2.3.0 * we'll just send the engagement_id twice until we find a better solution */ $related_post_id = ( ! $related_post_id ) ? $e->engagement_id : $related_post_id; $handler_action = 'lifterlms_engagement_award_certificate'; $handler_args = array( $user_id, $e->engagement_id, $related_post_id ); break; case 'email' : $handler_action = 'lifterlms_engagement_send_email'; $handler_args = array( $user_id, $e->engagement_id, $related_post_id ); break; // allow extensions to hook into our engagements default : extract( apply_filters( 'lifterlms_external_engagement_handler_arguments' , array( 'handler_action' => $handler_action, 'handler_args' => $handler_args, ), $e, $user_id, $related_post_id, $trigger_type ) ); }// End switch(). // can't proceed without an action and a handler if ( ! $handler_action && ! $handler_args ) { continue; } // if we have a delay, schedule the engagement handler $delay = intval( $e->delay ); $this->log( '$delay: ' . $delay ); $this->log( '$handler_action: ' . $handler_action ); $this->log( '$handler_args: ' . json_encode( $handler_args ) ); if ( $delay ) { wp_schedule_single_event( time() + ( DAY_IN_SECONDS * $delay ), $handler_action, array( $handler_args ) ); } // End if(). else { do_action( $handler_action, $handler_args ); } }// End foreach(). }// End if(). $this->log( '======= end maybe_trigger_engagement ========' ); } /** * Retrieve engagements based on the trigger type * * Joins rather than nested loops and sub queries ftw * * @param string $trigger_type name of the trigger to look for * @return array of objects * Array( * [0] => stdClass Object ( * [engagement_id] => 123, // WordPress Post ID of the event post (email, certificate, achievement, etc...) * [trigger_id] => 123, // this is the Post ID of the llms_engagement post * [trigger_event] => 'user_registration', // triggering action * [event_type] => 'certificate', // engagement event action * [delay] => 0, // time in days to delay the engagement * ) * ) * * @since 2.3.0 * @version 3.13.1 */ private function get_engagements( $trigger_type, $related_post_id = '' ) { global $wpdb; if ( $related_post_id ) { $related_select = ', relation_meta.meta_value AS related_post_id'; $related_join = "LEFT JOIN $wpdb->postmeta AS relation_meta ON triggers.ID = relation_meta.post_id"; $related_where = $wpdb->prepare( "AND relation_meta.meta_key = '_llms_engagement_trigger_post' AND relation_meta.meta_value = %d", $related_post_id ); } else { $related_select = ''; $related_join = ''; $related_where = ''; } $r = $wpdb->get_results( $wpdb->prepare( // the query "SELECT DISTINCT triggers.ID AS trigger_id , triggers_meta.meta_value AS engagement_id , engagements_meta.meta_value AS trigger_event , event_meta.meta_value AS event_type , delay.meta_value AS delay $related_select FROM $wpdb->postmeta AS engagements_meta LEFT JOIN $wpdb->posts AS triggers ON triggers.ID = engagements_meta.post_id LEFT JOIN $wpdb->postmeta AS triggers_meta ON triggers.ID = triggers_meta.post_id LEFT JOIN $wpdb->posts AS engagements ON engagements.ID = triggers_meta.meta_value LEFT JOIN $wpdb->postmeta AS event_meta ON triggers.ID = event_meta.post_id LEFT JOIN $wpdb->postmeta AS delay ON triggers.ID = delay.post_id $related_join WHERE triggers.post_type = 'llms_engagement' AND triggers.post_status = 'publish' AND triggers_meta.meta_key = '_llms_engagement' AND engagements_meta.meta_key = '_llms_trigger_type' AND engagements_meta.meta_value = %s AND engagements.post_status = 'publish' AND event_meta.meta_key = '_llms_engagement_type' AND delay.meta_key = '_llms_engagement_delay' $related_where ", // prepare variables $trigger_type ), OBJECT ); $this->log( '$wpdb->last_query' . $wpdb->last_query ); return $r; } }
Expand full source code Collapse full source code View on GitHub
Changelog Changelog
Version | Description |
---|---|
3.30.3 | Fixed spelling errors. |
2.3.0 | Introduced. |
Methods Methods
- __construct — Constructor Adds actions to events that trigger engagements
- add_actions — Register all actions that trigger engagements
- get_engagements — Retrieve engagements based on the trigger type
- handle_achievement — Award an achievement
- handle_certificate — Award a certificate
- handle_email — Send an email engagement
- init — Include engagement types (excluding email)
- instance — Create instance of class
- log — Log debug data to the WordPress debug.log file
- maybe_trigger_engagement — Handles all actions that could potentially trigger an engagement
User Contributed Notes User Contributed Notes
Permalink: