Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1bf6b0f
Add the core/media-query ability
jorgefilipecosta Oct 1, 2026
38795f9
Gate core/media-query behind the Custom Abilities experiment
jorgefilipecosta Oct 1, 2026
10bd2f1
Port the core REST attachment read tests
jorgefilipecosta Oct 1, 2026
1e58951
Add ability tests for core/media-query
jorgefilipecosta Oct 1, 2026
78673ec
Add an e2e spec for core/media-query
jorgefilipecosta Oct 1, 2026
1335f31
Port the core get item params test
jorgefilipecosta Oct 2, 2026
e39950e
Skip the password check on items the user can edit in the edit context
jorgefilipecosta Oct 2, 2026
c1cc367
Keep the password gate on generated captions in the edit context
jorgefilipecosta Oct 2, 2026
8540caa
Deny every request when attachments are hidden from REST
jorgefilipecosta Oct 2, 2026
1da9b8c
Leave the media type enum out when no MIME types are allowed
jorgefilipecosta Oct 2, 2026
f69317e
Remove the temporary filters even when a callback throws
jorgefilipecosta Oct 2, 2026
d03481d
Reset a bound global post instead of unsetting it
jorgefilipecosta Oct 2, 2026
5b0cf4f
Validate collection items against the item schema
jorgefilipecosta Oct 2, 2026
57b6e97
Correct the page and totals descriptions
jorgefilipecosta Oct 2, 2026
377b85f
Check that a gated caption does not reveal the description
jorgefilipecosta Oct 2, 2026
5345709
Fix a data set label
jorgefilipecosta Oct 2, 2026
471cc5a
Check the status code of a forbidden status list
jorgefilipecosta Oct 2, 2026
722a3d7
Stop sweeping uploads the tests never add
jorgefilipecosta Oct 2, 2026
56fa89a
Drop e2e filters the PHPUnit tests already cover
jorgefilipecosta Oct 2, 2026
7e3af1d
Fold the unknown field test into the unsupported input cases
jorgefilipecosta Oct 2, 2026
a0a279d
Drop the title search test the file name search port covers
jorgefilipecosta Oct 2, 2026
00abc5d
Drop string inputs the ported tests already cover
jorgefilipecosta Oct 2, 2026
ee7dff4
Merge the params subset test into its port
jorgefilipecosta Oct 2, 2026
9c97da8
Let create_fixture take post fields and use it for inline fixtures
jorgefilipecosta Oct 2, 2026
c407d60
Use the REST test case's error assertion
jorgefilipecosta Oct 2, 2026
afb11db
Register the category through the ability's own fallback in tests
jorgefilipecosta Oct 2, 2026
ae362ba
Reject unknown output properties like the sibling abilities
jorgefilipecosta Oct 2, 2026
8f1916c
Restore the global post the way the content ability does
jorgefilipecosta Oct 2, 2026
6914c20
Describe the page like the content ability
jorgefilipecosta Oct 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Keep the password gate on generated captions in the edit context
  • Loading branch information
jorgefilipecosta committed Oct 2, 2026
commit c1cc367752a62aeddc7675230f0d00f9a42aa7ef
46 changes: 1 addition & 45 deletions includes/Abilities/Media/Media.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ public function check_permission( $input = array() ): bool {
*
* {@see WP_Ability::execute()} always runs {@see self::check_permission()} first, so a
* single item is only looked up again here, while each collection row is checked. The
* global post, which each prepared item replaces, and the password check are restored
* afterwards.
* global post, which each prepared item replaces, is restored afterwards.
*
* @since x.x.x
*
Expand All @@ -205,11 +204,6 @@ public function execute_media_query( $input = array() ) {

try {
if ( isset( $request['id'] ) ) {
// Allow access to all password protected posts if the context is edit.
if ( 'edit' === $request['context'] ) {
add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 );
}

return $this->get_item( $request );
}

Expand All @@ -226,8 +220,6 @@ public function execute_media_query( $input = array() ) {

return $this->get_items( $request );
} finally {
remove_filter( 'post_password_required', array( $this, 'check_password_required' ) );

if ( $previous_post instanceof WP_Post ) {
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Restores the previous global post.
$GLOBALS['post'] = $previous_post;
Expand Down Expand Up @@ -334,32 +326,6 @@ private function get_items_permissions_check( array $request ): bool {
return 'edit' !== $request['context'] || ( $post_type && current_user_can( $post_type->cap->edit_posts ) ); // phpcs:ignore WordPress.WP.Capabilities.Undetermined -- Capability is resolved from the post type's capability object.
}

/**
* Overrides the result of the post password check for requested attachments.
*
* Allows users to read the content of password protected posts if they have the
* `edit_post` capability for the post being checked.
*
* @since x.x.x
*
* @param bool $required Whether the post requires a password check.
* @param \WP_Post|null $post The post been password checked.
* @return bool Result of password check taking into account the edit capability.
*/
public function check_password_required( $required, $post ) {
if ( ! $required ) {
return $required;
}

$post = get_post( $post );

if ( ! $post ) {
return $required;
}

return ! current_user_can( 'edit_post', $post->ID );
}

/**
* Retrieves a collection of attachments.
*
Expand Down Expand Up @@ -434,11 +400,6 @@ private function get_items( array $request ) {
/** @var \WP_Post[] $query_result The query does not ask for IDs only. */
$query_result = $posts_query->query( $query_args );

// Allow access to all password protected posts if the context is edit.
if ( 'edit' === $request['context'] ) {
add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 );
}

$posts = array();

update_post_author_caches( $query_result );
Expand All @@ -458,11 +419,6 @@ private function get_items( array $request ) {
$posts[] = $this->prepare_item_for_response( $post, $request );
}

// Reset filter.
if ( 'edit' === $request['context'] ) {
remove_filter( 'post_password_required', array( $this, 'check_password_required' ) );
}

$page = (int) ( $query_args['paged'] ?? 0 );
$total_posts = $posts_query->found_posts;

Expand Down
18 changes: 5 additions & 13 deletions tests/Integration/Includes/Abilities/Media/MediaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1759,12 +1759,12 @@ public function test_rendered_fields_apply_the_display_filters(): void {
}

/**
* With raw fields, the password of an item the user can edit does not gate its rendered
* caption, which core generates from the description when the caption is empty.
* Raw fields do not lift an item's password: the rendered caption, which core generates
* from the description when the caption is empty, stays gated.
*
* @since x.x.x
*/
public function test_raw_fields_unlock_password_protected_items_the_user_can_edit(): void {
public function test_raw_fields_keep_the_password_gate_on_generated_captions(): void {
$attachment_id = self::factory()->attachment->create_object(
self::$test_file,
0,
Expand All @@ -1784,17 +1784,9 @@ public function test_raw_fields_unlock_password_protected_items_the_user_can_edi
)
);
$collection = $this->execute( array( 'fields' => $fields ) );
$view = $this->execute(
array(
'id' => $attachment_id,
'fields' => array( 'caption_rendered' ),
)
);

$this->assertSame( "<p>Secret description</p>\n", $single['caption_rendered'], 'The single item should not be gated by the password.' );
$this->assertSame( "<p>Secret description</p>\n", $collection['media'][0]['caption_rendered'], 'The collection item should not be gated by the password.' );
$this->assertStringNotContainsString( 'Secret description', $view['caption_rendered'], 'Without raw fields, the password should gate the generated caption.' );
$this->assertTrue( post_password_required( $attachment_id ), 'The password gate should be restored afterwards.' );
$this->assertStringContainsString( 'password-protected', $single['caption_rendered'], 'The single item caption should stay gated.' );
$this->assertStringContainsString( 'password-protected', $collection['media'][0]['caption_rendered'], 'The collection item caption should stay gated.' );
}

/**
Expand Down
Loading