@@ -228,6 +228,47 @@ private function register_test_abilities(): void {
228228 )
229229 );
230230
231+ // Destructive ability (DELETE method).
232+ wp_register_ability (
233+ 'test/delete-user ' ,
234+ array (
235+ 'label ' => 'Delete User ' ,
236+ 'description ' => 'Deletes a user ' ,
237+ 'category ' => 'system ' ,
238+ 'input_schema ' => array (
239+ 'type ' => 'object ' ,
240+ 'properties ' => array (
241+ 'user_id ' => array (
242+ 'type ' => 'integer ' ,
243+ 'default ' => 0 ,
244+ ),
245+ ),
246+ ),
247+ 'output_schema ' => array (
248+ 'type ' => 'string ' ,
249+ 'required ' => true ,
250+ ),
251+ 'execute_callback ' => static function ( array $ input ) {
252+ $ user_id = $ input ['user_id ' ] ?? get_current_user_id ();
253+ $ user = get_user_by ( 'id ' , $ user_id );
254+ if ( ! $ user ) {
255+ return new WP_Error ( 'user_not_found ' , 'User not found ' );
256+ }
257+ return 'User successfully deleted! ' ;
258+ },
259+ 'permission_callback ' => static function () {
260+ return is_user_logged_in ();
261+ },
262+ 'meta ' => array (
263+ 'annotations ' => array (
264+ 'destructive ' => true ,
265+ 'idempotent ' => true ,
266+ ),
267+ 'show_in_rest ' => true ,
268+ ),
269+ )
270+ );
271+
231272 // Ability with contextual permissions
232273 wp_register_ability (
233274 'test/restricted ' ,
@@ -402,6 +443,27 @@ public function test_execute_readonly_ability_get(): void {
402443 $ this ->assertEquals ( self ::$ user_id , $ data ['id ' ] );
403444 }
404445
446+ /**
447+ * Test executing a destructive ability with GET.
448+ *
449+ * @ticket 64098
450+ */
451+ public function test_execute_destructive_ability_delete (): void {
452+ $ request = new WP_REST_Request ( 'DELETE ' , '/wp/v2/abilities/test/delete-user/run ' );
453+ $ request ->set_query_params (
454+ array (
455+ 'input ' => array (
456+ 'user_id ' => self ::$ user_id ,
457+ ),
458+ )
459+ );
460+
461+ $ response = $ this ->server ->dispatch ( $ request );
462+
463+ $ this ->assertEquals ( 200 , $ response ->get_status () );
464+ $ this ->assertEquals ( 'User successfully deleted! ' , $ response ->get_data () );
465+ }
466+
405467 /**
406468 * Test HTTP method validation for regular abilities.
407469 *
@@ -452,6 +514,24 @@ public function test_readonly_ability_requires_get(): void {
452514 $ this ->assertSame ( 'Read-only abilities require GET method. ' , $ data ['message ' ] );
453515 }
454516
517+ /**
518+ * Test HTTP method validation for destructive abilities.
519+ *
520+ * @ticket 64098
521+ */
522+ public function test_destructive_ability_requires_delete (): void {
523+ // Try POST on a destructive ability (should fail).
524+ $ request = new WP_REST_Request ( 'POST ' , '/wp/v2/abilities/test/delete-user/run ' );
525+ $ request ->set_header ( 'Content-Type ' , 'application/json ' );
526+ $ request ->set_body ( wp_json_encode ( array ( 'user_id ' => 1 ) ) );
527+
528+ $ response = $ this ->server ->dispatch ( $ request );
529+
530+ $ this ->assertSame ( 405 , $ response ->get_status () );
531+ $ data = $ response ->get_data ();
532+ $ this ->assertSame ( 'rest_ability_invalid_method ' , $ data ['code ' ] );
533+ $ this ->assertSame ( 'Abilities that perform destructive actions require DELETE method. ' , $ data ['message ' ] );
534+ }
455535
456536 /**
457537 * Test output validation against schema.
0 commit comments