Skip to content

Commit 9824c6f

Browse files
Abilities API: Include initial core abilities and categories registration.
Without this patch we would introduce the Abilities API without any core abilities being registered. This patch includes the following initial abilities: - core/get-bloginfo - Retrieve individual site information fields (name, description, url, wpurl, admin_email, charset, language, version). - core/get-current-user-info - Get current authenticated user data (id, display_name, user_nicename, user_login, roles, locale). - core/get-environment-type - Get WordPress environment type (production, staging, development, local). Developed in #10411. Follow-up [64098]. Props gziolo, jorgefilipecosta, mukesh27, isotropic, jorbin, justlevine, jason_the_adams. Fixes #64146. git-svn-id: https://develop.svn.wordpress.org/trunk@61063 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 9d7752e commit 9824c6f

File tree

5 files changed

+455
-0
lines changed

5 files changed

+455
-0
lines changed
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
<?php
2+
/**
3+
* Core Abilities registration.
4+
*
5+
* @package WordPress
6+
* @subpackage Abilities_API
7+
* @since 6.9.0
8+
*/
9+
10+
declare( strict_types = 1 );
11+
/**
12+
* Registers the core ability categories.
13+
*
14+
* @since 6.9.0
15+
*
16+
* @return void
17+
*/
18+
function wp_register_core_ability_categories(): void {
19+
wp_register_ability_category(
20+
'site',
21+
array(
22+
'label' => __( 'Site' ),
23+
'description' => __( 'Abilities that retrieve or modify site information and settings.' ),
24+
)
25+
);
26+
27+
wp_register_ability_category(
28+
'user',
29+
array(
30+
'label' => __( 'User' ),
31+
'description' => __( 'Abilities that retrieve or modify user information and settings.' ),
32+
)
33+
);
34+
}
35+
36+
/**
37+
* Registers the default core abilities.
38+
*
39+
* @since 6.9.0
40+
*
41+
* @return void
42+
*/
43+
function wp_register_core_abilities(): void {
44+
$category_site = 'site';
45+
$category_user = 'user';
46+
47+
$site_info_fields = array(
48+
'name',
49+
'description',
50+
'url',
51+
'wpurl',
52+
'admin_email',
53+
'charset',
54+
'language',
55+
'version',
56+
);
57+
58+
wp_register_ability(
59+
'core/get-site-info',
60+
array(
61+
'label' => __( 'Get Site Information' ),
62+
'description' => __( 'Returns site information configured in WordPress. By default returns all fields, or optionally a filtered subset.' ),
63+
'category' => $category_site,
64+
'input_schema' => array(
65+
'type' => 'object',
66+
'properties' => array(
67+
'fields' => array(
68+
'type' => 'array',
69+
'items' => array(
70+
'type' => 'string',
71+
'enum' => $site_info_fields,
72+
),
73+
'description' => __( 'Optional: Limit response to specific fields. If omitted, all fields are returned.' ),
74+
),
75+
),
76+
'additionalProperties' => false,
77+
'default' => array(),
78+
),
79+
'output_schema' => array(
80+
'type' => 'object',
81+
'properties' => array(
82+
'name' => array(
83+
'type' => 'string',
84+
'description' => __( 'The site title.' ),
85+
),
86+
'description' => array(
87+
'type' => 'string',
88+
'description' => __( 'The site tagline.' ),
89+
),
90+
'url' => array(
91+
'type' => 'string',
92+
'description' => __( 'The site home URL.' ),
93+
),
94+
'wpurl' => array(
95+
'type' => 'string',
96+
'description' => __( 'The WordPress installation URL.' ),
97+
),
98+
'admin_email' => array(
99+
'type' => 'string',
100+
'description' => __( 'The site administrator email address.' ),
101+
),
102+
'charset' => array(
103+
'type' => 'string',
104+
'description' => __( 'The site character encoding.' ),
105+
),
106+
'language' => array(
107+
'type' => 'string',
108+
'description' => __( 'The site language locale code.' ),
109+
),
110+
'version' => array(
111+
'type' => 'string',
112+
'description' => __( 'The WordPress version.' ),
113+
),
114+
),
115+
'additionalProperties' => false,
116+
),
117+
'execute_callback' => static function ( $input = array() ) use ( $site_info_fields ): array {
118+
$input = is_array( $input ) ? $input : array();
119+
$requested_fields = ! empty( $input['fields'] ) ? $input['fields'] : $site_info_fields;
120+
121+
$result = array();
122+
foreach ( $requested_fields as $field ) {
123+
$result[ $field ] = get_bloginfo( $field );
124+
}
125+
126+
return $result;
127+
},
128+
'permission_callback' => static function (): bool {
129+
return current_user_can( 'manage_options' );
130+
},
131+
'meta' => array(
132+
'annotations' => array(
133+
'readonly' => true,
134+
'destructive' => false,
135+
'idempotent' => true,
136+
),
137+
'show_in_rest' => true,
138+
),
139+
)
140+
);
141+
142+
wp_register_ability(
143+
'core/get-user-info',
144+
array(
145+
'label' => __( 'Get User Information' ),
146+
'description' => __( 'Returns basic profile details for the current authenticated user to support personalization, auditing, and access-aware behavior.' ),
147+
'category' => $category_user,
148+
'output_schema' => array(
149+
'type' => 'object',
150+
'required' => array( 'id', 'display_name', 'user_nicename', 'user_login', 'roles', 'locale' ),
151+
'properties' => array(
152+
'id' => array(
153+
'type' => 'integer',
154+
'description' => __( 'The user ID.' ),
155+
),
156+
'display_name' => array(
157+
'type' => 'string',
158+
'description' => __( 'The display name of the user.' ),
159+
),
160+
'user_nicename' => array(
161+
'type' => 'string',
162+
'description' => __( 'The URL-friendly name for the user.' ),
163+
),
164+
'user_login' => array(
165+
'type' => 'string',
166+
'description' => __( 'The login username for the user.' ),
167+
),
168+
'roles' => array(
169+
'type' => 'array',
170+
'description' => __( 'The roles assigned to the user.' ),
171+
'items' => array(
172+
'type' => 'string',
173+
),
174+
),
175+
'locale' => array(
176+
'type' => 'string',
177+
'description' => __( 'The locale string for the user, such as en_US.' ),
178+
),
179+
),
180+
'additionalProperties' => false,
181+
),
182+
'execute_callback' => static function (): array {
183+
$current_user = wp_get_current_user();
184+
185+
return array(
186+
'id' => $current_user->ID,
187+
'display_name' => $current_user->display_name,
188+
'user_nicename' => $current_user->user_nicename,
189+
'user_login' => $current_user->user_login,
190+
'roles' => $current_user->roles,
191+
'locale' => get_user_locale( $current_user ),
192+
);
193+
},
194+
'permission_callback' => static function (): bool {
195+
return is_user_logged_in();
196+
},
197+
'meta' => array(
198+
'annotations' => array(
199+
'readonly' => true,
200+
'destructive' => false,
201+
'idempotent' => true,
202+
),
203+
'show_in_rest' => false,
204+
),
205+
)
206+
);
207+
208+
wp_register_ability(
209+
'core/get-environment-info',
210+
array(
211+
'label' => __( 'Get Environment Info' ),
212+
'description' => __( 'Returns core details about the site\'s runtime context for diagnostics and compatibility (environment, PHP runtime, database server info, WordPress version).' ),
213+
'category' => $category_site,
214+
'output_schema' => array(
215+
'type' => 'object',
216+
'required' => array( 'environment', 'php_version', 'db_server_info', 'wp_version' ),
217+
'properties' => array(
218+
'environment' => array(
219+
'type' => 'string',
220+
'description' => __( 'The site\'s runtime environment classification (can be one of these: production, staging, development, local).' ),
221+
'enum' => array( 'production', 'staging', 'development', 'local' ),
222+
),
223+
'php_version' => array(
224+
'type' => 'string',
225+
'description' => __( 'The PHP runtime version executing WordPress.' ),
226+
),
227+
'db_server_info' => array(
228+
'type' => 'string',
229+
'description' => __( 'The database server vendor and version string reported by the driver.' ),
230+
'examples' => array( '8.0.34', '10.11.6-MariaDB' ),
231+
),
232+
'wp_version' => array(
233+
'type' => 'string',
234+
'description' => __( 'The WordPress core version running on this site.' ),
235+
),
236+
),
237+
'additionalProperties' => false,
238+
),
239+
'execute_callback' => static function (): array {
240+
global $wpdb;
241+
242+
$env = wp_get_environment_type();
243+
$php_version = phpversion();
244+
$db_server_info = '';
245+
if ( method_exists( $wpdb, 'db_server_info' ) ) {
246+
$db_server_info = $wpdb->db_server_info() ?? '';
247+
}
248+
$wp_version = get_bloginfo( 'version' );
249+
250+
return array(
251+
'environment' => $env,
252+
'php_version' => $php_version,
253+
'db_server_info' => $db_server_info,
254+
'wp_version' => $wp_version,
255+
);
256+
},
257+
'permission_callback' => static function (): bool {
258+
return current_user_can( 'manage_options' );
259+
},
260+
'meta' => array(
261+
'annotations' => array(
262+
'readonly' => true,
263+
'destructive' => false,
264+
'idempotent' => true,
265+
),
266+
'show_in_rest' => true,
267+
),
268+
)
269+
);
270+
}

src/wp-includes/default-filters.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,10 @@
532532
add_action( 'rest_api_init', 'create_initial_rest_routes', 99 );
533533
add_action( 'parse_request', 'rest_api_loaded' );
534534

535+
// Abilities API.
536+
add_action( 'wp_abilities_api_categories_init', 'wp_register_core_ability_categories' );
537+
add_action( 'wp_abilities_api_init', 'wp_register_core_abilities' );
538+
535539
// Sitemaps actions.
536540
add_action( 'init', 'wp_sitemaps_get_server' );
537541

src/wp-settings.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
require ABSPATH . WPINC . '/abilities-api/class-wp-ability.php';
291291
require ABSPATH . WPINC . '/abilities-api/class-wp-abilities-registry.php';
292292
require ABSPATH . WPINC . '/abilities-api.php';
293+
require ABSPATH . WPINC . '/abilities/wp-core-abilities.php';
293294
require ABSPATH . WPINC . '/rest-api.php';
294295
require ABSPATH . WPINC . '/rest-api/class-wp-rest-server.php';
295296
require ABSPATH . WPINC . '/rest-api/class-wp-rest-response.php';

tests/phpunit/includes/functions.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,26 @@ function _unhook_font_registration() {
364364
remove_action( 'init', '_wp_register_default_font_collections' );
365365
}
366366
tests_add_filter( 'init', '_unhook_font_registration', 1000 );
367+
368+
/**
369+
* Before the abilities API categories init action runs, unhook the core ability
370+
* categories registration function to prevent core categories from being registered
371+
* during tests.
372+
*
373+
* @since 6.9.0
374+
*/
375+
function _unhook_core_ability_categories_registration() {
376+
remove_action( 'wp_abilities_api_categories_init', 'wp_register_core_ability_categories' );
377+
}
378+
tests_add_filter( 'wp_abilities_api_categories_init', '_unhook_core_ability_categories_registration', 1 );
379+
380+
/**
381+
* Before the abilities API init action runs, unhook the core abilities
382+
* registration function to prevent core abilities from being registered during tests.
383+
*
384+
* @since 6.9.0
385+
*/
386+
function _unhook_core_abilities_registration() {
387+
remove_action( 'wp_abilities_api_init', 'wp_register_core_abilities' );
388+
}
389+
tests_add_filter( 'wp_abilities_api_init', '_unhook_core_abilities_registration', 1 );

0 commit comments

Comments
 (0)