-
Notifications
You must be signed in to change notification settings - Fork 466
fix(#3438, #1999): Media item privacy inheritance and attachment status queries #3444
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jasonbahl
merged 8 commits into
wp-graphql:develop
from
jasonbahl:fix/3438-media-item-visibility-issues
Nov 21, 2025
Merged
fix(#3438, #1999): Media item privacy inheritance and attachment status queries #3444
jasonbahl
merged 8 commits into
wp-graphql:develop
from
jasonbahl:fix/3438-media-item-visibility-issues
Nov 21, 2025
+814
−6
Conversation
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
…p-graphql#3438) Adds test coverage for issue wp-graphql#3438 where media items with "inherit" status attached to draft parent posts were incorrectly accessible when queried by DATABASE_ID, but correctly private when queried by SLUG. The test verifies that media items inherit privacy from their parent posts when they have "inherit" status, ensuring consistent behavior across all ID type resolution paths. This test will fail without the corresponding fix.
…phql#3438) Media items with "inherit" status attached to draft parent posts were incorrectly accessible when queried by DATABASE_ID, but correctly private when queried by SLUG. Modified Post::is_private() to check parent privacy for attachments with "inherit" status, ensuring consistent behavior across all ID type resolution paths while preserving documented behavior for media items without parents or with published parents.
3 tasks
…raphql#1999) Adds testMediaItemsQueryWithPublishStatus() to verify that mediaItems queries can find attachments with 'publish' status (set by plugins) when querying by ID. This test reproduces the scenario described in issue wp-graphql#1999 where PostObjectConnectionResolver was hardcoding post_status='inherit' for attachments, causing queries to miss attachments that plugins had changed to 'publish' status. The test will fail without the fix to PostObjectConnectionResolver.php and pass once post_status='any' is used for attachments. Refs: wp-graphql#1999 (comment)
…-media-item-visibility-issues
…p-graphql#1999) Changed PostObjectConnectionResolver to use post_status='any' for attachments instead of hardcoding 'inherit'. This ensures queries can find attachments regardless of their status, including 'publish' status set by plugins. Previously, PostObjectConnectionResolver was hardcoding post_status='inherit' for all attachment queries, causing queries to miss attachments that plugins had changed to 'publish' status. This resulted in featuredImage returning null and mediaItems queries missing attachments even when they existed. The Model's is_private() method (fixed in wp-graphql#3438) handles privacy checks based on the attachment's parent and status, so using 'any' status is safe and allows proper privacy enforcement. This fix applies to all attachment queries, including featuredImage connections and direct mediaItems queries. Refs: wp-graphql#1999 (comment)
Adds testGraphqlPreModelDataIsPrivateFilterMakesAttachmentsPublic() and testGraphqlDataIsPrivateFilterMakesAttachmentsPublic() to verify that the documented filters for overriding media item privacy work correctly. These tests ensure that users can use the filters documented in the PR description to make all media items public, even when attached to draft posts. This helps prevent regressions for users relying on these filters. The tests verify both filter hooks: - graphql_pre_model_data_is_private (before privacy check) - graphql_data_is_private (after privacy check) Both filters should allow subscribers to access attachments attached to draft parents, overriding the default privacy inheritance behavior.
3 tasks
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.
What bug does this fix? Explain your changes.
This PR fixes two related issues with media item/attachment queries and privacy:
Bug #1: Media Item Privacy Inheritance (#3438)
The Bug:
Media items with "inherit" status attached to draft parent posts were incorrectly accessible when queried by
DATABASE_ID, but correctly private when queried bySLUG. This inconsistent behavior occurred because:SLUG, thenode_resolver->resolve_uri()path uses WordPress'sWP_Query, which properly filters out attachments with draft parentsDATABASE_ID, the code directly loads the post and bypasses WordPress's query system, relying solely on the Model'sis_private()checkis_private()method was treating all attachments as public, regardless of their parent's privacy statusRoot Cause:
The
Post::is_private()method insrc/Model/Post.phphad a blanket rule that all attachments are public (lines 323-325), which ignored the "inherit" status that should cause attachments to inherit privacy from their parent posts.The Fix:
Modified
Post::is_private()to check if an attachment has "inherit" status and a parent post. If so, it now checks the parent's privacy status and inherits it. This ensures consistent behavior across all ID type resolution paths (DATABASE_ID, SLUG, GLOBAL_ID, etc.) while preserving the documented behavior that attachments without parents or with published parents remain public.Bug #2: Missing Attachments with 'publish' Status (#1999)
The Bug:
Media items (attachments) that plugins had changed from the default 'inherit' status to 'publish' status were not being found in queries, including
featuredImageconnections and directmediaItemsqueries. This occurred because:PostObjectConnectionResolverwas hardcodingpost_status='inherit'for all attachment queriespost_status='inherit'would miss these attachmentsfeaturedImageto returnnulleven when an image existed, andmediaItemsqueries to miss attachments with 'publish' statusRoot Cause:
The
PostObjectConnectionResolver::prepare_query_args()method was settingpost_status='inherit'specifically for attachments (line 209), which prevented queries from finding attachments with any other status, including 'publish' status set by plugins.The Fix:
Modified
PostObjectConnectionResolver::prepare_query_args()to usepost_status='any'for attachments instead of hardcoding 'inherit'. This ensures queries can find attachments regardless of their status ('inherit', 'publish', etc.), while the Model'sis_private()method handles privacy checks based on the attachment's parent and status.How the Fixes Work Together:
Does this close any currently open issues?
Tests
Issue #3438 (Media Item Privacy Inheritance)
Issue #1999 (Missing Attachments with 'publish' Status)
Before/After Examples
Before (Inconsistent Behavior - Issue #3438):
After (Consistent Behavior - Issue #3438):
Before (Missing Attachments - Issue #1999):
After (Attachments Found - Issue #1999):
Additional Context
Preserved Behavior (Issue #3438)
post_parent = 0) remain publicPreserved Behavior (Issue #1999)
is_private()method (fixed in Issue Unable to fetch draft media by slug #3438) handles privacy checks after the attachment is foundImplementation Details
Issue #3438:
Postmodel instance is created to check the parent's privacy statusIssue #1999:
PostObjectConnectionResolverto usepost_status='any'for all attachment queriesis_private()method (fixed in Issue Unable to fetch draft media by slug #3438) then handles privacy checks based on the attachment's parent and statusfeaturedImageconnections and directmediaItemsqueriesRelated Code
Issue #3438:
src/Model/Post.php- Modifiedis_private()method (lines 310-346)tests/wpunit/MediaItemQueriesTest.php- AddedtestMediaItemWithDraftParentInheritsPrivacy()andtestMediaItemWithPublishedParentRemainsPublic()testsIssue #1999:
src/Data/Connection/PostObjectConnectionResolver.php- Modifiedprepare_query_args()method to usepost_status='any'for attachments (line 216)tests/wpunit/MediaItemQueriesTest.php- AddedtestFeaturedImageBugScenarioWithInheritStatus(),testFeaturedImageBugScenarioWithPublishStatus(), andtestMediaItemsQueryWithPublishStatus()testsOverriding Behavior
If you need to make all media items public (regardless of parent status), you can use the
graphql_pre_model_data_is_privatefilter to override this behavior:Alternatively, you can use the
graphql_data_is_privatefilter to modify the privacy check after it's been determined: