Skip to content

REST API: Restore global $post in WP_REST_Posts_Controller::prepare_item_for_response() - #11695

Open
wppoland wants to merge 2 commits into
WordPress:trunkfrom
wppoland:trac/43502
Open

wppoland wants to merge 2 commits into
WordPress:trunkfrom
wppoland:trac/43502

Conversation

@wppoland

@wppoland wppoland commented May 3, 2026 •

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/43502

prepare_item_for_response() overwrote $GLOBALS['post'] and called setup_postdata() without restoring the previous state. Anything running after a REST request that re-used the controller (block rendering, the_content filters, etc.) saw the wrong global post.

This PR captures the previous global before mutation and restores it on every return path, including the early HEAD-request return.

Tests cover:

  • Restoration when a global post is already set
  • Restoration to null when no global post was set
  • Restoration on the HEAD-method early-return branch

Complements GH-1165 and GH-11455.

Use of AI Tools

AI assistance: Yes
Tool(s): Antigravity IDE
Model(s): Gemini 2.5 Pro
Used for: Code analysis, conflict resolution, test suite updates, and patch verification. All changes were manually reviewed and tested locally.


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.

@github-actions

github-actions Bot commented May 3, 2026 •

Copy link
Copy Markdown

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 props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props motylanogha, westonruter.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@wppoland

Copy link
Copy Markdown
Author

[62952] just fixed the identical setup_postdata() / unrestored global $post bug in WP_REST_Revisions_Controller (committed under #65495, with a "See #43502" reference).

This PR applies the same fix to the sibling case: WP_REST_Posts_Controller::prepare_item_for_response() still does $GLOBALS['post'] = $post; setup_postdata( $post ); (around line 1854) without restoring the previous $post on any return path, including the early HEAD return. Same fix shape as [62952], different controller — a natural follow-up while this area is being tidied up.

Rebased status: MERGEABLE, full CI green, and has unit tests covering the restore on every return path. CC @westonruter since you just handled the revisions controller.

@wppoland
wppoland force-pushed the trac/43502 branch 2 times, most recently from 9ba75b6 to 7787967 Compare September 13, 2026 07:43
@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@westonruter

Copy link
Copy Markdown
Member

@wppoland Why is a new PR being opened when we already have #11455?

…prepare_item_for_response()`.

Previously, this method overwrote `$GLOBALS['post']` and called `setup_postdata()` without restoring the previous state. Anything running after a REST request that re-used the controller (block rendering, the_content filters in subsequent calls, etc.) saw the wrong global post.

This commit captures the previous global before mutation and restores it on every return path, including the early HEAD-request return.

Adds tests covering:

* Restoration when a global post is already set.
* Restoration to `null` when no global post was set.
* Restoration on the HEAD-method early-return branch.

Complements WordPressGH-1165 and WordPressGH-11455.

See #43502.
@wppoland

Copy link
Copy Markdown
Author

@westonruter Apologies for missing #11455 when opening this - that was an oversight on my part.

The reason for the implementation here is that #11455 used a direct $GLOBALS['post'] = $previous_post; wp_reset_postdata(); pattern. That has two subtle issues:

  1. When $previous_post is set, calling wp_reset_postdata() immediately overwrites $GLOBALS['post'] with the main query's post if one exists, discarding $previous_post. If no main query post exists, wp_reset_postdata() is a no-op, leaving secondary globals ($id, $authordata, etc.) out of sync with $previous_post.
  2. When there was no previous post (null), assigning before wp_reset_postdata() repopulates the global from the main query rather than leaving it clear.

When [62952] landed the clean resolution for WP_REST_Revisions_Controller via #65495 using the dedicated restore_post_data() helper, this PR ported that exact, battle-tested pattern over to WP_REST_Posts_Controller, along with regression tests covering both existing/null states and early HEAD returns.

I have updated the @since tags to 7.2.0. If you'd prefer to consolidate onto #11455, I am more than happy to close this PR and post the updated patch/tests there, or keep this one and make sure @liaisontw is credited in the props on #43502.

@westonruter

Copy link
Copy Markdown
Member

Aside: This PR is missing the required AI Disclosure:

## Use of AI Tools
<!--
You are free to use artificial intelligence (AI) tooling to contribute, but you must disclose what tooling you are using and to what extent a pull request has been authored by AI. It is your responsibility to review and take responsibility for what AI generates. See the WordPress AI Guidelines: <https://make.wordpress.org/ai/handbook/ai-guidelines/>.
Example disclosure:
AI assistance: Yes
Tool(s): GitHub Copilot, ChatGPT
Model(s): GPT-5.1
Used for: Initial code skeleton and test suggestions; final implementation and tests were reviewed and edited by me.
-->

Please be sure to note the AI harness and model used when generating PRs and comments for GitHub and Trac.

@wppoland

Copy link
Copy Markdown
Author

Thank you @westonruter! Added the AI Disclosure section to the PR description. For reference, Antigravity IDE with Gemini 2.5 Pro was used for code analysis, conflict resolution, test suite updates, and patch verification, with all changes manually reviewed and tested locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants