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.
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;
}