0

I know from this post that I can get posts by tag name by just specifying a filter[tag] query parameter. And similarly with filter[category_name].

Is there a way to get posts that are not in a list of tags or categories for the purpose of excluding posts? I would prefer to do it with the name, or else I would have to make another request just to get the ID of the category, which would just slow down my overall response time in my app.

3 Answers 3

0

So one way this can be done is by creating a filter to check for a custom query string parameter that represents a tag name or names.

I added a function similar to this to my theme. It modifies the global WP_Query object before a request is made for posts by the REST API.

add_filter('pre_get_posts', function ($query) {
        // I couldn't read from query_vars for some reason, so using global $_GET
        $exclude_tag_name = isset($_GET['exclude_tag_name']);

        if (!$exclude_tag_name) {
            return; // Nothing to do
        }

        // Whitelist for security
        // Add to this list as needed
        $whitelist = ['SomeExcludedTagNameHere'];

        $tag_name = $exclude_tag_name;

        // Additional logic goes here to handle multiple names, such as splitting

        // Check if tag name is in white list (with strict type checking)
        // For security, you could also probably use a REGEX to sanitize
        // or one of WP's built in sanitizing functions.
        if (!in_array($tag_name, $whitelist, true)) {
            return; // nothing to do
        }

        // Get all tags that contain this name (case insensitive)
        // Or just use the tag directly if it doesn't matter to you.
        $tags = get_tags([
            'search' => $tag_name
        ]);

        $tag_ids = [];
        foreach ($tags as $tag) {
            $tag_ids[] = $tag->term_id;
        }

        // Exclude these category IDs from the query
        if (!empty($tag_ids)) {
            // Modify the query object that was passed in by reference
            // This function uses the tag ID's not names!
            $query->set('tag__not_in', $tag_ids);
        }
});

Similar code can be used to include only posts that have been tagged with a particular tag.

0

You could try using the rest_post_query action to add exclusion filters for categories and tags. Try something like the below.

This adds ['filter']['exclude_categories'] and ['filter']['exclude_tags'] as options to use in the WP REST API. Each filter accepts multiple categories/tags seperated by a comma.

add_action( 'rest_post_query', 'your_exclude_query', 10, 2 );
function your_exclude_query( $args, $request ) {

    // Exclude Query
    if ( isset($request['filter']['exclude_categories']) || isset($request['filter']['exclude_tags']) ) {

        // If the exclude categories filter is set
        if ( isset($request['filter']['exclude_categories']) ) {
            $categories = explode( ',', $request['filter']['exclude_categories'] ); // NOTE: Assumes comma separated taxonomies
            array_push( $pre_tax_query, array(
                'taxonomy' => 'category',
                'field' => 'name',
                'terms' => array( $categories ),
                'operator' => 'NOT IN'
            ));
        }

        // If the exclude tags filter is set
        if ( isset($request['filter']['exclude_tags']) ) {
            $tags = explode( ',', $request['filter']['exclude_tags'] );  // NOTE: Assumes comma separated taxonomies
            array_push( $pre_tax_query, array(
                'taxonomy' => 'post_tag',
                'field' => 'name',
                'terms' => array( $tags ),
                'operator' => 'NOT IN'
            ));
        }

        $tax_query = array(
            'relation' => 'AND',
            $pre_tax_query
        );

        $args[ 'tax_query' ] = $tax_query;

    }

    return $args;

} // end your_exclude_query
0

This is an old question but I think for now the solution exists.

We can use the tags_exclude=<tag-id> to execlude specifix tags.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.