Conversation
get_adjacent_post() resolved the terms used for the in_same_term clause in
PHP and interpolated them straight into SQL, so the only way to change which
terms are matched was to filter the finished SQL string.
Add a dynamic get_{$adjacent}_post_terms filter on the resolved term array,
placed after the excluded terms are removed and before the term IDs are cast
to integers, so a filtered value is still cast before it reaches the query.
This lets a site narrow the matched terms, for example to restrict matching
to a child term, without touching the generated SQL. The default behaviour is
unchanged: the callback still matches a post that shares any term, and a
filter that returns an empty array results in the existing no-adjacent-post
behaviour rather than an empty IN clause.
Props WazzaJB, boonebgorges.
Fixes #35082.
Assert that the adjacent post terms filter is applied, that it receives the documented arguments, and that narrowing the term array to a child term changes the adjacent post from one that shares only the parent term to one that shares the child term. Also pins the default behaviour, so the existing in_same_term semantics of matching any shared term are proven to be preserved, and covers a filter that removes every term. Fixes #35082.
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @skikken. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The reporter wants
get_adjacent_post()with$in_same_termto only consider leaf terms, so that two posts sharing only a parent term are not treated as adjacent when their deepest terms differ.This PR deliberately does not do that. That behaviour change was reviewed and rejected on the ticket:
The maintainer then offered an alternative and the reporter agreed to pursue it:
That filter was never written. This PR adds it.
The problem with the status quo is that the term list is resolved in PHP and then interpolated into the SQL, so the only way to change which terms are matched is to filter the finished SQL string. The new
get_{$adjacent}_post_termsfilter exposes the resolved term IDs instead:Three placement decisions:
$excluded_termsdiff, so the callback sees the list that will actually be used rather than one it then has to reconcile against exclusions.IN ()clause, which would be invalid SQL.array_map( 'intval', ... ). That ordering matters: term IDs are interpolated directly into the query, so keeping the integer cast downstream of the filter means a filtered value cannot reach SQL without being cast. An earlier position would have made the filter an injection surface.The name and argument style follow the existing dynamic filters in the same function (
get_{$adjacent}_post_excluded_terms,get_{$adjacent}_post_join,get_{$adjacent}_post_where,get_{$adjacent}_post_sort), so bothget_previous_post_termsandget_next_post_termsare available.Nothing changes by default.
$in_same_termstill matches any shared term, and there is a test pinning that so the rejected behaviour cannot creep in.The main test builds the reporter's own fixture, a parent term with a child term and three posts, and asserts both halves:
Trac ticket: https://core.trac.wordpress.org/ticket/35082
Use of AI Tools
AI assistance: Yes
Tool(s): Claude
Model(s): Sonnet
Used for: test cases, code review
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.