Make WordPress Core

Opened 10 years ago

Last modified 4 years ago

#19493 new defect (bug)

post and archive pagination don't work with custom endpoints

Reported by: mintindeed Owned by:
Milestone: Awaiting Review Priority: normal
Severity: normal Version: 2.1
Component: Rewrite Rules Keywords: needs-patch
Focuses: Cc:


Archive pagination and post pagination are not endpoint-aware, so they break when endpoints are added to them.

The following example code creates an endpoint, and then uses a filter to add that endpoint to various links on the rendered page:

add_action( 'init', function() {
	global $wp_rewrite;
	add_rewrite_endpoint( 'foo', EP_ALL );
} );

add_filter( 'post_link', 'gist_add_endpoint_to_url', 99 );
add_filter( 'get_pagenum_link', 'gist_add_endpoint_to_url', 99 );
function gist_add_endpoint_to_url( $url_base ) {
	$endpoint = 'foo';

	$url_parts = parse_url( $url_base );

	$url = ( isset($url_parts['scheme']) && isset($url_parts['host']) ) ? $url_parts['scheme'] . '://' . $url_parts['host'] : '';

	$url .= isset($url_parts['path']) ? $url_parts['path'] : '';

	$url = user_trailingslashit( $url );

	if ( '' === get_option('permalink_structure') ) {
		$url .= isset($url_parts['query']) ? '?' . $url_parts['query'] : '';

		$url = add_query_arg( $endpoint, 'true', $url );
	} else {
		$url .= $endpoint . '/true';
		$url = user_trailingslashit( $url );
		$url .= isset($url_parts['query']) ? '?' . $url_parts['query'] : '';

	$url .= isset($url_parts['fragment']) ? '#' . $url_parts['fragment'] : '';

	return $url;

You'll see that it works perfectly using the theme unit test, except that paginated posts produce URLs like this:
...which doesn't work. The inverse -- http://example.com/2008/09/layout-test/2/foo/true/ -- also doesn't work, and produces a 404 on top of it.

Also, the older posts / newer posts produce this format of link:
.. .which also doesn't work.

If you change gist_add_endpoint_to_url() to add a querystring param, older posts/newer posts links work fine, but post pagination still breaks:

function gist_add_endpoint_to_url( $url_base ) {
	$endpoint = 'foo';
	$url_base = add_query_arg( $endpoint, 'true', $url_base );
	return $url_base;

If you don't use a permalink structure at all, it works fine, since the pagination params are passed directly in the URL.

I'm not sure if the fix lies in modifying add_rewrite_endpoint() so that it creates pagination urls in wp_rewrite, or modifying the way _wp_link_page() and get_next_posts_link() work.

Change History (11)

#1 @scribu
10 years ago

  • Component changed from General to Rewrite Rules

I never understood what the difference between endpoints and permastructs was.

#2 @nacin
10 years ago

  • Version changed from 3.3 to 2.1

#3 @WraithKenny
9 years ago

  • Cc Ken@… added

I was working from a variation of westi's code from http://core.trac.wordpress.org/ticket/16303#comment:1 and the json endpoint breaks on paged urls: example.com/json/ works, and example.com/page/2/ works, but example.com/page/2/json/ fails has_posts() because $wp_query contains query->attachment and query_vars->attachment are set to "2" for some reason in addition to json being set true.

Pretty sure this is related? Fits the title at least.

#4 @WraithKenny
9 years ago

Further, ?paged=3&json=1 gets redirected to /page/3/?json=1 which works correctly (returns JSON).

Also, /page/3/garbage/ returns paged=1 but without stickies and 404 title (which has nothing to do with endpoints), and /page/3/something/json returns JSON but with the query attachment: "something" (and json: true) while using non-permalink vars (/?paged=3&something&json/) work as expected (turns into /page/3/?something&json/).

I don't fully understand how the permalink parsing works, so I can't tell if this is expected or bugged, but to the permalink layperson, this seems unexpected and buggy.

#5 @danielbachhuber
9 years ago

  • Cc wordpress@… added

#6 @mordauk
8 years ago

I'm seeing the exact same behavior when trying to paginate a custom endpoint.

#7 @mordauk
8 years ago

  • Cc pippin@… added

#8 @Krstarica
7 years ago

Any update on this, the bug is still present in 4.1?

#9 @BrianLayman
6 years ago

Yep, still present. I ran into this one too on a VIP site.

#10 @mihdan
5 years ago

Any update on this? The bug is still present in 4.2.2

#11 @davidshq
4 years ago

I'm still seeing this issue in 4.9.

Note: See TracTickets for help on using tickets.