Posted on

Sorting the posts by Wishlist Member membership levels

Someone wanted a way to prioritize posts that are targeting particular Wishlist Member membership level. The basic implementation here is simple: create a relevanssi_hits_filter function that will sort the posts by the level. More information about relevanssi_hits_filter.

There’s a trick to this, though, as Wishlist Member does not provide a way to check the level of one post. There’s a function that will get all the posts on a particular level, though, so we need to come up with a method to get the list once, then use it to check each individual post.

The relevanssi_hits_filter function is simple: it uses array_filter()to get the target posts from the list of all search results, then array_udiff() to get the rest of the posts and then array_merge() to merge the list back together in the correct order.

The filter function for array_filter() calls a function that will return a list of post IDs for the target level posts and uses that check whether a post is on that list or not.

The function that gets the list of post IDs will do that once, and will then just return the list on later calls.

/**
 * Generates the list of posts for the specific membership level.
 *
 * The list is fetched with wlmapi_get_level_posts(), which returns a
 * fairly complicated format. The format is simplified with
 * array_column() to extract just the post IDs. Those are set as
 * array keys with value of true to make lookup faster, as you can then
 * use isset( $array[ $post_ID ] ) instead of slower in_array().
 *
 * @param int $level The membership level.
 *
 * @return array An array of post_ID => true pairs.
 */
function rlv_generate_level_post_list( $level ) {
	global $rlv_wishlist_level_posts;
  
	if ( ! isset( $rlv_wishlist_level_posts[ $level ] ) ) {
		$rlv_wishlist_level_posts[ $level ] = array();
    }

	if ( empty( $rlv_wishlist_level_posts[ $level ] ) ) {
		$results = wlmapi_get_level_posts( $level );

		$rlv_wishlist_level_posts[ $level ] = array_fill_keys(
			array_column( $results['posts']['post'], 'ID' ),
			true
		);
	}

	return $rlv_wishlist_level_posts[ $level ];
}

/**
 * Filter function that returns true if posts is on the specific level.
 *
 * @param WP_Post The post object to check.
 *
 * @return boolean True if post is on the specific level.
 */
function rlv_free_filter( $post ) {
	$free_posts = rlv_generate_level_post_list( 1313127748 );
	return isset( $free_posts[ $post->ID ] );
}

/**
 * Comparison function for array_udiff: post objects are considered
 * equal if they have the same ID.
 *
 * @param WP_Post $a Compared object.
 * @param WP_Post $b Compared object.
 *
 * @return int 0 if the objects are equal, not 0 if not.
 */
function rlv_id_comparison( $a, $b ) {
	return $a->ID - $b->ID;
}

add_filter( 'relevanssi_hits_filter', 'rlv_free_posts_first' );

/**
 * Adjusts the hits so that posts on the specific Wishlist Member level
 * are first in the results.
 *
 * @param array $hits Contains the posts in $hits[0].
 *
 * @return array The $hits array, filtered.
 */
function rlv_free_posts_first( $hits ) {
	$free_posts  = array_filter( $hits[0], 'rlv_free_filter' );
	$other_posts = array_udiff( $hits[0], $free_posts, 'rlv_id_comparison' );
	$hits[0]     = array_merge( $free_posts, $other_posts );

	return $hits;
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.