Opened 12 years ago
Closed 12 years ago
#22162 closed defect (bug) (fixed)
WP_Query must convert posts to WP_Post objects after filters are run
Reported by: | nacin | Owned by: | ryan |
---|---|---|---|
Milestone: | 3.5 | Priority: | normal |
Severity: | critical | Version: | 3.5 |
Component: | Query | Keywords: | has-patch |
Focuses: | Cc: |
Description
WP_Query sets all found posts to WP_Post objects with this:
if ( $this->posts ) $this->posts = array_map( 'get_post', $this->posts );
This takes place before the post_results and the_posts filters, which may actually set new posts. One use case would be to set posts from cache (which may still be stdClass objects) after bypassing the original query using the posts_request or post_request_ids filters (which is why we needed to add if ( $this->posts )
to begin with).
For more, see the advanced post caching plugin, a newer version of which is running on WP.com. The symptom they saw there is the queried object ends up an stdClass, and then in nav-menu-template.php — _wp_menu_item_classes_by_context(), specifically — $queried_object->ancestors is assumed to be an array. In reality, it will be null, as the stdClass object has no magic. This generates a warning.
#14426 was just re-opened for similar gotchas.
The solution: WP_Query must convert posts to WP_Post objects after filters are run. This second call could even only run when filters are not suppressed, I imagine.
Attachments (4)
Change History (15)
#4
@
12 years ago
Maybe we should check the count before and after the filters run and and re-map the array if the count changed.
I don't think that's a good heuristic. Maybe some plugin just replaces one post with another.
Always running array_map() shouldn't be too expensive.
#5
@
12 years ago
It's probably good enough.
Alternatively, since we already do a foreach sanitize_post() loop, do an is_a check and upgrade stdClass objects.
#7
@
12 years ago
nacin mentioned that we should probably wrap the_preview in get_post().
We also talked briefly about posts_results and whether there should be a re-map after it as well. Decided to skip that until we see problems with it in the wild.
Arguably we'd want to run them both before and after. Maybe we should check the count before and after the filters run and and re-map the array if the count changed.