888888.888888.88""Yb..dP"Yb..8888b..Yb..dP.88b.88....db....8b....d8.88..dP""b8..dP"Y8
88__...88__...88__dP.dP...Yb..8I..Yb.YbdP..88Yb88...dPYb...88b..d88.88.dP...`".`Ybo."
88""...88""...88"Yb..Yb...dP..8I..dY..8P...88.Y88..dP__Yb..88YbdP88.88.Yb......o.`Y8b
88.....888888.88..Yb..YbodP..8888Y"..dP....88..Y8.dP""""Yb.88.YY.88.88..YboodP.8bodP'


88b.88.888888.888888.Yb........dP.dP"Yb..88""Yb.88..dP
88Yb88.88__.....88....Yb..db..dP.dP...Yb.88__dP.88odP.
88.Y88.88"".....88.....YbdPYbdP..Yb...dP.88"Yb..88"Yb.
88..Y8.888888...88......YP..YP....YbodP..88..Yb.88..Yb

January 26, 2008

Quick N Dirty

This is the third of my Quick N Dirty plugin posts. In the second post I showed how to access the post object and alter the post content before saving it back to the database. This plugin will also access to the post object, but this time I will use it to exclude posts from being displayed on the home page.

The hook I am going to use for this plugin is the_posts filter. This filter is called when a list of posts is pulled from the WordPress database ready to be displayed on screen.

The filter passes an array of post objects to the function which gives us the opportunity to carry out mass edits, add posts, or, as in this case, remove posts in certain circumstances.

What I want to do is to make sure that posts in my General category do not appear on the home page. I want them as part of my feed, as an added sweetener for subscribing, and I want them as part of my single post and my archives.

Here’s the plugin, I will explain more at the bottom:

[php]
/*
Plugin Name: Quick N Dirty Post Exclusion
Plugin URI: [insert the plugin uri here]
Description: Removes posts from the home page
Author: Andrew Rickmann
Version: 1
Author URI: http://www.wp-fun.co.uk
*/

//call the filter
//the_posts is called when a list of posts is retrieved from the database
//qnd_post_exclusion is the function
//1 is the priority, 1 runs first, 10 last
add_filter('the_posts', 'qnd_post_exclusion' , 1 );

function qnd_post_exclusion( $posts ){

//only apply this if we are looking at the home page
if ( !is_home() ) { return $posts; }

//create an array to hold the posts we want to show
$new_posts = array();

//loop through all the post objects
foreach( $posts as $post ){

//for each object get an array of applicable categories
$cats = get_the_category( $post->ID );

//create a variable that determins if this post should be included
//the default is true, i.e. include the post
$include = true;

//loop through all the categories applicable to the post
foreach( $cats as $cat) {

//if the post is assigned to our undesirable category then do not include it
if ( $cat->name == 'General' ) { $include = false; }
}
//if we want to include it then add the post object to the new posts array
if ( $include === true ) { $new_posts[] = $post; }
}

//send the new post array back to be used by WordPress
return $new_posts;
}

?>

By now the add_filter function should be fairly familiar so I won’t dwell on it. It shows the the hook, the function to be used, and specifies that it should run with the highest priority. I have chosen high priority so that any plugins that follow on that might modify the content of the post are saved the trouble of modifying a post that will later be removed. Aside from that the priority isn’t too relevant here.

The usual template functions is_home, is_feed, is_archive, etc will work at this point and so I have used is_home to restrict the plugin to posts displayed on the home page. If we are not dealing with the home page then the function will simply return the original array of posts. It is essential that it does return the array. Not returning the array is the same as filtering out every post, leaving no posts at all.

When the function is called it is passed an array of post objects. We use the post ID in each case to get an array of the categories the post is assigned to using the function below:

[php]get_the_category( $post->ID );

We then iterate through this array and if our chosen category is not in the array for each post we add the post to a new array . When we are done it is this array that is passed back to WordPress to continue its journey toward screen.

Note: If you copy the content of this plugin you will need to replace all the quote marks as WordPress replaces them with fancy ones.

Wordpress Chat
Wordpress chat?
3 comments
page 1308
Post Image The Easy Peasy Way
How to receive an image using post php?
26 comments
page 1065
Fun With Sidebar Tabs Styling
Tabs sidebar box?
2 comments
page 336
Post Image The Easy Peasy Way
Wordpress attachment url?
26 comments
page 1065
How To Add Sidebars To A Theme
How to register sidebar in wordpress?
10 comments
page 1053
Fun With Sidebar Tabs Styling
Alternate css in wp sidebar widgets?
2 comments
page 336
Using Your Own Url Shortener
Short url?
4 comments
page 1190
Post Image The Easy Peasy Way
Attachment picture in comments?
26 comments
page 1065
Doing More With Widgets Changing Layouts
Registersidebarwidget thematic?
6 comments
page 28
Using Your Own Url Shortener
Short links wordpress htaccess?
4 comments
page 1190
Html 5 Gallery
Html5 wordpress theme?
6 comments
page 1305
Updating Code Snippets Here
Fun wordpress sites?
no comment
page 1338
Dont Mess With My Toot Toot
Fun with toots?
15 comments
page 599
Dont Mess With My Toot Toot
Fun with toots?
15 comments
page 599
Post Image The Easy Peasy Way
Wordpress hook image size?
26 comments
page 1065
Post Image The Easy Peasy Way
Wp image get link of attachment?
26 comments
page 1065
Post Image The Easy Peasy Way
Wp get post attchements?
26 comments
page 1065
Photoshop Design Framework
Photoshop framework?
3 comments
page 296
Updating Code Snippets Here
Fun with wordpress?
no comment
page 1338
Post Image The Easy Peasy Way
Find the one we want based on its characteristics?
26 comments
page 1065
Why I Ditched Disqus
Disqus limitations?
5 comments
page 1175
Quick N Dirty Admin Login Screen
Login page css?
no comment
page 128
Quick N Dirty Admin Login Screen
Login page css style?
no comment
page 128
Wp Polls Reviewed
Different templates in wppolls?
one comment
page 58
Post Image The Easy Peasy Way
Php code add attachment wordpress?
26 comments
page 1065
Wordpress Chat
Chat para wordpress?
3 comments
page 1308
Photoshop Design Framework
Framework to photoshop?
3 comments
page 296
Post Image The Easy Peasy Way
Php get attachment from post?
26 comments
page 1065
Are Child Themes The Best Option
Wordpress thematic html5 child theme?
15 comments
page 1262
Are Child Themes The Best Option
Wordpress thematic html5?
15 comments
page 1262
Why I Ditched Disqus
Better than disqus?
5 comments
page 1175
Post Image The Easy Peasy Way
Wordpress imaged default url?
26 comments
page 1065
Are Child Themes The Best Option
Wordpress thematic html5?
15 comments
page 1262
  1 query every 1068 seconds, updated 1 seconds ago.
Friday, 6pm
 __
(__)
   `

 Andrew Rickmann

I have had a play with this now and I think the only way is to get into the SQL. Found_posts just returns a string.

You might this post useful that I saw today: http://wpengineer.com/quick-tipps-for-wordpress...

Tuesday, 1am
 __
(__)
   `

 Robert Griffin

Yeah, I really don't have time either. I'll be keeping an eye out here in case you do, or when I am bored, I will give it another go.

Monday, 9am
 __
(__)
   `

 Andrew Rickmann

Are you sure your filter left enough posts remaining to be paged? It is worth checking, perhaps echoing out a count of the posts array before you end the filter to make sure.

I think found_posts is just a count of the number of posts and found_posts_query may be the sql so a foreach loop wouldn't work there.

It may be possible to use post_results to figure out which posts you will be left with, i.e. by putting the ID in an array, then use found_posts to change the number of posts it thinks it has found, then finally use the_posts to actually filter the posts. Unfortunately I don't have the time to try it out at the moment.

Monday, 7am
 __
(__)
   `

 Robert Griffin

I had some time to play with the 'post_results'. When I used the same code it didn't show any paging at all. Only the first 5 posts in my case. When it is used in the 'the_posts' I get pagnation like before but I can see my other posts. From what I can see, this is the first place you can manipulate the returned posts.

Any filter I tried before that would would get errors on the foreach loop. I am new to filters and it scares me each time. I tried found_posts_query and found_posts but both gave me errors on the foreach.

Your filter works fine, and it looks like it is the first filter to use like this. Since my filter process is too complicated for a SQL query, it is probably best. Although, you would think that you could adjust the paging limit somehow.

Friday, 5am
 __
(__)
   `

 realsol

The combo between the shortcode the 'the_content' and the custom field in the 'the_posts' work great. I was just concerned about speed over putting it in the theme. Really , I don't see any difference. I was trying so many filter plugins it forced me into purchasing a MySQL container on my host, thinking it was just wordpressMU. But after I got rid of those and wrote my own, my strain on the server went away. Don't really need a MySQL container after all.

I will check out the filter you are talking about and see if it helps with the pages and let you know. It really is like on the back burner right now, since there are enough posts that show that it doesn't make too much difference.

I'll let you know what happens, since you might also want to use it on your front page.

Wednesday, 6pm
 __
(__)
   `

 Andrew Rickmann

That's quite a list of possible outcomes and I can see why a basic filter won't do it. I would say that filter the_posts is the right approach, you just need to fix the paging.

I must admit that I have never looked into how the paging works, so this isn't definite but in query.php, in wp-includes there are some more filters you might like to try.

First there is a post filter earlier on in the process which you should be able to simply replace with the one in my post above. This is posts_results. This seems to be the first process that happens immediately after the query so ought to be before any paging is calculated.

Beside that there are a few more that might relate to paging so you might want to take a look through that file and figure out how it all works.

Wednesday, 2am
 __
(__)
   `

 Robert Griffin

Thanks again. I hope I am not junking up you blog.

I am not sure a query would do. I like you wanted some info not seen to the average visitor. I have looked at many plug-ins, most left behind database entry's (another day). What I basically did, using your code example is created a plug-in that uses both a custom field and a short-code called user_access. I allow you to set levels against this. If used in a post you can hide, or show information based on whether the user is logged-in, logged-out,user lever, user name, or any php true false code you can think of in the shortcode. This allows me to display or hide portions of the post based on my custom criteria.

If used as a custom field, same usage applies, but to the whole post.

I really couldn't find anything out there that would let me do everything and that seemed wordpressmu friendly.

Because of the different options, I probably couldn't adjust the query since I can base it on so many things, like only show if a user is level 2, has edit rights, and is in a certain category, all from a shortcode or custom field.

While a plug-in is more transferable (I can use it in many different themes and blogs since I don't have to edit the theme) I want it to be quick. The plug-ins I tried, many really slowed things down. That why I wasn't sure if a plug-in or some code would be the quickest. I thought a plug-in would happen before the loop, but that is fine as long as performance doesn't lag. It doesn't appear to so far, but its really a virgin blog.

Tuesday, 5pm
 __
(__)
   `

 Andrew Rickmann

If you don't actually need a plugin then the best route would be to use query_posts right above the loop. Check out http://codex.wordpress.org/Template_Tags/query_... this explains how to do it.

Monday, 10pm
 __
(__)
   `

 Robert Griffin

Thanks for the response. I was filtering within the theme just below the loop statement. From what you said above, does this mean the theme is actually formatting all of the posts prior to me hiding them? I was just calling 'continue' as the second line in the loop before, thus, if I was hiding the post, no further processing was being done by the theme. It would just move on to the next post. I thought by using a plugin, I would be grabbing the post prior to the theme, thus cutting out some of the processing and formatting the theme does, since it would never see the hidden posts.

Would it be faster then to just leave my code in the them rather than calling it from the 'the_posts' filter?

Monday, 4pm
 __
(__)
   `

 Andrew Rickmann

Robert, the problem is that this takes the array at the last moment before it is output, after all the paging has been generated so this method will always have that problem.

It would be better to intercept the query before hand, perhaps by using the template_redirect hook and, depending on what is being requested, running a new query_posts() as shown in Multiple Loops example 1 on this page: http://codex.wordpress.org/The_Loop

Monday, 3pm
 __
(__)
   `

 Robert Griffin

I was looking for a good example for the filter(the_posts) and this was perfect. I was filtering each post but within my theme. I wanted to be able to do it as a plug-in but didn't know where to start.

My only problem is I am restricting my posts to 10 per page. It seems that when you hide a post, WordPress doesn't realize it and still counts the post as one of the 10. So if I am hiding 9 of the first 10 posts, I get a nextpage after the first post. Is there a way to tell WordPress to also exclude this post from the pagecount?

Thanks.