BBP_User_Engagements_User

User strategy for interfacing with User Engagements


Description Description

This strategy largely exists for backwards compatibility with bbPress 2.5, or installations that have not upgraded their databases to 2.6 or above.

Note: this strategy is going to be a bit less tidy than the others, because it needs to do weird things to maintain the 2.5 status-quo. Do not use this strategy as an example when building your own.


Source Source

File: includes/common/engagements.php

class BBP_User_Engagements_User extends BBP_User_Engagements_Base {

	/**
	 * Type of strategy being used.
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @var string
	 */
	public $type = 'user';

	/**
	 * Private function to map 2.6 meta keys to 2.5 user-option keys.
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param string $meta_key
	 * @param int    $object_id
	 * @param bool   $prefix
	 *
	 * @return string
	 */
	private function get_user_option_key( $meta_key = '', $object_id = 0, $prefix = false ) {
		switch ( $meta_key ) {

			// Favorites
			case '_bbp_favorite' :
				$key = '_bbp_favorites';
				break;

			// Subscriptions
			case '_bbp_subscription' :

				// Maybe guess at post type
				$post_type = ! empty( $object_id )
					? get_post_type( $object_id )
					: bbp_get_topic_post_type();

				// Forums & Topics used different keys :/
				$key = ( bbp_get_forum_post_type() === $post_type )
					? '_bbp_forum_subscriptions'
					: '_bbp_subscriptions';

				break;

			// Unknown, so pluralize
			default :
				$key = "{$meta_key}s";
				break;
		}

		// Maybe prefix the key (for use in raw database queries)
		if ( true === $prefix ) {
			$key = bbp_db()->get_blog_prefix() . $key;
		}

		// Return the old (pluralized) user option key
		return $key;
	}

	/**
	 * Private function to get a 2.5 compatible cache key.
	 *
	 * This method exists to provide backwards compatibility with bbPress 2.5,
	 * which had caching surrounding the FIND_IN_SET usermeta queries.
	 *
	 * @since 2.6.3 bbPress (r6991)
	 *
	 * @param string $meta_key
	 * @param int    $object_id
	 *
	 * @return string
	 */
	private function get_cache_key( $meta_key = '', $object_id = 0 ) {

		// No negative numbers in cache keys (zero is weird, but not disallowed)
		$object_id = absint( $object_id );

		// Maybe guess at post type
		$post_type = ! empty( $object_id )
			? get_post_type( $object_id )
			: bbp_get_topic_post_type();

		switch ( $meta_key ) {

			// Favorites
			case '_bbp_favorite' :
				$key = 'bbp_get_topic_favoriters_';
				break;

			// Subscriptions
			case '_bbp_subscription' :

				// Forums & Topics used different keys :/
				$key = ( bbp_get_forum_post_type() === $post_type )
					? 'bbp_get_forum_subscribers_'
					: 'bbp_get_topic_subscribers_';

				break;

			// Unknown, so pluralize
			default :
				$nounize = rtrim( $meta_key, 'e' );
				$key     = "bbp_get_{$post_type}_{$nounize}ers_";
				break;
		}

		// Return the old (pluralized) user option key with object ID appended
		return "{$key}{$object_id}";
	}

	/**
	 * Get the user engagement cache for a given meta key and object ID.
	 *
	 * This method exists to provide backwards compatibility with bbPress 2.5,
	 * which had caching surrounding the FIND_IN_SET queries in usermeta.
	 *
	 * @since 2.6.3 bbPress (r6991)
	 *
	 * @param string $meta_key
	 * @param int    $object_id
	 *
	 * @return mixed Results from cache get
	 */
	private function cache_get( $meta_key = '', $object_id = 0 ) {
		$cache_key = $this->get_cache_key( $meta_key, $object_id );

		return wp_cache_get( $cache_key, 'bbpress_engagements' );
	}

	/**
	 * Set the user engagement cache for a given meta key and object ID.
	 *
	 * This method exists to provide backwards compatibility with bbPress 2.5,
	 * which had caching surrounding the FIND_IN_SET queries in usermeta.
	 *
	 * @since 2.6.3 bbPress (r6991)
	 *
	 * @param string $meta_key
	 * @param int    $object_id
	 *
	 * @return mixed Results from cache set
	 */
	private function cache_set( $meta_key = '', $object_id = 0, $user_ids = array() ) {
		$cache_key = $this->get_cache_key( $meta_key, $object_id );
		$user_ids  = $this->parse_comma_list( $user_ids );

		return wp_cache_set( $cache_key, $user_ids, 'bbpress_engagements' );
	}

	/**
	 * Delete the user engagement cache for a given meta key and object ID.
	 *
	 * This method exists to provide backwards compatibility with bbPress 2.5,
	 * which had caching surrounding the FIND_IN_SET queries in usermeta.
	 *
	 * @since 2.6.3 bbPress (r6991)
	 *
	 * @param string $meta_key
	 * @param int    $object_id
	 *
	 * @return mixed Results from cache delete
	 */
	private function cache_delete( $meta_key = '', $object_id = 0 ) {
		$cache_key = $this->get_cache_key( $meta_key, $object_id );

		return wp_cache_delete( $cache_key, 'bbpress_engagements' );
	}

	/**
	 * Turn a comma-separated string into an array of integers
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param string $results
	 * @return array
	 */
	private function parse_comma_list( $results = '' ) {
		return array_filter( wp_parse_id_list( $results ) );
	}

	/**
	 * Add a user id to an object
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param int    $object_id The object id
	 * @param int    $user_id   The user id
	 * @param string $meta_key  The relationship key
	 * @param string $meta_type The relationship type (usually 'post')
	 * @param bool   $unique    Whether meta key should be unique to the object
	 *
	 * @return bool Returns true on success, false on failure
	 */
	public function add_user_to_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post', $unique = false ) {
		$retval     = false;
		$option_key = $this->get_user_option_key( $meta_key, $object_id );
		$object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
		$exists     = array_search( $object_id, $object_ids );

		// Not already added, so add it
		if ( false === $exists ) {
			$object_ids[] = $object_id;
			$object_ids   = implode( ',', $this->parse_comma_list( $object_ids ) );
			$retval       = update_user_option( $user_id, $option_key, $object_ids );

			// Delete cache if successful (accounts for int & true)
			if ( false !== $retval ) {
				$this->cache_delete( $meta_key, $object_id );
			}
		}

		// Return true if added, or false if not
		return $retval;
	}

	/**
	 * Remove a user id from an object
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param int    $object_id The object id
	 * @param int    $user_id   The user id
	 * @param string $meta_key  The relationship key
	 * @param string $meta_type The relationship type (usually 'post')
	 *
	 * @return bool Returns true on success, false on failure
	 */
	public function remove_user_from_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
		$retval     = false;
		$option_key = $this->get_user_option_key( $meta_key, $object_id );
		$object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
		$exists     = array_search( $object_id, $object_ids );

		// Exists, so remove it
		if ( false !== $exists ) {
			unset( $object_ids[ $exists ] );

			$object_ids = implode( ',', $this->parse_comma_list( $object_ids ) );
			$retval     = ! empty( $object_ids )
				? update_user_option( $user_id, $option_key, $object_ids )
				: delete_user_option( $user_id, $option_key );

			// Delete cache if successful (accounts for int & true)
			if ( false !== $retval ) {
				$this->cache_delete( $meta_key, $object_id );
			}
		}

		// Return true if removed, or false if not
		return $retval;
	}

	/**
	 * Remove a user id from all objects
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param int    $user_id   The user id
	 * @param string $meta_key  The relationship key
	 * @param string $meta_type The relationship type (usually 'post')
	 *
	 * @return bool Returns true on success, false on failure
	 */
	public function remove_user_from_all_objects( $user_id = 0, $meta_key = '', $meta_type = 'post' ) {

		// Get the key
		$option_key = $this->get_user_option_key( $meta_key );

		// Get the option
		$object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );

		// Attempt to delete the user option
		$retval = delete_user_option( $user_id, $option_key );

		// Try to delete caches, but only if everything else succeeded
		if ( ! empty( $retval ) && ! empty( $object_ids ) ) {
			foreach ( $object_ids as $object_id ) {
				$this->cache_delete( $meta_key, $object_id );
			}
		}

		// Return true if user was removed, or false if not
		return $retval;
	}

	/**
	 * Remove an object from all users
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param int    $object_id The object id
	 * @param int    $user_id   The user id
	 * @param string $meta_key  The relationship key
	 * @param string $meta_type The relationship type (usually 'post')
	 *
	 * @return bool Returns true on success, false on failure
	 */
	public function remove_object_from_all_users( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {

		// Query for users
		$user_ids = $this->get_users_for_object( $object_id, $meta_key, $meta_type );
		$u_count  = count( $user_ids );

		// Count number of removals
		$removed  = array();
		$r_count  = 0;

		// Users have engaged, so remove them
		if ( ! empty( $u_count ) ) {

			// Loop through users and remove them from the object
			foreach ( $user_ids as $user_id ) {
				$removed[] = $this->remove_user_from_object( $object_id, $user_id, $meta_key, $meta_type );
			}

			// Count the removed users
			$r_count = count( $removed );
		}

		// Return true if successfully removed from all users
		return ( $r_count === $u_count );
	}

	/**
	 * Remove all users from all objects
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param string $meta_key  The relationship key
	 * @param string $meta_type The relationship type (usually 'post')
	 *
	 * @return bool Returns true on success, false on failure
	 */
	public function remove_all_users_from_all_objects( $meta_key = '', $meta_type = 'post' ) {

		// Query for users
		$option_key = $this->get_user_option_key( $meta_key, 0, true );
		$bbp_db     = bbp_db();
		$user_ids   = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$option_key}'" );
		$u_count    = count( $user_ids );

		// Count number of removals
		$removed    = array();
		$r_count    = 0;

		// Users have engaged, so remove them
		if ( ! empty( $u_count ) ) {

			// Loop through users and remove their user options
			foreach ( $user_ids as $user_id ) {
				$removed[] = $this->remove_user_from_all_objects( $user_id, $meta_key );
			}

			// Count the removed users
			$r_count = count( $removed );
		}

		// Return true if successfully removed from all users
		return ( $r_count === $u_count );
	}

	/**
	 * Get users of an object
	 *
	 * The database queries in this function were cached in bbPress versions
	 * older than 2.6, but no longer are to avoid cache pollution.
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param int    $object_id The object id
	 * @param string $meta_key  The key used to index this relationship
	 * @param string $meta_type The type of meta to look in
	 *
	 * @return array Returns ids of users
	 */
	public function get_users_for_object( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {

		// Try to get user IDs from cache
		$user_ids = $this->cache_get( $meta_key, $object_id );

		// Cache is empty, so hit the database
		if ( false === $user_ids ) {
			$option_key = $this->get_user_option_key( $meta_key, $object_id, true );
			$bbp_db     = bbp_db();
			$user_ids   = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$option_key}' and FIND_IN_SET('{$object_id}', meta_value) > 0" );

			// Always cache results (even if empty, to prevent multiple misses)
			$this->cache_set( $meta_key, $object_id, $user_ids );
		}

		// Return parsed IDs
		return $this->parse_comma_list( $user_ids );
	}

	/**
	 * Get the part of the query responsible for JOINing objects to relationships.
	 *
	 * @since 2.6.0 bbPress (r6844)
	 *
	 * @param array  $args
	 * @param string $meta_key
	 * @param string $meta_type
	 *
	 * @return array
	 */
	public function get_query( $args = array(), $context_key = '', $meta_key = '', $meta_type = 'post' ) {
		$user_id    = bbp_get_user_id( $args, true, true );
		$option_key = $this->get_user_option_key( $meta_key );
		$object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );

		// Maybe trick WP_Query into ".ID IN (0)" to return no results
		if ( empty( $object_ids ) ) {
			$object_ids = array( 0 );
		}

		// Maybe include these post IDs
		$args = array(
			'post__in' => $object_ids
		);

		// Parse arguments
		return bbp_parse_args( $args, array(), $context_key );
	}
}

Top ↑

Changelog Changelog

Changelog
Version Description
2.6.0 Introduced.


Top ↑

Methods Methods


Top ↑

User Contributed Notes User Contributed Notes

You must log in before being able to contribute a note or feedback.