Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 19 additions & 20 deletions includes/Abilities/Content/Content.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
* so the two implementations stay in sync. Differences from the core class are marked with
* `// Plugin:` comments. Additionally, all user-facing strings use the 'ai' text domain.
*
* Plugin: the class is final and instance-based (with private helpers), matching the
* plugin's other ability classes (e.g. `Settings`) and core's `WP_Settings_Abilities`.
* Core's `WP_Content_Abilities` is still static; the structures are otherwise equivalent.
*
* @internal This class should not be used outside the plugin and there is no guarantee of backwards compatibility.
*
* @since 1.2.0
Expand Down Expand Up @@ -219,8 +215,10 @@ private function register_content_query(): void {
'readonly' => true,
'destructive' => false,
'idempotent' => true,
// MCP clients assume open-world (may reach external systems) when the
// hint is absent; this ability only reads the local database.
/*
* MCP clients assume open-world (may reach external systems) when the
* hint is absent; this ability only reads the local database.
*/
'open_world' => false,
),
'show_in_rest' => true,
Expand Down Expand Up @@ -629,8 +627,10 @@ public function execute_content_query( $input = array() ) {

$prime_post_caches = $this->should_prime_post_caches( $fields );

// `orderby` is left unset, which orders by `post_date` descending, matching the
// default of the REST posts controller.
/*
* `orderby` is left unset, which orders by `post_date` descending, matching the
* default of the REST posts controller.
*/
$query_args = array(
'post_type' => $post_type,
'post_status' => $this->normalize_statuses( $input ),
Expand Down Expand Up @@ -763,7 +763,7 @@ private function get_query_total( WP_Query $query, array $query_args, int $page
$count_args['posts_per_page'] = 1;
$count_args['update_post_meta_cache'] = false;
$count_args['update_post_term_cache'] = false;
unset( $count_args['paged'] );
unset( $count_args['paged'], $count_args['no_found_rows'] );

$count_query = new WP_Query( $count_args );

Expand Down Expand Up @@ -893,8 +893,10 @@ private function normalize_include( array $input ): array {
return array();
}

// A GET request delivers list inputs as scalar/CSV strings; wp_parse_id_list()
// accepts both and yields unique positive IDs, matching schema validation.
/*
* A GET request delivers list inputs as scalar/CSV strings; wp_parse_id_list()
* accepts both and yields unique positive IDs, matching schema validation.
*/
return array_values( array_filter( wp_parse_id_list( $include ) ) );
}

Expand Down Expand Up @@ -1454,13 +1456,11 @@ private function get_rendered_excerpt( WP_Post $post ): string {
* of the request.
*/
try {
/** This filter is documented in wp-includes/post-template.php. */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core excerpt filter to mirror REST rendering.
$excerpt = apply_filters( 'get_the_excerpt', $post->post_excerpt, $post );
/** This filter is documented in wp-includes/post-template.php */
$excerpt = apply_filters( 'get_the_excerpt', $post->post_excerpt, $post ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core excerpt filter to mirror REST rendering.

/** This filter is documented in wp-includes/post-template.php. */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core excerpt filter to mirror REST rendering.
$excerpt = apply_filters( 'the_excerpt', $excerpt );
/** This filter is documented in wp-includes/post-template.php */
$excerpt = apply_filters( 'the_excerpt', $excerpt ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core excerpt filter to mirror REST rendering.

return is_string( $excerpt ) ? $excerpt : '';
} finally {
Expand Down Expand Up @@ -1499,9 +1499,8 @@ private function get_rendered_content( WP_Post $post ): string {
* of the request.
*/
try {
/** This filter is documented in wp-includes/post-template.php. */
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core content filter to mirror REST rendering.
$content = apply_filters( 'the_content', $post->post_content );
/** This filter is documented in wp-includes/post-template.php */
$content = apply_filters( 'the_content', $post->post_content ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Applying the core content filter to mirror REST rendering.

return is_string( $content ) ? $content : '';
} finally {
Expand Down
76 changes: 36 additions & 40 deletions tests/Integration/Includes/Abilities/Content/ContentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,13 @@ private function ensure_ability_category( string $slug ): void {

global $wp_current_filter;
$wp_current_filter[] = 'wp_abilities_api_categories_init'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Faking the action context to register within it.
try {
wp_register_ability_category(
$slug,
array(
'label' => ucfirst( $slug ),
'description' => ucfirst( $slug ) . '.',
)
);
} finally {
array_pop( $wp_current_filter );
}
wp_register_ability_category(
$slug,
array(
'label' => ucfirst( $slug ),
'description' => ucfirst( $slug ) . '.',
)
);
}

/**
Expand All @@ -197,11 +193,7 @@ private function ensure_ability_category( string $slug ): void {
private function register_ability(): void {
global $wp_current_filter;
$wp_current_filter[] = 'wp_abilities_api_init'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Faking the action context to register within it.
try {
( new Content() )->register();
} finally {
array_pop( $wp_current_filter );
}
( new Content() )->register();
}

/**
Expand Down Expand Up @@ -283,22 +275,18 @@ public function test_does_not_register_core_content_query_ability_without_expose
public function test_override_replaces_existing_core_content_query(): void {
global $wp_current_filter;
$wp_current_filter[] = 'wp_abilities_api_init'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Faking the action context to register within it.
try {
wp_register_ability(
'core/content-query',
array(
'label' => 'Core Provided',
'description' => 'Core provided content ability.',
'category' => 'content',
'execute_callback' => static function (): array {
return array( 'posts' => array() );
},
'permission_callback' => '__return_true',
)
);
} finally {
array_pop( $wp_current_filter );
}
wp_register_ability(
'core/content-query',
array(
'label' => 'Core Provided',
'description' => 'Core provided content ability.',
'category' => 'content',
'execute_callback' => static function (): array {
return array( 'posts' => array() );
},
'permission_callback' => '__return_true',
)
);

$this->assertSame(
'Core Provided',
Expand Down Expand Up @@ -1150,8 +1138,10 @@ public function test_get_single_published_post_by_slug_can_return_content_fields
public function test_slug_lookup_is_not_bounded_by_a_page_size(): void {
global $wpdb;

// Author every post as the administrator, so the subscriber who reads them below can
// only see the published one.
/*
* Author every post as the administrator, so the subscriber who reads them below can
* only see the published one.
*/
$this->login_as( 'administrator' );

// The published post owns the slug and is the oldest of the group.
Expand All @@ -1163,8 +1153,10 @@ public function test_slug_lookup_is_not_bounded_by_a_page_size(): void {
)
);

// Drafts skip slug uniqueness, so they can all share the slug. Create more of them
// than the largest page the ability will ever return.
/*
* Drafts skip slug uniqueness, so they can all share the slug. Create more of them
* than the largest page the ability will ever return.
*/
for ( $i = 0; $i < 110; $i++ ) {
self::factory()->post->create(
array(
Expand Down Expand Up @@ -1202,8 +1194,10 @@ public function test_get_single_post_by_slug_zero(): void {
$this->login_as( 'administrator' );
$this->register_ability();

// Core regenerates an "empty" post_name from the title, so a post titled "0"
// ends up with the literal slug "0".
/*
* Core regenerates an "empty" post_name from the title, so a post titled "0"
* ends up with the literal slug "0".
*/
$post_id = self::factory()->post->create(
array(
'post_title' => '0',
Expand Down Expand Up @@ -2467,8 +2461,10 @@ public function test_query_keeps_posts_with_empty_field_projection(): void {
$this->login_as( 'administrator' );
$this->register_ability();

// `parent` never applies to the non-hierarchical `post` type, so every row
// projects to an empty object.
/*
* `parent` never applies to the non-hierarchical `post` type, so every row
* projects to an empty object.
*/
$result = wp_get_ability( 'core/content-query' )->execute(
array(
'post_type' => 'post',
Expand Down
Loading