get_adjacent_post: adjacent post query plugin compatibility
Follow up to https://github.com/WordPress/wordpress-develop/pull/10394
Tests out an idea suggested in https://core.trac.wordpress.org/ticket/64390#comment:10 Props @azaozz
[!NOTE] This is mainly to discuss whether it's worth the change, if so good, if not, I can close.
Description
This PR is a follow-up to #10394 that makes the deterministic ordering changes more defensive and plugin-friendly. It ensures that when plugins modify the get_{$adjacent}_post_where or get_{$adjacent}_post_sort filters, the deterministic logic is not applied on top of their modifications.
Problem
In PR #10394, deterministic ID-based ordering was added to fix adjacent post navigation for posts with identical dates. However, the implementation applied the deterministic logic before the filters ran, which meant:
- Plugins modifying the WHERE or SORT clauses via filters would receive SQL that already included the deterministic changes
- Plugins couldn't opt out or modify the SQL in ways that might conflict with the deterministic logic
- This could break plugins that parse or manipulate the SQL clauses
Solution
This PR implements a defensive approach that:
- Applies filters first with the original (non-deterministic) SQL clauses
- Only applies deterministic logic if filters don't modify the clauses - checks if the filtered value equals the original prepared value
- Respects plugin modifications - when filters modify the SQL, their changes are preserved and deterministic logic is not applied
Implementation:
- For WHERE clause: Only applies ID-based fallback if
$where === $where_prepared(filter didn't modify it) - For SORT clause: Only applies ID-based sorting if
$sort === $sort_prepared(filter didn't modify it)
Test Steps
Automated Tests
Run the PHPUnit tests:
npm run test:php -- --filter Tests_Link_GetAdjacentPost
Manual Testing
1. Verify Default Behavior (No Filters)
-
Create test scenario:
- Create multiple posts with identical
post_datevalues (bulk publish drafts) - Navigate between posts
- Create multiple posts with identical
-
Expected Results:
- Navigation works deterministically, you should be able to navigate through all posts with identical dates
2. Verify Filter Modifications Are Respected
Test WHERE Filter:
-
Add test filter to
functions.phpor a test plugin:
// Test filter for next post WHERE clause
add_filter( 'get_next_post_where', function( $where ) {
// Modify the WHERE clause - deterministic fallback should NOT be applied.
return $where . ' AND 1=1';
}, 10, 1 );
// Test filter for previous post WHERE clause
add_filter( 'get_previous_post_where', function( $where ) {
// Modify the WHERE clause - deterministic fallback should NOT be applied.
return $where . ' AND 1=1';
}, 10, 1 );
-
Verify behavior:
- Navigate between posts, rhe deterministic ID fallback should NOT be applied (no
AND p.IDin WHERE clause)
- Navigate between posts, rhe deterministic ID fallback should NOT be applied (no
Test SORT Filter:
- Remove WHERE filters, add SORT filter:
add_filter( 'get_next_post_sort', function( $sort, $post, $order ) {
// Remove ID from sort - deterministic ID sort should NOT be applied.
return "ORDER BY p.post_date $order LIMIT 1";
}, 10, 3 );
add_filter( 'get_previous_post_sort', function( $sort, $post, $order ) {
return "ORDER BY p.post_date $order LIMIT 1";
}, 10, 3 );
-
Verify behavior:
- Create posts with identical dates
- Navigate between posts, deterministic ID sort is NOT applied
3. Verify Unmodified Filters Still Get Deterministic Logic
- Add filters that don't modify the clauses:
add_filter( 'get_next_post_where', function( $where ) {
// Return unchanged - deterministic fallback should be applied.
return $where;
}, 10, 1 );
add_filter( 'get_next_post_sort', function( $sort ) {
// Return unchanged - deterministic ID sort should be applied.
return $sort;
}, 10, 1 );
-
Verify behavior:
- Navigation works deterministically, you should be able to navigate through all posts with identical dates
Trac ticket: https://core.trac.wordpress.org/ticket/64390