LLMS_Sessions
LLMS_Sessions class.
Contents
Source Source
File: includes/class-llms-sessions.php
class LLMS_Sessions { use LLMS_Trait_Singleton; /** * Current user id. * * @var null */ protected $user_id = null; /** * Private Constructor. * * @since 3.36.0 * @since 3.37.2 Add filter to the cleanup cronjob interval. * * @return void */ private function __construct() { add_filter( 'cron_schedules', array( $this, 'add_cron_schedule' ) ); if ( ! wp_next_scheduled( 'llms_end_idle_sessions' ) ) { /** * Filter the recurrence interval at which LifterLMS closes idle sessions. * * @link https://developer.wordpress.org/reference/functions/wp_get_schedules/ * * @since 3.37.2 * * @param string $recurrence Cron job recurrence interval. Must be valid interval as retrieved from `wp_get_schedules()`. Default is "every_five_mins". */ $recurrence = apply_filters( 'llms_sessions_end_idle_cron_recurrence', 'every_five_mins' ); wp_schedule_event( time(), $recurrence, 'llms_end_idle_sessions' ); } add_action( 'llms_end_idle_sessions', array( $this, 'end_idle_sessions' ) ); } /** * Add cron schedule for session end interval checks. * * @since 3.36.0 * * @param array $schedules Array of cron schedules. * @return array */ public function add_cron_schedule( $schedules ) { // Adds every 5 minutes to the existing schedules. $schedules['every_five_mins'] = array( 'interval' => MINUTE_IN_SECONDS * 5, 'display' => sprintf( __( 'Every %d Minutes', 'lifterlms' ), 5 ), ); return $schedules; } /** * End the 50 oldest idle sessions. * * @since 3.36.0 * * @return void */ public function end_idle_sessions() { foreach ( $this->get_open_sessions() as $i => $event ) { if ( $this->is_session_idle( $event ) ) { $this->end( $event ); } } } /** * End a session. * * @since 3.36.0 * @since 4.5.0 Delete open session entry from the `wp_lifterlms_events_open_sessions` table. * * @param LLMS_Event $start Event object for a session start. * @return LLMS_Event|WP_Error */ protected function end( $start ) { $end = llms()->events()->record( array( 'actor_id' => $start->get( 'actor_id' ), 'object_type' => 'session', 'object_id' => $start->get( 'object_id' ), 'event_type' => 'session', 'event_action' => 'end', ) ); if ( ! is_wp_error( $end ) ) { global $wpdb; $wpdb->query( $wpdb->prepare( " DELETE FROM {$wpdb->prefix}lifterlms_events_open_sessions WHERE `event_id` = %d ", $start->get( 'id' ) ) ); // db call ok; no-cache ok. } return $end; } /** * Ends the currently active session for the logged in user. * * @since 3.36.0 * * @return LLMS_Event|WP_Error|false */ public function end_current() { $current = $this->get_current(); if ( ! $current ) { return false; } return $this->end( $current ); } /** * Retrieve the current session start event record for a given user. * * @since 3.36.0 * @since 4.5.0 Added optional `$user_id` parameter. * * @param int $user_id Optional. WP_User ID of a student. Default `null` * If not provided, or a falsy is provided, will fall back on the current user id. * @return LLMS_Event|false */ public function get_current( $user_id = null ) { $user_id = $user_id ? $user_id : get_current_user_id(); if ( ! $user_id ) { return false; } $session = $this->get_last_session( $user_id ); if ( ! $session ) { return false; } $session = new LLMS_Event( $session->id ); if ( ! $this->is_session_open( $session ) ) { return false; } return $session; } /** * Determine if a session is idle. * * A session is considered idle if it's open and no new events have been recorded * in the last 30 minutes. * * @since 3.36.0 * @since 4.7.0 When retrieving the last event, instantiate the events query passing `no_found_rows` arg as `true`, * to improve performance. * * @param LLMS_Event $start Event record for the start of the session. * @return bool */ public function is_session_idle( $start ) { // Session is closed so it can't be idle. if ( ! $this->is_session_open( $start ) ) { return false; } $now = llms_current_time( 'timestamp' ); /** * Filter the time (in minutes) to allow a session to remain open before it's considered an "idle" session. * * @param int $minutes Number of minutes. */ $timeout = absint( apply_filters( 'llms_idle_session_timeout', 30 ) ) * MINUTE_IN_SECONDS; // Session has started within the idle window, so it can't have expired yet. if ( ( $now - strtotime( $start->get( 'date' ) ) ) < $timeout ) { return false; } $events = $this->get_session_events( $start, array( 'per_page' => 1, 'sort' => array( 'date' => 'DESC', ), 'no_found_rows' => true, ) ); // No events, the session is idle. if ( ! $events ) { return true; } $last_event = array_shift( $events ); return ( ( $now - strtotime( $last_event->get( 'date' ) ) ) > $timeout ); } /** * Determines if the given session is open (has not ended) * * @since 3.36.0 * * @param LLMS_Event Event record for the start of the session. * @return bool */ public function is_session_open( $start ) { return is_null( $this->get_session_end( $start ) ); } /** * Retrieve the last session object for the current user. * * @since 3.36.0 * @since 4.5.0 Added optional `$user_id` parameter. * * @param int $user_id Optional. WP_User ID of a student. Default `null` * If not provided, or a falsy is provided, will fall back on the current user id. * @return obj|null */ protected function get_last_session( $user_id = null ) { $user_id = $user_id ? $user_id : get_current_user_id(); global $wpdb; return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}lifterlms_events WHERE actor_id = %d AND object_type = 'session' AND event_type = 'session' AND event_action = 'start' ORDER BY date DESC LIMIT 1;", $user_id ) ); // db call ok; no-cache ok. } /** * Retrieve open sessions. * * @since 3.36.0 * @since 4.5.0 Retrieve open sessions from the `wp_lifterlms_events_open_sessions` table. * * @param int $limit Number of sessions to return. * @param int $skip Number of sessions to skip. * @return LLMS_Event[] */ protected function get_open_sessions( $limit = 50, $skip = 0 ) { global $wpdb; $sessions = $wpdb->get_col( $wpdb->prepare( " SELECT event_id FROM {$wpdb->prefix}lifterlms_events_open_sessions ORDER BY event_id ASC LIMIT %d, %d ", $skip, $limit ) ); // db call ok; no-cache ok. $ret = array(); if ( count( $sessions ) ) { foreach ( $sessions as $id ) { $ret[] = new LLMS_Event( $id ); } } return $ret; } /** * Retrieve an array of events which occurred during a session. * * @since 3.36.0 * * @param LLMS_Event $start Event record for the session.start event. * @param array $args Array of additional arguments to pass to the LLMS_Events_Query. * @return LLMS_Event[] */ public function get_session_events( $start, $args = array() ) { $end = $this->get_session_end( $start ); $args = wp_parse_args( $args, array( 'date_after' => $start->get( 'date' ), 'exclude' => array( $start->get( 'id' ) ), 'actor' => $start->get( 'actor_id' ), 'sort' => array( 'date' => 'ASC', ), 'per_page' => 10, ) ); if ( $end ) { $args['date_before'] = $end->get( 'date' ); $args['exclude'][] = $end->get( 'id' ); } $query = new LLMS_Events_Query( $args ); return $query->get_events(); } /** * Retrieve session end record for by session id. * * @since 3.36.0 * * @param LLMS_Event $start Event record for the session.start event. * @return LLMS_Event|end */ public function get_session_end( $start ) { global $wpdb; $end = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}lifterlms_events WHERE actor_id = %d AND object_id = %d AND object_type = 'session' AND event_type = 'session' AND event_action = 'end' ORDER BY date DESC LIMIT 1;", $start->get( 'actor_id' ), $start->get( 'object_id' ) ) ); // db call ok; no-cache ok. if ( ! $end ) { return null; } return new LLMS_Event( $end ); } /** * Retrieve a new session ID. * * @since 3.36.0 * @since 4.5.0 Added optional `$user_id` parameter. * * @param int $user_id Optional. WP_User ID of a student. Default `null` * If not provided, or a falsy is provided, will fall back on the current user id. * @return int */ protected function get_new_id( $user_id = null ) { $user_id = $user_id ? $user_id : get_current_user_id(); $last = $this->get_last_session( $user_id ); if ( ! $last ) { return 1; } return ++$last->object_id; } /** * Start a new session for the current user. * * @since 3.36.0 * @since 4.5.0 Create open session entry in the `wp_lifterlms_events_open_sessions` table. * Added optional `$user_id` parameter. * * @param int $user_id Optional. WP_User ID of a student. Default `null` * If not provided, or a falsy is provided, will fall back on the current user id. * @return false|LLMS_Event|WP_Error */ public function start( $user_id = null ) { $user_id = $user_id ? $user_id : get_current_user_id(); if ( ! $user_id ) { return false; } $start = llms()->events()->record( array( 'actor_id' => $user_id, 'object_type' => 'session', 'object_id' => $this->get_new_id( $user_id ), 'event_type' => 'session', 'event_action' => 'start', ) ); if ( ! is_wp_error( $start ) ) { global $wpdb; $wpdb->query( // db call ok; no-cache ok. $wpdb->prepare( " INSERT INTO {$wpdb->prefix}lifterlms_events_open_sessions ( `event_id` ) VALUES ( %d ) ", $start->get( 'id' ) ) ); } return $start; } }
Expand full source code Collapse full source code View on GitHub
Methods Methods
- __construct — Private Constructor.
- add_cron_schedule — Add cron schedule for session end interval checks.
- end — End a session.
- end_current — Ends the currently active session for the logged in user.
- end_idle_sessions — End the 50 oldest idle sessions.
- get_current — Retrieve the current session start event record for a given user.
- get_last_session — Retrieve the last session object for the current user.
- get_new_id — Retrieve a new session ID.
- get_open_sessions — Retrieve open sessions.
- get_session_end — Retrieve session end record for by session id.
- get_session_events — Retrieve an array of events which occurred during a session.
- instance — Get Main Singleton Instance.
- is_session_idle — Determine if a session is idle.
- is_session_open — Determines if the given session is open (has not ended)
- start — Start a new session for the current user.
Changelog Changelog
Version | Description |
---|---|
6.0.0 | Removed the deprecated LLMS_Sessions::$_instance property. |
5.3.0 | Replace singleton code with LLMS_Trait_Singleton . |
3.37.2 | Add filter llms_sessions_end_idle_cron_recurrence to allow customization of the recurrence of the idle session cleanup cronjob. |
3.36.0 | Introduced. |