Last active
December 17, 2015 23:29
-
-
Save davidmh/5689418 to your computer and use it in GitHub Desktop.
Fast Next/Prev Post Links for large databases. http://wordpress.stackexchange.com/q/101435/
This file contains 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 # -*- coding: utf-8 -*- | |
namespace WPSE; | |
/* Plugin Name: Fast Next/Prev Post Links | |
* Plugin URI: http://wordpress.stackexchange.com/q/101435/ | |
*/ | |
add_action( | |
'fast_prev_post_link', | |
__NAMESPACE__ . '\fast_prev_post_link', | |
10, | |
4 | |
); | |
add_action( | |
'fast_next_post_link', | |
__NAMESPACE__ . '\fast_next_post_link', | |
10, | |
4 | |
); | |
add_action( | |
'transition_post_status', | |
__NAMESPACE__ . '\delete_fast_adjacent_meta', | |
10, | |
3 | |
); | |
/** | |
* Print previous post link. | |
* | |
* @param unknown_type $format | |
* @param unknown_type $link | |
* @param unknown_type $in_same_cat | |
* @param unknown_type $excluded_categories | |
*/ | |
function fast_prev_post_link( | |
$format = '« %link', | |
$link = '%title', | |
$in_same_cat = FALSE, | |
$excluded_categories = '' | |
) | |
{ | |
empty ( $format ) && $format = '%link »'; | |
fast_adjacent_post_link( | |
$format, | |
$link, | |
$in_same_cat, | |
$excluded_categories, | |
TRUE | |
); | |
} | |
/** | |
* Print next post link. | |
* | |
* @param string $format | |
* @param string $link | |
* @param bool $in_same_cat | |
* @param array|string $excluded_categories | |
* @return void | |
*/ | |
function fast_next_post_link( | |
$format = '%link »', | |
$link = '%title', | |
$in_same_cat = FALSE, | |
$excluded_categories = '' | |
) | |
{ | |
empty ( $format ) && $format = '%link »'; | |
fast_adjacent_post_link( | |
$format, | |
$link, | |
$in_same_cat, | |
$excluded_categories, | |
FALSE | |
); | |
} | |
/** | |
* Display adjacent post link. | |
* | |
* Slightly changed copy of adjacent_post_link(). | |
* Unfortunately, WP mixes retrieving data and display. :( | |
* | |
* Can be either next post link or previous. | |
* | |
* @param string $format Link anchor format. | |
* @param string $link Link permalink format. | |
* @param bool $in_same_cat Whether link should be in a same | |
* category. | |
* @param array|string $excluded_categories Array or comma-separated list of | |
* excluded category IDs. | |
* @param bool $previous Default is true. Whether to display | |
* link to previous or next post. | |
* @return void | |
*/ | |
function fast_adjacent_post_link( | |
$format, | |
$link, | |
$in_same_cat = FALSE, | |
$excluded_categories = '', | |
$previous = TRUE | |
) | |
{ | |
if ( $previous && is_attachment() ) | |
$post = get_post( get_post()->post_parent ); | |
else // the only real change | |
$post = get_fast_adjacent_post(compact( | |
'in_same_cat', | |
'excluded_categories', | |
'previous' | |
)); | |
if ( ! $post ) { | |
$output = ''; | |
} else { | |
$title = $post->post_title; | |
if ( empty( $post->post_title ) ) | |
$title = $previous ? __( 'Previous Post' ) : __( 'Next Post' ); | |
$title = apply_filters( 'the_title', $title, $post->ID ); | |
$date = mysql2date( get_option( 'date_format' ), $post->post_date ); | |
$rel = $previous ? 'prev' : 'next'; | |
$string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">'; | |
$inlink = str_replace( '%title', $title, $link ); | |
$inlink = str_replace( '%date', $date, $inlink ); | |
$inlink = $string . $inlink . '</a>'; | |
$output = str_replace( '%link', $inlink, $format ); | |
} | |
$adjacent = $previous ? 'previous' : 'next'; | |
echo apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post ); | |
} | |
/** | |
* Get next or previous post from post meta. | |
* | |
* @param array $args Optional, The defaults are as follows: | |
* bool $in_same_cat = false | |
* string|array $excluded_categories = array() | |
* unknown_type $previous = true | |
* object $post = null | |
*/ | |
function get_fast_adjacent_post( $args = array() ) | |
{ | |
extract(shortcode_atts(array( | |
'in_same_cat' => false, | |
'excluded_categories' => '', | |
'previous' => true, | |
'post' => null | |
), $args)); | |
if ( ! $post = get_post( $post ) ) | |
return; | |
$excluded_categories = prepare_excluded_categories( $excluded_categories ); | |
$type = $previous ? 'prev' : 'next'; | |
$cat_hash = empty ( $excluded_categories ) ? 0 : join( '-', $excluded_categories ); | |
$hash = (int) $in_same_cat . "-$cat_hash"; | |
$meta = (array) get_post_meta( $post->ID, "_fast_{$type}_post", TRUE ); | |
if ( isset ( $meta[ $hash ] ) ) | |
return get_post( $meta[ $hash ] ); | |
$adjacent_post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous ); | |
$meta[ $hash ] = $adjacent_post->ID; | |
update_post_meta( $post->ID, "_fast_{$type}_post", $meta ); | |
return get_post( $meta[ $hash ] ) ; | |
} | |
/** | |
* Prepare categories sent as string. | |
* | |
* @param string|array $cats | |
* @return array | |
*/ | |
function prepare_excluded_categories( $cats ) | |
{ | |
if ( empty ( $cats ) or is_array( $cats ) ) | |
return array(); | |
$cats = explode( ',', $cats ); | |
$cats = array_map( 'trim', $excluded_categories ); | |
$cats = array_map( 'intval', $excluded_categories ); | |
return $cats; | |
} | |
/** | |
* Deletes post meta values for the current post and all posts referencing it. | |
* | |
* @wp-hook transition_post_status | |
* @param string $new_status | |
* @param string $old_status | |
* @param object $post | |
* @return void | |
*/ | |
function delete_fast_adjacent_meta( $new_status, $old_status, $post ) | |
{ | |
$prev = (array) get_post_meta( $post->ID, '_fast_prev_post', TRUE ); | |
if ( ! empty ( $prev ) ) | |
{ | |
foreach ( $prev as $post_id ) | |
delete_post_meta( $post_id, '_fast_next_post' ); | |
} | |
$next = (array) get_post_meta( $post->ID, '_fast_next_post', TRUE ); | |
if ( ! empty ( $next ) ) | |
{ | |
foreach ( $next as $post_id ) | |
delete_post_meta( $post_id, '_fast_prev_post' ); | |
} | |
delete_post_meta( $post->ID, '_fast_prev_post' ); | |
delete_post_meta( $post->ID, '_fast_next_post' ); | |
} | |
function get_fast_previous_post( $args = array() ) | |
{ | |
$args['previous'] = true; | |
return get_fast_adjacent_post($args); | |
} | |
function get_fast_next_post( $args = array() ) | |
{ | |
$args['previous'] = false; | |
return get_fast_adjacent_post($args); | |
} | |
// To print the links, use this in the template: | |
// do_action( 'fast_prev_post_link' ); | |
// do_action( 'fast_next_post_link' ); | |
// | |
// To get the posts, use: | |
// $in_same_cat = 1; | |
// WPSE\get_fast_previous_post( compact(in_same_cat) ); | |
// WPSE\get_fast_next_post( compact(in_same_cat) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment