Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fast Next/Prev Post Links for large databases. http://wordpress.stackexchange.com/q/101435/
<?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 = '&laquo; %link',
$link = '%title',
$in_same_cat = FALSE,
$excluded_categories = ''
)
{
empty ( $format ) && $format = '%link &raquo;';
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 &raquo;',
$link = '%title',
$in_same_cat = FALSE,
$excluded_categories = ''
)
{
empty ( $format ) && $format = '%link &raquo;';
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
You can’t perform that action at this time.