Make WordPress Core

Opened 4 months ago

Last modified 3 weeks ago

#63843 new defect (bug)

`<wfw:commentRss>` in feeds can be empty causing invalid feed when filtered by `post_comments_feed_link`

Reported by: jerclarke's profile jerclarke Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version:
Component: Feeds Keywords: 2nd-opinion
Focuses: Cc:

Description

For history on this issue please see this older (resolved) ticket: https://core.trac.wordpress.org/ticket/9134

In it they ensured that the feeds didn't insert a <wfw:commentRss> URL for each post in the main feed unless comments were open or there were already comments (i.e. that you could expect content).

This ticket is about a related issue that affects the same code: It's possible for get_post_comments_feed_link() to return empty, if filtered by post_comments_feed_link, and in that scenario, currently, the result is an invalid feed because <wfw:commentRss> must contain a valid URL.

(Note this ticket is about the RSS2 feed, but I'm pretty sure the same fix will also apply to Atom)

Higher-level problem: Need a way to disable per-post comment feeds

WordPress needs a straightforward way to completely disable per-post comment feeds, and currently the only solution causes RSS validation errors due to wfw:commentRss being inserted in feed-rss2.php regardless of whether there is a link or not.

This ticket assumes there's no willingness to add a proper way to disable per-post comment feeds, such as a per_post_comment_feeds_enabled filter that could handle the various aspects of this, ensuring the per-post feed URLs result in HTTP errors as well as ensuring the URLs aren't inserted into the header or main feeds.

Either way, if such a higher-level filter was added, some change to feed-rss2.php would still be needed, because the logic in that file, described below, is unable to handle a scenario where per-post comment feeds are disabled.

Why disable per-post comment feeds?

Simple answer is because we simply have a right to decide for ourselves. There should be some form of fine-grained control over the publishing of comment feeds sitewide and per-post, without having to disable comments completely on posts (the only way that normal users can do so currently).

The more specific motivation for our case, a journalism org going back to 2005, is that scrapers pick up and check all the per-post RSS feeds, which is a huge resource drain that provides no value to anyone involved. We share full RSS of our content, and are happy to have a single, site-wide commend feed, but in the case of per-post comment feeds, we want to both turn them off so they don't load, and of course also stop promoting the feed URLs so they don't get visited at all and don't risk an SEO punishment for inserting links that don't resolve.

Only way to disable per-post comment feeds in RSS: Filter post_comments_feed_link causing validation errors

There should be an easy way to disable these feeds, but when I looked I found nothing and came up with the following solution, which I shared on the WP StackExchange:

https://wordpress.stackexchange.com/a/361130/175

It involves several filters to do the whole job, I won't repeat them all here, but the one that triggers the major issue for us is post_comments_feed_link which, as far as I can tell, is the only logical way to avoid publishing the per-post comment feed URLs in RSS:

function gv_disable_insert_post_comments_feed($for_comments) {	return ''; } add_filter('post_comments_feed_link', 'gv_disable_insert_post_comments_feed'); 

Doing this means that when feed-rss2.php checks for the per-post comments URL, it gets nothing, which is good, except that it still outputs the empty <wfw:commentRss></wfw:commentRss> tag. This results in the following output in https://validator.w3.org/:

Sorry This feed does not validate. line 76, column 21: wfw:commentRss must be a full and valid URL: (64 occurrences) [help]	<wfw:commentRss></wfw:commentRss> 

It seems self-evident to me that if there's no URL, WP should not output an empty tag that generates a validation error. It's also clear that the <wfw:commentRss> is in no way mandatory, because it's not shown if there are no comments and comments are closed.

So it seems worthwhile to fix this and ensure that the tag is only inserted when there is a URL to show.

Here's the old code:

<?php if ( get_comments_number() || comments_open() ) : ?>	<wfw:commentRss><?php echo esc_url( get_post_comments_feed_link( null, 'rss2' ) ); ?></wfw:commentRss>	<slash:comments><?php echo get_comments_number(); ?></slash:comments>	<?php endif; ?> 

Seems a simple update that avoids the possibliity of a validation error would be the following:

<?php if ( esc_url( get_post_comments_feed_link( null, 'rss2' ) ) AND ( get_comments_number() || comments_open() )) : ?>	<wfw:commentRss><?php echo esc_url( get_post_comments_feed_link( null, 'rss2' ) ); ?></wfw:commentRss>	<slash:comments><?php echo get_comments_number(); ?></slash:comments>	<?php endif; ?> 

Not exactly elegant, but it avoids the error, and would allow sites to use the post_comments_feed_link filter to solve the problem with a single solution.

Any reason not to do this?

Any core committers think it would instead be better to add more of an API for this, e.g. a function wp_post_comment_feeds_enabled() which has it's own filter to completely disable the feed URLs? Honestly that's what I tink is called for, considering that turning off these feeds is very appealing in the age of AI scrapers. It should be extremely simple both for someone to do themselves if they have access to a functions.php file, and for someone to add to a plugin via the API rather than via hacks.

Thanks to anyone who read through this, hopefully we can fix this little issue at some point!

Change History (2)

#1 @jerclarke
4 months ago

I'll add that in writing up this ticket, which I think remains a valid bug, I did come up with a solution to stop the per-post feed URLs showing in RSS without errors.

The combination of these three filters seems to do the trick (though I haven't tested it heavily yet):

function gv_disable_insert_post_comments_feed($for_comments) {	return ''; } add_filter('post_comments_feed_link', 'gv_disable_insert_post_comments_feed'); function gv_disable_post_comment_feeds_filter_get_comments_number(int $comments_number, int $post_id) { if (!is_feed()) { return $comments_number; } return 0; } add_filter('get_comments_number', 'gv_disable_post_comment_feeds_filter_get_comments_number', 10, 2); function gv_disable_post_comment_feeds_filter_comments_open( bool $comments_open, int $post_id ) { if (!is_feed()) { return $comments_open; } return false; } add_filter('comments_open', 'gv_disable_post_comment_feeds_filter_get_comments_number', 10, 2); 

By "disabling comments" and pretending every post has zero comments when loading feeds, we get the effect that the specific current logic of feed-rss2.php is hijacked and the <wfw:commentRss> tag isn't output.

The problem with this solution is obvious: It's indirect and could lead to all kinds of unpredictable side-effects. If feed-rss2.php is changed in the future, the URLs could end up being inserted again, and who knows what kind of knock-on effects it could have to "disable comments" on posts in this context.

On top of that, this solution also removes the option of inserting the comment count without the feed. To me the <slash:comments> tag is mostly useless, but also totally harmless, there's no reason to have to throw this baby out with the bath water.

I'll be using this solution for now, but it would be so much more logical for the template to honor just the first filter, post_comments_feed_link, and only insert the <wfw:commentRss> tag if there's a URL!

#2 @wildworks
3 weeks ago

  • Version trunk deleted
Note: See TracTickets for help on using tickets.