Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

It's possible to make a site totally inaccessible via feeds (RSS, Atom, RDF) with a function like this:

function itsme_disable_feed() {
    wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
}
add_action('do_feed', 'itsme_disable_feed', 1);
add_action('do_feed_rdf', 'itsme_disable_feed', 1);
add_action('do_feed_rss', 'itsme_disable_feed', 1);
add_action('do_feed_rss2', 'itsme_disable_feed', 1);
add_action('do_feed_atom', 'itsme_disable_feed', 1);
add_action('do_feed_rss2_comments', 'itsme_disable_feed', 1);
add_action('do_feed_atom_comments', 'itsme_disable_feed', 1);

But that disables feeds for the entire site i.e. the main feed, feeds for categories, tags, comments, posts, pages, custom post types, etc.

How do I disable just the main feed and the main comments feed of the site? i.e. only make site.com/feed/ and site.com/comments/feed/ inaccessible.

Simply hiding feed using something like this (below) isn't an option:

remove_action( 'wp_head', 'feed_links_extra', 3 );
remove_action( 'wp_head', 'feed_links', 2 );
share|improve this question
    
Please send 404 Not Found or 410 Gone before exiting. :) –  sam Oct 28 '13 at 17:24

5 Answers 5

up vote 3 down vote accepted

Very, very quick unscientific research suggests that there is only one query_var set for the main feed. Other feeds such as category, tag, author feeds have more than one query_var. Thus the following should kill the main feed but leave others intact.

add_filter(
  'pre_get_posts', 
  function($qry) {
    if ($qry->is_feed()) {
      $fvars = array_filter($qry->query_vars);
      if (1 == count($fvars)) {
        wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
      }
    }
  },
  1
);

To remove the main comment feed, you need a small edit to check for the presence of $fvars['withcomments'].

add_filter(
  'pre_get_posts', 
  function($qry) {
    if ($qry->is_feed() ) {
      $fvars = array_filter($qry->query_vars);
      if (1 == count($fvars) || isset($fvars['withcomments'])) {
        wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
      }
    }
  },
  1
);

Be warned: Barely tested. Possibly buggy. Caveat emptor. No refunds.

share|improve this answer
    
I think he wants to keep comment feeds that aren't the main comment feed. –  sam Oct 29 '13 at 17:32
    
I believe this should meet that criteria. –  s_ha_dum Oct 29 '13 at 18:14
    
Won't (1 == count($fvars) || isset($fvars['withcomments']) === true for any comment feed, not just the main one? –  sam Oct 29 '13 at 19:02

This is a modded version of @s_ha_dum answer.

I'm agree with him that when in main feed the only variable setted is 'feed' (for posts feed) and 'withcomments' for main comment feed, but instead of relying on current query object variables, and filter the many empty defaults using array_filter, I think that - probably - is more reliable looking at $wp->query_vars: an array that contain only the query variables effectively used to run the query:

add_action('pre_get_posts', 'no_main_feeds', 1);

function no_main_feeds( $q ) {
  if ( is_feed() || is_comment_feed() ) {
    $vars = $GLOBALS['wp']->query_vars;
    unset( $vars['feed'], $vars['withcomments'] );
    if ( empty($vars) ) wp_die( 'No feed available' );
  }
}

The check for is_comment_feed() is actually needless, because when in main comment feed is_feed() is true, but I think it makes code intentions more clear, probably is also more future proof, and finally it doesn't hurt...

Unlike other answers here it (should) works with any permalink structure and also if pretty permalinks are disabled at all.

share|improve this answer
1  
Won't unset( $vars['feed'], $vars['withcomments'] ); affect all feeds? –  sam Oct 28 '13 at 20:40
1  
Just noticed that I inset the $vars variable, not the query variables. –  G. M. Oct 29 '13 at 16:38

using rewrite rules you can disable a url pattern that match main feed.

add_filter('rewrite_rules_array', 'rewrite_rules_array_feed_disable');
function rewrite_rules_array_feed_disable($rules){
    unset($rules['feed/(feed|rdf|rss|rss2|atom)/?$']);
    unset($rules['(feed|rdf|rss|rss2|atom)/?$']);
    return $rules;
}
share|improve this answer
add_filter('request', 'itsme_disable_main_feeds');

function itsme_disable_main_feeds($q)
{
    $exit_msg   = 'No feed available. Please visit the <a href="%s">homepage</a>.';
    $exit_title = 'No Feed Available';

    if (    !empty($q['feed'])         && count($q) === 1
         || !empty($q['withcomments']) && count($q) === 2 ) {

        $exit_msg = sprintf($exit_msg, esc_url( home_url('/') ));
        wp_die( $exit_msg, $exit_title, array('response' => 404) );
    }

    return $q;
}
share|improve this answer

The hook callback needs to check if it's a tag feed, or if it's a category feed or may be if it's a author feed. You can get a lot of information about the feed being produced if you add this two line in the callback. i.e function itsme_disable_feed(){ ... }

global $wp_query;
die(print_r($wp_query->query_vars));

You will notice that for a tag feed, or a category feed or a comment feed or even for an author feed there are certain parameters which contain values. Just do a check so that if those parameters have any value associated with it, you will do nothing. And if not, which means it's a main feed, you will call die().

Hope it helps.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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