WordPress.org

Make WordPress Core

Opened 4 years ago

Closed 4 years ago

#29663 closed defect (bug) (fixed)

next_post_link & previous_post_link Category exclude broken

Reported by: gabrieldiggs Owned by: nacin
Milestone: 4.0.1 Priority: normal
Severity: normal Version: 4.0
Component: Posts, Post Types Keywords: needs-testing reporter-feedback
Focuses: template Cc:

Description (last modified by ocean90)

Hello, As of WordPress 4.0 my custom next_post_link & previous_post_link is broken. My code is as follows:

<?php next_post_link( '&laquo; %link', '%title', TRUE, '115' ); ?> |
<?php previous_post_link( '%link &raquo;', '%title', TRUE, '115' ); ?>

WordPress now ignores the excluded category (115) part of the code and shows all post regardless of category when clicking the next or previous post links. Everything was working before the upgrade to 4.0

Attachments (1)

29663-tests.diff (3.0 KB) - added by MikeHansenMe 4 years ago.

Download all attachments as: .zip

Change History (38)

#1 in reply to: ↑ description @kaprice
4 years ago

I tested to see if I can replicate this bug. I used a custom next_post_link, with an exclusion of a certain category. But the call to next_post_link worked just fine in 4.0 for me.

Before: http://i1252.photobucket.com/albums/hh570/Ken_Ken_Price/test1_zps1393d34a.png

After: http://i1252.photobucket.com/albums/hh570/Ken_Ken_Price/test2_zps6c4ddb50.png

Edit: I used modified content.php of the twentyfourteen theme this time, and added a call to next_post_link on line 62.

	<div class="entry-content">
		<?php
			the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentyfourteen' ) );
			wp_link_pages( array(
				'before'      => '<div class="page-links"><span class="page-links-title">' . __( 'Pages:', 'twentyfourteen' ) . '</span>',
				'after'       => '</div>',
				'link_before' => '<span>',
				'link_after'  => '</span>',
			) );
		
			next_post_link( '%link', '%title', false, '2');
		?>
		
	</div><!-- .entry-content -->

When you pass true as the third argument, next_post_link will check to see if the link is in the same taxonomy term as specified in the fifth argument ('category' by default). I was able to replicate the effect you described, but ostensibly it is not a bug.

Last edited 4 years ago by kaprice (previous) (diff)

#2 @ocean90
4 years ago

#29667 was marked as a duplicate.

#3 @ocean90
4 years ago

  • Description modified (diff)

#4 @gabrieldiggs
4 years ago

On a hunch I downloaded WordPress version 3.9.2 from the archive and replaced the link-template.php from 4.0 with the version from 3.9.2. Sure enough everything is back to normal on my site so the problem with category exclusion is definitely due to changes made in link-template.php from WordPress 3.9.2 to 4.0. I compared both files using File Merge on Mac OS X and there are multiple differences between the two files. Should I just keep the version from 3.9.2 or should I wait for a fix to WordPress version 4.0?

#5 follow-up: @kaprice
4 years ago

I put this line in one of my pages:

next_post_link( '%link', '%title', true, '3');

This page had categories 2 and 3. I went to the page using the same database using link-template.php from 3.9.2 and 4.0. I logged the mySQL queries for both. next_post_link() calls get_adjacent_post() where the database queries are made.

Here are the differences in the queries:

From 3.9.2

SELECT p.ID FROM wp_posts AS p  INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id
  INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id 
  AND tt.taxonomy = 'category' AND tt.term_id IN (3,2) WHERE p.post_date > '2014-09-14 03:51:26'
  AND p.post_type = 'post' AND p.post_status = 'publish'  ORDER BY p.post_date ASC LIMIT 1

From 4.0:

SELECT p.ID FROM wp_posts AS p  INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id 
  INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id 
  WHERE p.post_date > '2014-09-14 03:51:26' AND p.post_type = 'post' AND p.post_status = 
  'publish' AND tt.taxonomy = 'category' AND tt.term_id IN (2) AND p.ID NOT IN ( SELECT 
  object_id FROM wp_term_relationships WHERE term_taxonomy_id IN (3) ) ORDER BY p.post_date ASC
  LIMIT 1

The queries reflect the change in the php code for both versions of link-template.php. I don't know exactly what's wrong in your case, but using both versions had worked fine with me.

Last edited 4 years ago by kaprice (previous) (diff)

#6 in reply to: ↑ 5 @gabrieldiggs
4 years ago

Replying to kaprice:

I put this line in one of my pages:

next_post_link( '%link', '%title', true, '3');

This page had categories 2 and 3. I went to the page using the same database using link-template.php from 3.9.2 and 4.0. I logged the mySQL queries for both. next_post_link() calls get_adjacent_post() where the database queries are made.

Here are the differences in the queries:

From 3.9.2

SELECT p.ID FROM wp_posts AS p  INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id
  INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id 
  AND tt.taxonomy = 'category' AND tt.term_id IN (3,2) WHERE p.post_date > '2014-09-14 03:51:26'
  AND p.post_type = 'post' AND p.post_status = 'publish'  ORDER BY p.post_date ASC LIMIT 1

From 4.0:

SELECT p.ID FROM wp_posts AS p  INNER JOIN wp_term_relationships AS tr ON p.ID = tr.object_id 
  INNER JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id 
  WHERE p.post_date > '2014-09-14 03:51:26' AND p.post_type = 'post' AND p.post_status = 
  'publish' AND tt.taxonomy = 'category' AND tt.term_id IN (2) AND p.ID NOT IN ( SELECT 
  object_id FROM wp_term_relationships WHERE term_taxonomy_id IN (3) ) ORDER BY p.post_date ASC
  LIMIT 1

The queries reflect the change in the php code for both versions of link-template.php. I don't know exactly what's wrong in your case, but using both versions had worked fine with me.

Thanks for taking a further look. According to FileMerge the major difference regarding get_next/previous_post_link & next/previous_post_link is for 3.9.2 it uses the parameter: $in_same_cat and for 4.0 it replaced all instances of that parameter with the parameter: $in_same_term

Perhaps that is what's wrong with my site. I'm not sure how to fix the problem beyond sticking to the 3.9.2 version. Any tips are much appreciated.

#7 @posterworld
4 years ago

I'm having the same problem. By doing the same than gabrieldiggs (replacing the link-template.php 4.0 to 3.9.2) the error/bug/whatever it is gets fixed.

#8 @ocean90
4 years ago

  • Component changed from General to Posts, Post Types
  • Focuses template added
  • Milestone changed from Awaiting Review to 4.0.1

This ticket was mentioned in IRC in #wordpress-dev by nacin. View the logs.


4 years ago

#10 @nacin
4 years ago

  • Owner set to wonderboymusic
  • Status changed from new to assigned

#11 follow-ups: @wonderboymusic
4 years ago

  • Keywords reporter-feedback added

I am having a hard time reproducing this - the only way I could get it to break is if the default category is different than Uncategorized, Uncategorized is deleted, and the post has no category relationships (since category is the default taxonomy) - the SQL will try to join on the taxonomy/post relationships, and if you didn't change the taxonomy, it will be category.

Can you please describe more about your setup:

  • What is your default category?
  • Does "Uncategorized" still exist?
  • What term does 115 represent?
  • Is 115 present in the category taxonomy?
  • Do you have posts what that term as a category assigned to them?

#12 in reply to: ↑ 11 @gabrieldiggs
4 years ago

What is your default category?

Uncategorized (All categories unchecked by default in new posts)

Does "Uncategorized" still exist?

Yes

What term does 115 represent?

News (Category)

Is 115 present in the category taxonomy?

Yes (If taxonomy means category and tag lists)

Do you have posts with that term as a category assigned to them?

Yes (All posts are tagged with category 115 except posts in category 129 which are my radio show posts. Posts in category 115 may or may not have other categories as well. Posts in category 129 are only tagged with category 129 and nothing else.)

Last edited 4 years ago by ocean90 (previous) (diff)

#13 in reply to: ↑ 11 @posterworld
4 years ago

  • What is your default category?

Uncategorized

  • Does "Uncategorized" still exist?

Yes

  • What term does 115 represent?

In my case is 78, the "to exclude" category named "poster"

  • Is 78 present in the category taxonomy?

Yes

  • Do you have posts what that term as a category assigned to them?

yes

--

Just in case I would like to add that in my case I have 3 categories that should show up while using the nav previous or next bar (Uncategorized, News and Design) so I'm using: <?php previous_post_link( '%link', '%title', FALSE, '78' ); ?>

#14 follow-up: @posterworld
4 years ago

  • Version changed from 4.0 to trunk

hey guys, how are you?

I'd been running some test and I found out this:

On link-template.php, line 1514 is if change this line from WP 4.0 file:

$where .= " AND p.ID NOT IN ( SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id IN (" . implode( $excluded_terms, ',' ) . ') )';

to this one from WP 3.9.2 the exclude works great:

$where = $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id NOT IN (" . implode( $excluded_terms, ',' ) . ')', $taxonomy );

I have no idea why but it works, I hope this could help you to find out what's happening with this.

Regards! Pablo

PD: Sorry for my lame English.

#15 in reply to: ↑ 14 @gabrieldiggs
4 years ago

Replying to posterworld:

hey guys, how are you?

I'd been running some test and I found out this:

On link-template.php, line 1514 is if change this line from WP 4.0 file:

$where .= " AND p.ID NOT IN ( SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id IN (" . implode( $excluded_terms, ',' ) . ') )';

to this one from WP 3.9.2 the exclude works great:

$where = $wpdb->prepare( " AND tt.taxonomy = %s AND tt.term_id NOT IN (" . implode( $excluded_terms, ',' ) . ')', $taxonomy );

I have no idea why but it works, I hope this could help you to find out what's happening with this.

Regards! Pablo

PD: Sorry for my lame English.

@posterworld That modification to version 4.0 didn't work for me. I have to use the entire link-template.php file from version 3.9.2 in order for the excluded posts function to work. I'm waiting on an update from the WordPress developers to see how I should proceed.

This ticket was mentioned in IRC in #wordpress-dev by nacin1. View the logs.


4 years ago

This ticket was mentioned in IRC in #wordpress-dev by doc-bot. View the logs.


4 years ago

#18 @MikeHansenMe
4 years ago

  • Keywords needs-unit-tests added

I am going to work up some unit tests for this.

#19 @MikeHansenMe
4 years ago

So I have been writing some unit tests for this and getting mixed results. First I went to write a basic test using the defaults for get_previous_post_link and I would expect to get something like

&laquo; <a href="http://example.org/?p=12" rel="prev">Post title 2</a>

but instead I get an empty string(most of the time). Once in awhile running the same test I will get the correct return link. This is after creating 8 posts in setUp and checking based on a post in the middle.

#20 @boonebgorges
4 years ago

MikeHansenMe - Thanks for working on tests for this. It's a bit hard to say with certainty without seeing your tests, but based on your "most of the time" comment, I'm guessing it's that the posts you're creating all have the same post_date. Look at the internals of get_adjacent_post() - they do a < or > check, and if the post_date is the same, it'll return nothing. When creating lots of items in a unit test, they'll usually have the same post_date, but sometimes won't if you happen to be spanning a second.

#21 @MikeHansenMe
4 years ago

@boonebgorges you nailed it. Creating separate posts with different dates gets the link to return in my tests. I will wrap up the basic ones here so we can build on them.

#22 @MikeHansenMe
4 years ago

  • Keywords needs-unit-tests removed

#23 @boonebgorges
4 years ago

  • Owner changed from wonderboymusic to boonebgorges
  • Status changed from assigned to accepted

This appears to be a problem related to shared terms. I'm guessing that gabrieldiggs also has a tag called 'News'. This would explain why wonderboymusic was unable to reproduce.

The problem was introduced in [29248] #22112. The excluded_terms subquery was rewritten to use a subquery (which is correct) but checks against term_taxonomy_id, when it should be checking against term_id. On test installations with no shared terms (or in the unit tests, without some fiddling), term_id and term_taxonomy_id match, which is why no one noticed this problem during testing. Once those numbers are offset, the bug rears its head.

#24 @boonebgorges
4 years ago

In 30264:

Add tests for get_adjacent_post_link() wrappers.

Props MikeHansenMe.
See #29663.

#25 @boonebgorges
4 years ago

  • Keywords reporter-feedback removed

[30263] missed this ticket and fixes the bug for trunk.

#26 @boonebgorges
4 years ago

  • Keywords fixed-major added
  • Owner changed from boonebgorges to nacin
  • Status changed from accepted to assigned

https://core.trac.wordpress.org/changeset/30263 applies cleanly and fixes the bug in 4.0. Ready to be merged.

#27 @boonebgorges
4 years ago

#30395 was marked as a duplicate.

#28 follow-up: @nacin
4 years ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 30405:

In get_adjacent_post(), $excluded_terms should check term_id rather than term_taxonomy_id.

Merges [30263] (and [30264] [30401]) to the 4.0 branch.

props boonebgorges.
fixes #29663, see #22112.

#29 @gabrieldiggs
4 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

Hi, As of WordPress 4.0.1 the issue still exists regarding next_post_link & previous_post_link Category exclude being broken. My account was just auto-updated and the problem returned. Once again I downloaded WordPress 3.9.2 and replaced the link-template.php and the problem was solved. I'm going to keep a copy of the link-template.php from WordPress 3.9.2 on hand as a band aid until the issue is solved. If I can provide any input or data to aid in the process please let me know.

#30 in reply to: ↑ 28 @posterworld
4 years ago

Replying to nacin:

Thank you guys!, in my case this solved the problem.

Hope you can solve your problem soon gabrieldiggs.

Best regards

#31 @ocean90
4 years ago

#29565 was marked as a duplicate.

#32 @ocean90
4 years ago

  • Keywords needs-testing added; fixed-major removed
  • Milestone changed from 4.0.1 to 4.0.2

Seems like we have fixed #29565 but not this one. Moving milestone to 4.0.2.

#33 follow-up: @ocean90
4 years ago

  • Keywords reporter-feedback added

@gabrieldiggs: Does the issue still exists in WordPress 4.1 beta 2 (https://wordpress.org/wordpress-4.1-beta2.zip)?

#34 @ocean90
4 years ago

  • Version changed from trunk to 4.0

#35 in reply to: ↑ 33 @gabrieldiggs
4 years ago

Replying to ocean90:

@gabrieldiggs: Does the issue still exists in WordPress 4.1 beta 2 (https://wordpress.org/wordpress-4.1-beta2.zip)?

Hi, I unzipped the 4.1 beta 2 extracted the link-template.php file only and replaced the existing link-template.php file on my server under WordPress 4.0. I cleared the browser cache, refreshed my page and everything seems to be working. I'd feel more comfortable doing a full install via the dashboard as a manual full install via ftp seems a bit tedious. Will this become an official future release?

Last edited 4 years ago by gabrieldiggs (previous) (diff)

#36 @boonebgorges
4 years ago

  • Milestone changed from 4.0.2 to 4.0.1

gabrieldiggs - Yes, the updated fixes will be included in WordPress 4.1, which will be available in the upcoming weeks. Since it appears that the fix actually does work for you, I'm going to reclose this ticket.

#37 @boonebgorges
4 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed
Note: See TracTickets for help on using tickets.