<?php
/*
Plugin Name: Next-Previous Post by Title
Version: R1.0.1
Plugin URI: http://wordpress.org/support/topic/87573
Description: Navigate next/previous post by title rather than date. Template tags: next_post_title() (replaces next_post_link()) and previous_post_title (replaces previous_post_link()).
Author: Kaf Oseo
Author URI: http://szub.net

    Copyright (c) 2006 Kaf Oseo (http://szub.net)
    Next-Previous Post by Title is released under the GNU General
    Public License (GPL) http://www.gnu.org/licenses/gpl.txt

    This is a WordPress plugin (http://wordpress.org).

~Changelog:
R1.0.1 (Oct-14-2006)
Bug fix deals with loop caused by apostrophes in post title
of query. Added support for WordPress 2.1.
*/

function next_post_title($format='%link &raquo;'$link='%title'$in_same_cat false$excluded_categories '') {
    
$post szub_next_previous_post_title($in_same_cat$excluded_categoriestrue);

    if ( !
$post )
        return;

    
$title apply_filters('the_title'$post->post_title$post);
    
$string '<a href="'.get_permalink($post->ID).'">';
    
$link str_replace('%title'$title$link);
    
$link $string $link '</a>';
    
$format str_replace('%link'$link$format);

    echo 
$format;
}

function 
previous_post_title($format='%link &raquo;'$link='%title'$in_same_cat false$excluded_categories '') {
    
$post szub_next_previous_post_title($in_same_cat$excluded_categoriesfalse);

    if ( !
$post )
        return;

    
$title apply_filters('the_title'$post->post_title$post);
    
$string '<a href="'.get_permalink($post->ID).'">';
    
$link str_replace('%title'$title$link);
    
$link $pre $string $link '</a>';
    
$format str_replace('%link'$link$format);

    echo 
$format;
}

function 
szub_next_previous_post_title($in_same_cat false$excluded_categories ''$next true) {
    global 
$post$wpdb$wp_version;

    if( !
is_single() || is_attachment() )
        return 
null;

    
$join '';
    if ( 
$in_same_cat ) {
        
$join " INNER JOIN $wpdb->post2cat ON $wpdb->posts.ID= $wpdb->post2cat.post_id ";
        
$cat_array get_the_category($post->ID);
        
$join .= ' AND (category_id = ' intval($cat_array[0]->cat_ID);
        for ( 
$i 1$i < (count($cat_array)); $i++ ) {
            
$join .= ' OR category_id = ' intval($cat_array[$i]->cat_ID);
        }
        
$join .= ')';
    }

    
$sql_exclude_cats '';
    if ( !empty(
$excluded_categories) ) {
        
$blah explode('and'$excluded_categories);
        foreach ( 
$blah as $category ) {
            
$category intval($category);
            
$sql_exclude_cats .= " AND post_category != $category";
        }
    }

    
$post_type = ($wp_version >= 2.1) ? 'AND post_type = \'post\'' '';

    if( 
$next ) {
        
$gt_lt '>';
        
$asc_desc 'ASC';
    } else {
        
$gt_lt '<';
        
$asc_desc 'DESC';
    }

    return @
$wpdb->get_row("SELECT ID,post_title FROM $wpdb->posts $join WHERE post_status = 'publish' $post_type AND TRIM(post_title) $gt_lt '" addslashes(trim($post->post_title)) . "' $sqlcat $sql_exclude_cats AND ID != $post->ID ORDER BY TRIM(post_title) $asc_desc LIMIT 1");
}
?>