Limit WordPress Post Navigation to Same Author and Category
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..
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( '←', 'Previous post link', 'twentyten' ) . ' %title','true','','true' ); ?>
<?php next_post_link( '%link', '%title ' . _x( '→', '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 in order to get things working as required.
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 tutorial will help solve a problem you’ve been having or guide you in the right direction.
Special guest post by David Powell
22 responses
-
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.
-
-
-
-
Everytime you modify WordPress Core. God kills a kitten.
-
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.
-
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.
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 . "'"; } 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);
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.
-
waw..wp-includes?
You don’t need modify that..
Can you call on your theme functions? -
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.
-
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 :)
-
Thanks! Hopefully you or someone will get use out for the concept/plugin.
-
-
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”?
-
-
-
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
subcat A {posts in subcat A}
subcat A-2 {posts in subcat A}
subcat B {posts in subcat B}
subcat B-2 {posts in subcat B}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.