There are 2 answers depending on where you want to do this. One has good news, the other has bad news
Anywhere That Uses Post Queries
Modifying the SQL is rarely necessary here and usually a sign that something was overlooked. In this case, WP_Query
already provides a simple parameter to do this named has_password
.
With this in mind, we can modify the main loop to hide passworded/protected posts easily via pre_get_posts
:
add_action( 'pre_get_posts', function ( \WP_Query $q ) {
if ( is_admin() || $q->is_singular() ) {
return;
}
$q->set( 'has_password', false );
} );
Anywhere That uses the get_calendar
function
This includes the calendar widget and block, I’m afraid the news is not great.
get_calendar
doesn’t use WP_Query
, but instead uses raw SQL queries to count posts ( it doesn’t retrieve the posts ). It doesn’t provide filters for the SQL either.
It does provide 2 opportunities however:
- The
get_calendar
filter gives you the final HTML, allowing you to make some modifications to the final string. With this you could completely replace the HTML by re-implementingget_calendar
and returning new HTML that excludes private posts in the SQL - The
query
filter. Becauseget_calendar
calls WPDB query directly, you could filter on this, however, this filter runs on all queries WP makes, not just those for the calendar. You will need to figure out if a query is coming fromget_calendar
or not, which may be difficult or impossible. If you modify a query that isn’t fromget_calendar
you could cause problems that lead to instability. There is also a potential bug,get_calendar
does a check if there are any posts and returns an empty string if none are found, if that post is a passworded post then this could lead to a calendar that has no posts. Be careful to make any filter on this run as fast as possible or you’ll slow down WP a lot, this means no new DB queries in the filter, no fetching data, no making http requests or loading files. There’s also the danger of recursive loops.
Note that get_calendar
caches by both month and year, so you need to flush caches to see updated output
Why Didn’t posts_where
work?
It didn’t work because that filter is a part of WP_Query
, which isn’t used by get_calendar
. I would advise against using this though as it breaks the post_password
parameter of WP_Query
and the functions that depend on it ( e.g get_posts
or areas of the admin )