Custom feed slug
To create a custom feed slug, e.g.
example.tld/billyfeed/
we can use the add_feed()
but we have to flush the rewrite rules to activate it. We can do that e.g. by visiting the Permalinks settings page in the backend.
To generate the feed we can use e.g. do_feed_rss2()
or do_feed_atom()
.
Here’s an example:
add_action( 'init', function()
{
add_feed( 'billyfeed', function()
{
do_feed_rss2();
});
});
Modify the custom feed query
Next we need to modify our custom feed so that we either get the authors or categories.
Here’s a workaround using the posts_clauses
filter but without using string replacements with str_replace()
.
/**
* Custom feed example.tld/billyfeed that queries authors or categories
* Supports pagination
*
* @link http://wordpress.stackexchange.com/a/207876/26350
*/
add_filter( 'posts_clauses', function( $clauses, \WP_Query $q )
{
//---------------------------------------
// Only target our custom feed
//---------------------------------------
if( ! $q->is_feed( 'billyfeed' ) || ! $q->is_main_query() )
return $clauses;
global $wpdb;
//---------------------------------------
// Input - we edit this to our needs
//---------------------------------------
$tax_query = [
[
'taxonomy' => 'category',
'field' => 'slug',
'terms' => [ 'red', 'green', 'blue' ]
]
];
$author__in = [ 1, 2, 3 ];
//---------------------------------------
// Generate the tax query SQL
//---------------------------------------
$qv = [ 'tax_query' => $tax_query, 'cat' => null, 'tag' => null ];
$q->parse_tax_query( $qv );
$tc = $q->tax_query->get_sql( $wpdb->posts, 'ID' );
//---------------------------------------
// Generate the author query SQL
//---------------------------------------
$csv = join( ',', wp_parse_id_list( (array) $author__in ) );
$authors = " {$wpdb->posts}.post_author IN ( $csv ) ";
//---------------------------------------
// Make sure the authors are set and
// the tax query is valid (doesn't contain 0 = 1)
//---------------------------------------
if( ! empty( $author__in ) && false === strpos ( $tc['where' ], ' 0 = 1' ) )
{
// Append to the current join/where parts
$clauses['join'] .= $tc['join'];
$clauses['where'] .= sprintf(
' AND ( %s OR ( 1=1 %s ) ) ', // The tax query SQL comes prepended with AND
$authors,
$tc['where']
);
}
return $clauses;
}, PHP_INT_MAX, 2 );
where we modify the $tax_query
and $author__in
to our needs.
This generates the following main SQL query:
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE
1=1
AND wp_posts.post_type="post"
AND (wp_posts.post_status="publish" OR wp_posts.post_status="private")
AND ( wp_posts.post_authors IN (1,2,3 ) OR ( 1=1 AND (
wp_term_relationships.term_taxonomy_id IN (1,43,120)
) ) )
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10;
With this approach we can still paginate our feed:
example.tld/billyfeed/?paged=2