DiggingIntoWordPress

by Chris Coyier & Jeff Starr

Limit WordPress Post Navigation to Same Author and Category

Posted by on

This is an exclusive guest post by , posted on May 28th, 2012.

In this DigWP post, guest author David Powell explains how to limit WordPress’ default post-navigation to include posts only from the same author and category as the currently viewed post. This method is effective, but involves making modifications to core WordPress files, something you should only do as a last resort, and if you know what you are doing. If you’re comfortable with that, read on to learn how it’s done..

Update (2012/05/30): There is now a plugin for limiting post-navigation to the same author and category. The method in the article remains for informational purposes only.

The Problem

In my adventures with WordPress I have come across some interesting needs. Recently I worked with a client that has seven authors that each write their own blog posts, with different categories depending on the audience. The problem they kept running into was that, when a user would view one blog entry, the next and previous links would switch authors. The client needed for the next_post_link and the previous_post_link to stay within the same category as well as the same author.

The WordPress functions for next_post_link and previous_post_link allow for keeping the links within the same category but not the same author. This is where manipulating the WordPress core files comes into play.

After reviewing filter hooks and action hooks, existing WordPress functionality isn’t going to get us there. So The next logical solution involves altering the link-template.php file.

The Solution

To limit post navigation to the same author and category, locate the link-template.php file in the /wp-includes/ folder, and edit using your favorite text editor (Notepad++ for me). In this file you will alter four functions. Locate the following lines in the link-template.php file:

function previous_post_link($format='« %link', $link='%title', $in_same_cat = false, $excluded_categories = '') {
	adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, true);
}

Change that to the following:

function previous_post_link($format='« %link', $link='%title', $in_same_cat = false, $excluded_categories = '', $is_author = false) {
	adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, true, $is_author);
}

Below the previous lines of code you should find this:

function next_post_link($format='%link »', $link='%title', $in_same_cat = false, $excluded_categories = '') {
	adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, false);
}

Change that to the following:

function next_post_link($format='%link »', $link='%title', $in_same_cat = false, $excluded_categories = '',$is_author = false) {
	adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, false, $is_author);
}

These changes are small. You should notice that the only changes made were adding $is_author = false to the function parameters and $is_author to the call to adjacent_post_link call.

On the next function you’ll be adding another parameter and adjust the SELECT query that is pulling in the next/previous post. Locate the following line that should look something like this:

function get_adjacent_post($in_same_cat = false, $excluded_categories = '', $previous = true) {
	...
	}

This block is fairly long so I’m only covering what’s being changed. On this line add the same parameter as before ($is_author = false):

function get_adjacent_post($in_same_cat = false, $excluded_categories = '', $previous = true, $is_author = false) {
	...
	}

Next, in this same function find the $where variable as shown below (roughly 50 lines into the function).

$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );

What we want to do next is alter this variable so it retains the author only when $is_author is true. To do this test the boolean value of $is_author and tack a little extra on the end of the $where variable.

$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare("WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $posts_in_ex_cats_sql", $current_post_date, $post->post_type), $in_same_cat, $excluded_categories );
	if($is_author)
		$where .= " AND p.post_author='".$post->post_author."'";

For the final change in the link-template.php file locate the following function:

function adjacent_post_link($format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true) {
	if ( $previous && is_attachment() )
		$post = & get_post($GLOBALS['post']->post_parent);
	else
		$post = get_adjacent_post($in_same_cat, $excluded_categories, $previous);

Alter this function by the $is_author in the adjacent_post_link function and adding it to the get_adjacent_post call:

function adjacent_post_link($format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true, $is_author = false) {
	if ( $previous && is_attachment() )
		$post = & get_post($GLOBALS['post']->post_parent);
	else
		$post = get_adjacent_post($in_same_cat, $excluded_categories, $previous, $is_author);

Now you’re ready to use this new option in the theme files. To “activate” the retain author function use something like this in your single.php:

<?php previous_post_link( '%link', '' . _x( '&larr;', 'Previous post link', 'twentyten' ) . ' %title','true','','true' ); ?>
<?php next_post_link( '%link', '%title ' . _x( '&rarr;', 'Next post link', 'twentyten' ) . '','true','','true' ); ?>

Setting the last value to “true” activates the retain author function for that link. This will ensure the link stays within the same author as well as the same date. Note, in the above example I have $excluded_categories since I also want to keep everything in the same category. For my client this was their “members-only” blogs.

Take Notice

It is important to note that if you update the root files of WordPress, such as updated from 3.3 to 3.4, it may over ride these changes and you’ll have to make the adjustments again.

Conclusion

This is a quick and simple solution to add more functionality to your WordPress sites when you have multiple authors and multiple categories. I would love to see WordPress implement this into their native install (nudge nudge). Doing research on getting this to work I found quite a few people who needed this functionality but couldn’t find a reliable way of getting it done. In most cases their solutions didn’t work or it required them to remove one function to get this working.

Of course, if anyone has a more elegant solution I welcome the input. I’m still looking into ways to get this same affect with hooks since updates to WordPress wouldn’t alter a theme’s functions file. I look forward to everyone’s feedback and hopefully this will solve a problem you’ve been having or guide you in the right direction.

About the Author

David Powell is a professional web master and freelance web designer and developer. When he doesn’t have his nose buried in a computer screen or design book he’s usually in the gym lifting heavy things or punching a bag. You can locate him at his website or on Google+.

22 Responses

  1. Instead of modifying the core file, why not create a small plugin to do this job? That would save you the trouble of re-modifying after every upgrade. You can re-use / call on all functions used in the core. If need be, you can simply rewrite it using the same code and just use different function names.

    Release the plugin for public use.

    After doing it, create a trac ticket with a patch (modifying the core files) like you did above. Hope that it will get in. At which point, your plugin would be useless because it would be in the core :)

    • A plugin for this would be a very good idea. Something that I have on my to do list. I came across a need for this from so many people I created this solution. However, a plugin to solve the problem is on my to do list for sure.

      • I understand that this is a quick fix. I’m saying that to create a plugin for this would not take more than an hour. Because do exactly what you are suggesting in this article (with new function names in a plugin file)… and just use those functions in your template.

        The plugin DOES NOT need to have a backend. You just need to know which function to call in the template.

        • It would need a settings screen. Since the user would need to specify what pages/post would use the author and category options.

  2. It does not matter how ‘quick’ the fix is, you should never be modifying core files. That is absolutely the WRONG way to do anything. I had thought the owners of DigWP knew that and would never let a tutorial like this through, it appears that’s not the case.

    • Jeff Starr

      No its not. People modify core files all the time, not just WP but all sorts of software. Last time I checked, WP is still free and open, right?

  3. Robert Dall May 28, 2012

    Everytime you modify WordPress Core. God kills a kitten.

  4. Seriously, you should never need to modify core files.

    If you want to keep promoting yourselves as a tutorial site, you should withdraw this so called tutorial immediately.

    In the spirit of constructive criticism, the correct solution to this is in two parts:

    Firstly, the third parameter to previous_post_link() and next_post_link() is a flag to say keep the same category. Modify your theme (probably in single.php) to add that third parameter as ‘true’ to both functions.

    Next, add the following 5 lines of code to your theme’s functions.php. That’s it: five lines is all that’s required to do the job properly.

    add_filter( 'get_next_post_where', 'keep_same_author_get_next_post_where', 10, 3 );
    add_filter( 'get_previous_post_where', 'keep_same_author_get_next_post_where', 10, 3 );
    function keep_same_author_get_next_post_where( $where, $in_same_cat, $excluded_categories ) {
    global $post;
    return $where .= " AND p.post_author='" . $post->post_author . "'";
    }

    And as for your guest authors: Anyone who can tell you to modify a line of core code that includes a filterable string clearly does not understand WordPress on anything but the the most superficial level.

    • Jeff Starr

      Thanks for the feedback Mike. I agree that best practices are important, but disagree that information regarding modifying core files is wrong. I’ve learned much in my life hacking things: Nintendo, PS3, iPhone, Windows, Apache, MySQL, and tons of other gadgets and software. Guess what, I’ve hacked WP core files too. Sometimes I publish or share the info, sometimes others write about it instead. It’s just free and open information that you can use if needed, or move along if not.

      For you to suggest that we “should withdraw this so called tutorial immediately” is laughable. I appreciate your feedback and contribution to the topic, but to honestly suggest that information should be taken down is the wrong mindset. You’ve stated your case, which others may disagree with.. so should I remove your comment to appease them? Nope, and I wouldn’t do it, because it’s all about free speech. Fortunately, that applies to WP users as well.

      • The purpose of a tutorial should be to help people, and suggesting people modify core files is not helpful.

        The next time they update WordPress they will lose likely those mods, and their site will stop working the way it was doing.
        They will assume the update to WordPress broke their site.

        I understand that sometimes, on some systems, modifying the core files is the only way to achieve something (and that has been true of WordPress). But in this case, WordPress’ comprehensive filter and actions functionality provides the means to achieve the intended result without having to modify core. and with less code too!

        I notice that the article now includes an appeal for input that wasn’t there before.

        Of course, if anyone has a more elegant solution I welcome the input.

        And David has also added

        I’m still looking into ways to get this same affect with hooks

        Quite frankly, that quote and his response here (http://digwp.com/2012/05/post-navigation-author-category/#comment-36894) show a real lack of understanding of how WordPress works.

        Look at the other comments on this post: every one that isn’t by you or David says this is a bad idea.

        Stop defending a bad post that gives bad advice; correct it, and move on. You are doing your readers (and your own reputation) a disservice.

        • Jeff Starr

          Great points Mike, thanks for taking the time to contribute to the article/thread. The author is working on a plugin that we’ll mention at the beginning of the article as a better alternative for doing this. I think he’s just waiting on approval from the Plugin Directory then we’ll get it posted asap. Thanks again for sharing your opinion, we appreciate it.

  5. amdhas May 29, 2012

    waw..wp-includes?
    You don’t need modify that..
    Can you call on your theme functions?

    • Jeff Starr

      Yes, see a previous comment for an alternate method.. also the author of the post is working on a plugin that will do it all automatically (and without modifying core files), will update the article soon.

  6. Howdy!

    While I think it has all been already said above, I kinda wanted to make it clearer to all concerned with a simple typeset that makes it a bit more obvious.

    Rule 1: There is *never* a good reason to “hack” the WordPress core code on a site.

    Rule 2: If you actually find such a reason, then that is a case where you can help improve WordPress by submitting a ticket or patch.

    Writing a tutorial telling people to change their sites in ways that will prevent those people from wanting to upgrade, and potentially leaving them open to security issues in the future is silly at best, and downright irresponsible at worst. What’s more, a quick question on our support forums, mailing lists, or IRC channels would have given you an easy way that doesn’t involve such things.

    We have a great support community, and before doing things that can be considered dangerous and “bad”, it might be a good idea to try to take advantage of it in the future.

    • Jeff Starr

      Hi Otto, thanks for neatly summarizing the argument against hacking the WP core. Rather than spend time repeating/arguing my point, I’ll just emphasize that I hear you loud and clear. I can’t say I’ll never post again about hacking stuff, but per your advice will try reaching out with any questions or concerns before doing so. As for everyone else posting on this thread (and everyone else who will), I value your feedback. Thanks for contributing to the conversation.

  7. Musik+ June 4, 2012

    It would need a settings screen. Since the user would need to specify what pages/post would use the author and category options. nice article and very useful :)

  8. Jesus Christ, why do you guys give him flak over this he is doing what he is asked of the client and shared his solution here. You think a client gives a shit about “modifying core files”?

    No. He wants his authors to be on the next post.

    • And when his client upgrades WordPress and the functionality breaks? What then?

      It might be acceptable (for a short time) if it was the only way to solve the problem, but as I demonstrated above, the correct solution is as simple as 5 lines of code in a plugin or a theme’s functions.php.

      • These are part of the things you explain to the client and he makes the decision. You tell him, it’s possible, but I have to do something that isn’t recommended and if we upgrade, the functionality might (or most likely will) break.

        The client makes the choice. Guess what he will say? DO IT.

        If there is a solution without breaking the code, GREAT, I am not questioning that one should break the core instead of not, but if there isnt, what? Am I going to say to a client, “not possible”?

  9. squizeers June 15, 2012

    Thank you for writing this great tutorial as well as the plugin.
    Can your plugin be used to
    NAVIGATE THE POSTS IN THE SAME ROOT CATEGORY
    For example if i have posts in the following category structure, I want to be able to navigate through all the posts in the sub categories of CATEGORY A.

    CATEGORY A
    subcatA
    {posts in subcatA}
    subcatA-2
    {posts in subcatA}

    subcatB
    {posts in subcatB}
    subcatB
    {posts in subcatB}

    OR
    If i can add same tag to all the posts in sub categories of CATEGORY A and be able to navigate through the posts with the same tags.

    Any help will be much appreciated.
    Thank you.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry