Diff: STRATO-apps/wordpress_03/app/wp-includes/abilities-api/class-wp-abilities-registry.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
/**
3
+
* Abilities API
4
+
*
5
+
* Defines WP_Abilities_Registry class.
6
+
*
7
+
* @package WordPress
8
+
* @subpackage Abilities API
9
+
* @since 6.9.0
10
+
*/
11
+
12
+
declare( strict_types = 1 );
13
+
14
+
/**
15
+
* Manages the registration and lookup of abilities.
16
+
*
17
+
* @since 6.9.0
18
+
* @access private
19
+
*/
20
+
final class WP_Abilities_Registry {
21
+
/**
22
+
* The singleton instance of the registry.
23
+
*
24
+
* @since 6.9.0
25
+
* @var self|null
26
+
*/
27
+
private static $instance = null;
28
+
29
+
/**
30
+
* Holds the registered abilities.
31
+
*
32
+
* @since 6.9.0
33
+
* @var WP_Ability[]
34
+
*/
35
+
private $registered_abilities = array();
36
+
37
+
/**
38
+
* Registers a new ability.
39
+
*
40
+
* Do not use this method directly. Instead, use the `wp_register_ability()` function.
41
+
*
42
+
* @since 6.9.0
43
+
*
44
+
* @see wp_register_ability()
45
+
*
46
+
* @param string $name The name of the ability. The name must be a string containing a namespace
47
+
* prefix, i.e. `my-plugin/my-ability`. It can only contain lowercase
48
+
* alphanumeric characters, dashes and the forward slash.
49
+
* @param array<string, mixed> $args {
50
+
* An associative array of arguments for the ability.
51
+
*
52
+
* @type string $label The human-readable label for the ability.
53
+
* @type string $description A detailed description of what the ability does.
54
+
* @type string $category The ability category slug this ability belongs to.
55
+
* @type callable $execute_callback A callback function to execute when the ability is invoked.
56
+
* Receives optional mixed input and returns mixed result or WP_Error.
57
+
* @type callable $permission_callback A callback function to check permissions before execution.
58
+
* Receives optional mixed input and returns bool or WP_Error.
59
+
* @type array<string, mixed> $input_schema Optional. JSON Schema definition for the ability's input.
60
+
* @type array<string, mixed> $output_schema Optional. JSON Schema definition for the ability's output.
61
+
* @type array<string, mixed> $meta {
62
+
* Optional. Additional metadata for the ability.
63
+
*
64
+
* @type array<string, bool|null> $annotations {
65
+
* Optional. Semantic annotations describing the ability's behavioral characteristics.
66
+
* These annotations are hints for tooling and documentation.
67
+
*
68
+
* @type bool|null $readonly Optional. If true, the ability does not modify its environment.
69
+
* @type bool|null $destructive Optional. If true, the ability may perform destructive updates to its environment.
70
+
* If false, the ability performs only additive updates.
71
+
* @type bool|null $idempotent Optional. If true, calling the ability repeatedly with the same arguments
72
+
* will have no additional effect on its environment.
73
+
* }
74
+
* @type bool $show_in_rest Optional. Whether to expose this ability in the REST API. Default false.
75
+
* }
76
+
* @type string $ability_class Optional. Custom class to instantiate instead of WP_Ability.
77
+
* }
78
+
* @return WP_Ability|null The registered ability instance on success, null on failure.
79
+
*/
80
+
public function register( string $name, array $args ): ?WP_Ability {
81
+
if ( ! preg_match( '/^[a-z0-9-]+\/[a-z0-9-]+$/', $name ) ) {
82
+
_doing_it_wrong(
83
+
__METHOD__,
84
+
__(
85
+
'Ability name must be a string containing a namespace prefix, i.e. "my-plugin/my-ability". It can only contain lowercase alphanumeric characters, dashes and the forward slash.'
86
+
),
87
+
'6.9.0'
88
+
);
89
+
return null;
90
+
}
91
+
92
+
if ( $this->is_registered( $name ) ) {
93
+
_doing_it_wrong(
94
+
__METHOD__,
95
+
/* translators: %s: Ability name. */
96
+
sprintf( __( 'Ability "%s" is already registered.' ), esc_html( $name ) ),
97
+
'6.9.0'
98
+
);
99
+
return null;
100
+
}
101
+
102
+
/**
103
+
* Filters the ability arguments before they are validated and used to instantiate the ability.
104
+
*
105
+
* @since 6.9.0
106
+
*
107
+
* @param array<string, mixed> $args {
108
+
* An associative array of arguments for the ability.
109
+
*
110
+
* @type string $label The human-readable label for the ability.
111
+
* @type string $description A detailed description of what the ability does.
112
+
* @type string $category The ability category slug this ability belongs to.
113
+
* @type callable $execute_callback A callback function to execute when the ability is invoked.
114
+
* Receives optional mixed input and returns mixed result or WP_Error.
115
+
* @type callable $permission_callback A callback function to check permissions before execution.
116
+
* Receives optional mixed input and returns bool or WP_Error.
117
+
* @type array<string, mixed> $input_schema Optional. JSON Schema definition for the ability's input.
118
+
* @type array<string, mixed> $output_schema Optional. JSON Schema definition for the ability's output.
119
+
* @type array<string, mixed> $meta {
120
+
* Optional. Additional metadata for the ability.
121
+
*
122
+
* @type array<string, bool|string> $annotations Optional. Annotation metadata for the ability.
123
+
* @type bool $show_in_rest Optional. Whether to expose this ability in the REST API. Default false.
124
+
* }
125
+
* @type string $ability_class Optional. Custom class to instantiate instead of WP_Ability.
126
+
* }
127
+
* @param string $name The name of the ability, with its namespace.
128
+
*/
129
+
$args = apply_filters( 'wp_register_ability_args', $args, $name );
130
+
131
+
// Validate ability category exists if provided (will be validated as required in WP_Ability).
132
+
if ( isset( $args['category'] ) ) {
133
+
if ( ! wp_has_ability_category( $args['category'] ) ) {
134
+
_doing_it_wrong(
135
+
__METHOD__,
136
+
sprintf(
137
+
/* translators: %1$s: ability category slug, %2$s: ability name */
138
+
__( 'Ability category "%1$s" is not registered. Please register the ability category before assigning it to ability "%2$s".' ),
139
+
esc_html( $args['category'] ),
140
+
esc_html( $name )
141
+
),
142
+
'6.9.0'
143
+
);
144
+
return null;
145
+
}
146
+
}
147
+
148
+
// The class is only used to instantiate the ability, and is not a property of the ability itself.
149
+
if ( isset( $args['ability_class'] ) && ! is_a( $args['ability_class'], WP_Ability::class, true ) ) {
150
+
_doing_it_wrong(
151
+
__METHOD__,
152
+
__( 'The ability args should provide a valid `ability_class` that extends WP_Ability.' ),
153
+
'6.9.0'
154
+
);
155
+
return null;
156
+
}
157
+
158
+
/** @var class-string<WP_Ability> */
159
+
$ability_class = $args['ability_class'] ?? WP_Ability::class;
160
+
unset( $args['ability_class'] );
161
+
162
+
try {
163
+
// WP_Ability::prepare_properties() will throw an exception if the properties are invalid.
164
+
$ability = new $ability_class( $name, $args );
165
+
} catch ( InvalidArgumentException $e ) {
166
+
_doing_it_wrong(
167
+
__METHOD__,
168
+
$e->getMessage(),
169
+
'6.9.0'
170
+
);
171
+
return null;
172
+
}
173
+
174
+
$this->registered_abilities[ $name ] = $ability;
175
+
return $ability;
176
+
}
177
+
178
+
/**
179
+
* Unregisters an ability.
180
+
*
181
+
* Do not use this method directly. Instead, use the `wp_unregister_ability()` function.
182
+
*
183
+
* @since 6.9.0
184
+
*
185
+
* @see wp_unregister_ability()
186
+
*
187
+
* @param string $name The name of the registered ability, with its namespace.
188
+
* @return WP_Ability|null The unregistered ability instance on success, null on failure.
189
+
*/
190
+
public function unregister( string $name ): ?WP_Ability {
191
+
if ( ! $this->is_registered( $name ) ) {
192
+
_doing_it_wrong(
193
+
__METHOD__,
194
+
/* translators: %s: Ability name. */
195
+
sprintf( __( 'Ability "%s" not found.' ), esc_html( $name ) ),
196
+
'6.9.0'
197
+
);
198
+
return null;
199
+
}
200
+
201
+
$unregistered_ability = $this->registered_abilities[ $name ];
202
+
unset( $this->registered_abilities[ $name ] );
203
+
204
+
return $unregistered_ability;
205
+
}
206
+
207
+
/**
208
+
* Retrieves the list of all registered abilities.
209
+
*
210
+
* Do not use this method directly. Instead, use the `wp_get_abilities()` function.
211
+
*
212
+
* @since 6.9.0
213
+
*
214
+
* @see wp_get_abilities()
215
+
*
216
+
* @return WP_Ability[] The array of registered abilities.
217
+
*/
218
+
public function get_all_registered(): array {
219
+
return $this->registered_abilities;
220
+
}
221
+
222
+
/**
223
+
* Checks if an ability is registered.
224
+
*
225
+
* Do not use this method directly. Instead, use the `wp_has_ability()` function.
226
+
*
227
+
* @since 6.9.0
228
+
*
229
+
* @see wp_has_ability()
230
+
*
231
+
* @param string $name The name of the registered ability, with its namespace.
232
+
* @return bool True if the ability is registered, false otherwise.
233
+
*/
234
+
public function is_registered( string $name ): bool {
235
+
return isset( $this->registered_abilities[ $name ] );
236
+
}
237
+
238
+
/**
239
+
* Retrieves a registered ability.
240
+
*
241
+
* Do not use this method directly. Instead, use the `wp_get_ability()` function.
242
+
*
243
+
* @since 6.9.0
244
+
*
245
+
* @see wp_get_ability()
246
+
*
247
+
* @param string $name The name of the registered ability, with its namespace.
248
+
* @return WP_Ability|null The registered ability instance, or null if it is not registered.
249
+
*/
250
+
public function get_registered( string $name ): ?WP_Ability {
251
+
if ( ! $this->is_registered( $name ) ) {
252
+
_doing_it_wrong(
253
+
__METHOD__,
254
+
/* translators: %s: Ability name. */
255
+
sprintf( __( 'Ability "%s" not found.' ), esc_html( $name ) ),
256
+
'6.9.0'
257
+
);
258
+
return null;
259
+
}
260
+
return $this->registered_abilities[ $name ];
261
+
}
262
+
263
+
/**
264
+
* Utility method to retrieve the main instance of the registry class.
265
+
*
266
+
* The instance will be created if it does not exist yet.
267
+
*
268
+
* @since 6.9.0
269
+
*
270
+
* @return WP_Abilities_Registry|null The main registry instance, or null when `init` action has not fired.
271
+
*/
272
+
public static function get_instance(): ?self {
273
+
if ( ! did_action( 'init' ) ) {
274
+
_doing_it_wrong(
275
+
__METHOD__,
276
+
sprintf(
277
+
// translators: %s: init action.
278
+
__( 'Ability API should not be initialized before the %s action has fired.' ),
279
+
'<code>init</code>'
280
+
),
281
+
'6.9.0'
282
+
);
283
+
return null;
284
+
}
285
+
286
+
if ( null === self::$instance ) {
287
+
self::$instance = new self();
288
+
289
+
// Ensure ability category registry is initialized first to allow categories to be registered
290
+
// before abilities that depend on them.
291
+
WP_Ability_Categories_Registry::get_instance();
292
+
293
+
/**
294
+
* Fires when preparing abilities registry.
295
+
*
296
+
* Abilities should be created and register their hooks on this action rather
297
+
* than another action to ensure they're only loaded when needed.
298
+
*
299
+
* @since 6.9.0
300
+
*
301
+
* @param WP_Abilities_Registry $instance Abilities registry object.
302
+
*/
303
+
do_action( 'wp_abilities_api_init', self::$instance );
304
+
}
305
+
306
+
return self::$instance;
307
+
}
308
+
309
+
/**
310
+
* Wakeup magic method.
311
+
*
312
+
* @since 6.9.0
313
+
* @throws LogicException If the registry object is unserialized.
314
+
* This is a security hardening measure to prevent unserialization of the registry.
315
+
*/
316
+
public function __wakeup(): void {
317
+
throw new LogicException( __CLASS__ . ' should never be unserialized.' );
318
+
}
319
+
320
+
/**
321
+
* Sleep magic method.
322
+
*
323
+
* @since 6.9.0
324
+
* @throws LogicException If the registry object is serialized.
325
+
* This is a security hardening measure to prevent serialization of the registry.
326
+
*/
327
+
public function __sleep(): array {
328
+
throw new LogicException( __CLASS__ . ' should never be serialized.' );
329
+
}
330
+
}
331
+