-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathclass-wp-settings-abilities.php
More file actions
348 lines (306 loc) · 8.93 KB
/
class-wp-settings-abilities.php
File metadata and controls
348 lines (306 loc) · 8.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
<?php
/**
* Registers core settings abilities.
*
* This is a utility class to encapsulate the registration of settings-related abilities.
* It is not intended to be instantiated or consumed directly by any other code or plugin.
*
* @package WordPress
* @subpackage Abilities_API
* @since 7.0.0
*
* @internal This class is not part of the public API.
* @access private
*/
declare( strict_types=1 );
/**
* Registers core settings abilities.
*
* @since 7.0.0
* @access private
*/
class WP_Settings_Abilities {
/**
* Available setting groups with show_in_abilities enabled.
*
* @since 7.0.0
* @var string[]
*/
private static $available_groups;
/**
* Dynamic output schema built from registered settings.
*
* @since 7.0.0
* @var array
*/
private static $output_schema;
/**
* Available setting slugs with show_in_abilities enabled.
*
* @since 7.0.0
* @var string[]
*/
private static $available_slugs;
/**
* Registers all settings abilities.
*
* @since 7.0.0
*
* @return void
*/
public static function register(): void {
self::init();
self::register_get_settings();
}
/**
* Initializes shared data for settings abilities.
*
* @since 7.0.0
*
* @return void
*/
private static function init(): void {
self::$available_groups = self::get_available_groups();
self::$available_slugs = self::get_available_slugs();
self::$output_schema = self::build_output_schema();
}
/**
* Gets registered settings that have show_in_abilities enabled.
*
* @since 7.0.0
*
* @return array Associative array of option_name => args for allowed settings.
*/
private static function get_allowed_settings(): array {
$settings = array();
foreach ( get_registered_settings() as $option_name => $args ) {
if ( ! empty( $args['show_in_abilities'] ) ) {
$settings[ $option_name ] = $args;
}
}
return $settings;
}
/**
* Gets unique setting groups that have show_in_abilities enabled.
*
* @since 7.0.0
*
* @return string[] List of unique group names.
*/
private static function get_available_groups(): array {
$groups = array();
foreach ( self::get_allowed_settings() as $args ) {
$group = $args['group'] ?? 'general';
if ( ! in_array( $group, $groups, true ) ) {
$groups[] = $group;
}
}
sort( $groups );
return $groups;
}
/**
* Gets unique setting slugs that have show_in_abilities enabled.
*
* @since 7.0.0
*
* @return string[] List of unique setting slugs.
*/
private static function get_available_slugs(): array {
$slugs = array();
foreach ( self::get_allowed_settings() as $option_name => $args ) {
$slugs[] = $option_name;
}
sort( $slugs );
return $slugs;
}
/**
* Builds a rich output schema from registered settings metadata.
*
* Creates a JSON Schema that documents each setting group and its settings
* with their types, titles, descriptions, defaults, and any additional
* schema properties from show_in_abilities.
*
* @since 7.0.0
*
* @return array JSON Schema for the output.
*/
private static function build_output_schema(): array {
$group_properties = array();
foreach ( self::get_allowed_settings() as $option_name => $args ) {
$group = $args['group'] ?? 'general';
$setting_schema = array(
'type' => $args['type'] ?? 'string',
);
if ( ! empty( $args['label'] ) ) {
$setting_schema['title'] = $args['label'];
}
if ( ! empty( $args['description'] ) ) {
$setting_schema['description'] = $args['description'];
} elseif ( ! empty( $args['label'] ) ) {
$setting_schema['description'] = $args['label'];
}
// Merge custom schema from show_in_abilities if provided as an array.
if ( is_array( $args['show_in_abilities'] ) && ! empty( $args['show_in_abilities']['schema'] ) ) {
$setting_schema = array_merge( $setting_schema, $args['show_in_abilities']['schema'] );
}
if ( ! isset( $group_properties[ $group ] ) ) {
$group_properties[ $group ] = array(
'type' => 'object',
'properties' => array(),
'additionalProperties' => false,
);
}
$group_properties[ $group ]['properties'][ $option_name ] = $setting_schema;
}
ksort( $group_properties );
return array(
'type' => 'object',
'description' => __( 'Settings grouped by registration group. Each group contains settings with their current values.' ),
'properties' => $group_properties,
'additionalProperties' => false,
);
}
/**
* Registers the core/get-settings ability.
*
* @since 7.0.0
*
* @return void
*/
private static function register_get_settings(): void {
wp_register_ability(
'core/get-settings',
array(
'label' => __( 'Get Settings' ),
'description' => __( 'Returns registered WordPress settings grouped by their registration group. Returns key-value pairs per setting.' ),
'category' => 'site',
'input_schema' => array(
'default' => (object) array(),
'oneOf' => array(
// Branch 1: No filter (empty object).
array(
'type' => 'object',
'additionalProperties' => false,
'maxProperties' => 0,
),
// Branch 2: Filter by group only.
array(
'type' => 'object',
'properties' => array(
'group' => array(
'type' => 'string',
'description' => __( 'Filter settings by group name.' ),
'enum' => self::$available_groups,
),
),
'required' => array( 'group' ),
'additionalProperties' => false,
),
// Branch 3: Filter by slugs only.
array(
'type' => 'object',
'properties' => array(
'slugs' => array(
'type' => 'array',
'description' => __( 'Filter settings by specific setting slugs.' ),
'items' => array(
'type' => 'string',
'enum' => self::$available_slugs,
),
),
),
'required' => array( 'slugs' ),
'additionalProperties' => false,
),
),
),
'output_schema' => self::$output_schema,
'execute_callback' => array( __CLASS__, 'execute_get_settings' ),
'permission_callback' => array( __CLASS__, 'check_manage_options' ),
'meta' => array(
'annotations' => array(
'readonly' => true,
'destructive' => false,
'idempotent' => true,
),
'show_in_rest' => true,
),
)
);
}
/**
* Permission callback for settings abilities.
*
* @since 7.0.0
*
* @return bool True if the current user can manage options, false otherwise.
*/
public static function check_manage_options(): bool {
return current_user_can( 'manage_options' );
}
/**
* Execute callback for core/get-settings ability.
*
* Retrieves all registered settings that are exposed through the Abilities API,
* grouped by their registration group.
*
* @since 7.0.0
*
* @param array $input {
* Optional. Input parameters.
*
* @type string $group Optional. Filter settings by group name. Cannot be used with slugs.
* @type string[] $slugs Optional. Filter settings by specific setting slugs. Cannot be used with group.
* }
* @return array Settings grouped by registration group.
*/
public static function execute_get_settings( $input = array() ): array {
$input = is_array( $input ) ? $input : array();
$filter_group = ! empty( $input['group'] ) ? $input['group'] : null;
$filter_slugs = ! empty( $input['slugs'] ) ? $input['slugs'] : null;
$settings_by_group = array();
foreach ( self::get_allowed_settings() as $option_name => $args ) {
$group = $args['group'] ?? 'general';
if ( $filter_group && $group !== $filter_group ) {
continue;
}
if ( $filter_slugs && ! in_array( $option_name, $filter_slugs, true ) ) {
continue;
}
$default = $args['default'] ?? null;
$value = get_option( $option_name, $default );
$value = self::cast_value( $value, $args['type'] ?? 'string' );
if ( ! isset( $settings_by_group[ $group ] ) ) {
$settings_by_group[ $group ] = array();
}
$settings_by_group[ $group ][ $option_name ] = $value;
}
ksort( $settings_by_group );
return $settings_by_group;
}
/**
* Casts a value to the appropriate type based on the setting's registered type.
*
* @since 7.0.0
*
* @param mixed $value The value to cast.
* @param string $type The registered type (string, boolean, integer, number, array, object).
* @return string|bool|int|float|array The cast value.
*/
private static function cast_value( $value, string $type ) {
switch ( $type ) {
case 'boolean':
return (bool) $value;
case 'integer':
return (int) $value;
case 'number':
return (float) $value;
case 'array':
case 'object':
return is_array( $value ) ? $value : array();
case 'string':
default:
return (string) $value;
}
}
}