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