Instantly share code, notes, and snippets.
Created
December 24, 2018 15:08
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save johnregan3/d93daddfd3e0aeb2da2f2bdbb2e74033 to your computer and use it in GitHub Desktop.
WordPress get related posts - Final
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Functions to find related posts | |
* | |
* Usage: Add this file to your theme or plugin. Then, simply use jr3_get_related_posts() to | |
* get an array of related posts. | |
* | |
* @package RelatedPosts | |
* @since 1.0.0 | |
* @author John Regan <[email protected]> | |
*/ | |
/** | |
* Get related posts. | |
* | |
* To set the count of posts returned, add a "posts_per_page" value to the $args array. | |
* The default number of posts returned is three. | |
* | |
* @since 1.0.0 | |
* | |
* @param int $post_id A \WP_Post ID. | |
* @param array $args Array of \WP_Query args. | |
* @param $count int The number of posts to retrieve. | |
* | |
* @return array An array of posts. | |
*/ | |
function jr3_get_related_posts( $post_id = 0, $args = array(), $count = 3 ) { | |
if ( empty( $post_id ) || ! is_numeric( $post_id ) ) { | |
$post_id = get_the_ID(); | |
} | |
if ( empty( $post_id ) ) { | |
return array(); | |
} | |
$transient_name = jr3_related_transient_name( $args ); | |
$output = get_transient( $transient_name ); | |
// Don't check if not empty, as the saved value may be an empty array. | |
if ( is_array( $output ) ) { | |
// Return what we have saved. | |
return $output; | |
} | |
$args = wp_parse_args( $args, array( | |
'posts_per_page' => 20, // For Sanity. | |
'orderby' => 'title', | |
'post_type' => get_post_type( $post_id ), | |
'post_status' => 'publish', | |
'author' => get_post_field( 'post_author', $post_id ), | |
'median' => 1, | |
) ); | |
// Do a tax query on first iteration. | |
$post = get_post( $post_id ); | |
$taxonomies = get_object_taxonomies( $post, 'names' ); | |
/* | |
* Sanity check. | |
* | |
* Limit the number of taxonomies to prevent an extremely slow query. | |
*/ | |
$taxonomies = array_slice( $taxonomies, 0, 3 ); | |
foreach ( $taxonomies as $taxonomy ) { | |
$terms = get_the_terms( $post_id, $taxonomy ); | |
if ( empty( $terms ) ) { | |
continue; | |
} | |
$term_list = wp_list_pluck( $terms, 'slug' ); | |
$args['tax_query'][] = array( | |
'taxonomy' => $taxonomy, | |
'field' => 'slug', | |
'terms' => $term_list, | |
); | |
} | |
if ( isset( $args['tax_query'] ) && count( $args['tax_query'] ) > 1 ) { | |
$args['tax_query']['relation'] = 'OR'; | |
} | |
// Force the 'post__not_in' var. | |
$args['post__not_in'] = array( $post_id ); | |
// Run the query. | |
$posts = jr3_related_posts_get( $args ); | |
if ( ! empty( $posts ) && count( $posts ) >= $count ) { | |
$posts = array_slice( $posts, 0, $count ); | |
set_transient( $transient_name, $posts, HOUR_IN_SECONDS ); | |
return $posts; | |
} | |
// Since we're continuing, don't duplicate any posts. | |
$args['post__not_in'] = wp_list_pluck( $posts, 'ID' ); | |
// Remove the author arg and try again. | |
unset( $args['author'] ); | |
$posts = jr3_related_posts_get( $args, $posts ); | |
$args['post__not_in'] = wp_list_pluck( $posts, 'ID' ); | |
if ( ! empty( $posts ) && count( $posts ) >= $count ) { | |
$posts = array_slice( $posts, 0, $count ); | |
set_transient( $transient_name, $posts, HOUR_IN_SECONDS ); | |
return $posts; | |
} | |
// Remove tax query arg and try again. | |
unset( $args['tax_query'] ); | |
$posts = jr3_related_posts_get( $args, $posts ); | |
$args['post__not_in'] = wp_list_pluck( $posts, 'ID' ); | |
if ( ! empty( $posts ) && count( $posts ) >= $count ) { | |
$posts = array_slice( $posts, 0, $count ); | |
set_transient( $transient_name, $posts, HOUR_IN_SECONDS ); | |
return $posts; | |
} | |
// Get random posts from the same post type. | |
$args['orderby'] = 'rand'; | |
$posts = jr3_related_posts_get( $args, $posts ); | |
// We're not going to remove any more args, just return what we have. | |
if ( ! empty( $posts ) && is_array( $posts ) ) { | |
$posts = array_slice( $posts, 0, $count ); | |
set_transient( $transient_name, $posts, HOUR_IN_SECONDS ); | |
return $posts; | |
} | |
return $posts; | |
} | |
/** | |
* Run a simple \WP_Query using the provided args. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $args An array of query args. | |
* | |
* @return array An array of posts, else an empty array. | |
*/ | |
function median_related_get_posts_by_args( $args = array() ) { | |
if ( empty( $args ) || ! is_array( $args ) ) { | |
return array(); | |
} | |
// Create the transient name. | |
$transient_name = jr3_related_transient_name( $args ); | |
$posts = get_transient( $transient_name ); | |
// Don't check if not empty, as the saved value may be an empty array. | |
if ( ! is_array( $posts ) ) { | |
// Don't use get_posts as the WP_Query object will be cached. | |
$query = new WP_Query( $args ); | |
if ( ! empty( $query->posts ) && is_array( $query->posts ) ) { | |
$posts = $query->posts; | |
} | |
set_transient( $transient_name, $posts, HOUR_IN_SECONDS ); | |
} | |
return $posts; | |
} | |
/** | |
* Get some posts using the provided $args. | |
* | |
* @since 1.0.0 | |
* | |
* @param array $args An array of \WP_Query args. | |
* @param array $posts An array of posts. | |
* | |
* @return array An updated array of posts. | |
*/ | |
function jr3_related_posts_get( $args, $posts = array() ) { | |
$new_posts = jr3_related_get_posts_by_args( $args ); | |
if ( is_array( $new_posts ) && ! empty( $new_posts ) ) { | |
$posts = $posts + $new_posts; | |
} | |
return $posts; | |
} | |
/** | |
* Get our transient name based on input args array. | |
* | |
* @since 1.0.0 | |
* | |
* @return string A transient name. | |
*/ | |
function jr3_related_transient_name( $args = array() ) { | |
return 'jr3_rel_' . md5( maybe_serialize( $args ) ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment