Skip to content

Commit a30870a

Browse files
committed
refactor: align Chat REST handlers with core Abilities API contract
Replace require_ability/ability_response with a single execute_ability() helper that follows core's WP_Ability::execute() contract: - wp_get_ability() directly (no function_exists guard — WP 6.9 minimum) - Core's execute() handles input validation + permissions + callback - WP_Error pass-through for core failures - Legacy { success: false } array shim until abilities return WP_Error Every handler is now a one-liner: extract params → execute_ability(). No fallback paths, no duplicated logic, no intermediate variables.
1 parent c423c7a commit a30870a

1 file changed

Lines changed: 45 additions & 77 deletions

File tree

inc/Api/Chat/Chat.php

Lines changed: 45 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -361,24 +361,16 @@ public static function handle_ping( WP_REST_Request $request ) {
361361
* @return WP_REST_Response Response data.
362362
*/
363363
public static function list_sessions( WP_REST_Request $request ) {
364-
$ability = self::require_ability( 'datamachine/list-chat-sessions' );
365-
if ( is_wp_error( $ability ) ) {
366-
return $ability;
367-
}
368-
369-
$agent_id = PermissionHelper::resolve_scoped_agent_id( $request );
370-
371-
$result = $ability->execute(
364+
return self::execute_ability(
365+
'datamachine/list-chat-sessions',
372366
array(
373367
'user_id' => get_current_user_id(),
374-
'agent_id' => $agent_id,
368+
'agent_id' => PermissionHelper::resolve_scoped_agent_id( $request ),
375369
'limit' => (int) $request->get_param( 'limit' ),
376370
'offset' => (int) $request->get_param( 'offset' ),
377371
'context' => $request->get_param( 'context' ),
378372
)
379373
);
380-
381-
return self::ability_response( $result, 'list_sessions_failed' );
382374
}
383375

384376
/**
@@ -390,19 +382,13 @@ public static function list_sessions( WP_REST_Request $request ) {
390382
* @return WP_REST_Response|WP_Error Response data or error.
391383
*/
392384
public static function mark_session_read( WP_REST_Request $request ) {
393-
$ability = self::require_ability( 'datamachine/mark-session-read' );
394-
if ( is_wp_error( $ability ) ) {
395-
return $ability;
396-
}
397-
398-
$result = $ability->execute(
385+
return self::execute_ability(
386+
'datamachine/mark-session-read',
399387
array(
400388
'session_id' => sanitize_text_field( $request->get_param( 'session_id' ) ),
401389
'user_id' => get_current_user_id(),
402390
)
403391
);
404-
405-
return self::ability_response( $result, 'mark_read_failed' );
406392
}
407393

408394
/**
@@ -412,19 +398,13 @@ public static function mark_session_read( WP_REST_Request $request ) {
412398
* @return WP_REST_Response|WP_Error Response data or error.
413399
*/
414400
public static function delete_session( WP_REST_Request $request ) {
415-
$ability = self::require_ability( 'datamachine/delete-chat-session' );
416-
if ( is_wp_error( $ability ) ) {
417-
return $ability;
418-
}
419-
420-
$result = $ability->execute(
401+
return self::execute_ability(
402+
'datamachine/delete-chat-session',
421403
array(
422404
'session_id' => sanitize_text_field( $request->get_param( 'session_id' ) ),
423405
'user_id' => get_current_user_id(),
424406
)
425407
);
426-
427-
return self::ability_response( $result, 'delete_failed' );
428408
}
429409

430410
/**
@@ -434,19 +414,13 @@ public static function delete_session( WP_REST_Request $request ) {
434414
* @return WP_REST_Response|WP_Error Response data or error.
435415
*/
436416
public static function get_session( WP_REST_Request $request ) {
437-
$ability = self::require_ability( 'datamachine/get-chat-session' );
438-
if ( is_wp_error( $ability ) ) {
439-
return $ability;
440-
}
441-
442-
$result = $ability->execute(
417+
return self::execute_ability(
418+
'datamachine/get-chat-session',
443419
array(
444420
'session_id' => sanitize_text_field( $request->get_param( 'session_id' ) ),
445421
'user_id' => get_current_user_id(),
446422
)
447423
);
448-
449-
return self::ability_response( $result, 'get_failed' );
450424
}
451425

452426
/**
@@ -681,24 +655,23 @@ private static function resolve_attachment_paths( array $attachments ): array {
681655
}
682656

683657
/**
684-
* Resolve an ability by slug, returning WP_Error if unavailable.
658+
* Execute an ability and return the REST response.
659+
*
660+
* Resolves the ability by slug, calls execute() with the given input,
661+
* and converts the result into a REST response. Handles WP_Error returns
662+
* from core's execute() pipeline (input validation, permissions, callback).
685663
*
686-
* Centralizes the guard so handlers never duplicate the check.
664+
* For ability callbacks that still return { success: false, error: ... }
665+
* arrays (legacy convention), those are mapped to WP_Error. New abilities
666+
* should return WP_Error directly per core best practices.
687667
*
688668
* @since 0.62.0
689669
*
690-
* @param string $slug Ability slug (e.g. 'datamachine/get-chat-session').
691-
* @return \WP_Ability|WP_Error The ability instance or an error.
670+
* @param string $slug Ability slug (e.g. 'datamachine/get-chat-session').
671+
* @param array $input Input parameters for the ability.
672+
* @return WP_REST_Response|WP_Error
692673
*/
693-
private static function require_ability( string $slug ) {
694-
if ( ! function_exists( 'wp_get_ability' ) ) {
695-
return new WP_Error(
696-
'ability_unavailable',
697-
__( 'Abilities API not loaded.', 'data-machine' ),
698-
array( 'status' => 500 )
699-
);
700-
}
701-
674+
private static function execute_ability( string $slug, array $input = array() ) {
702675
$ability = wp_get_ability( $slug );
703676

704677
if ( ! $ability ) {
@@ -710,40 +683,35 @@ private static function require_ability( string $slug ) {
710683
);
711684
}
712685

713-
return $ability;
714-
}
686+
$result = $ability->execute( $input );
715687

716-
/**
717-
* Convert an ability result array into a REST response.
718-
*
719-
* On success wraps in `{ success: true, data: ... }`.
720-
* On failure maps the error code to an appropriate HTTP status.
721-
*
722-
* @since 0.62.0
723-
*
724-
* @param array $result Ability execute() return value.
725-
* @param string $default_error Fallback error code when result has none.
726-
* @return WP_REST_Response|WP_Error
727-
*/
728-
private static function ability_response( array $result, string $default_error = 'ability_failed' ) {
729-
if ( ! empty( $result['success'] ) ) {
730-
return rest_ensure_response(
731-
array(
732-
'success' => true,
733-
'data' => $result,
734-
)
735-
);
688+
// Core's execute() returns WP_Error for validation/permission/callback failures.
689+
if ( is_wp_error( $result ) ) {
690+
return $result;
736691
}
737692

738-
$error_code = $result['error'] ?? $default_error;
693+
// Legacy convention: ability callbacks return { success: false, error: ... }.
694+
// Map to WP_Error until all abilities are migrated to return WP_Error directly.
695+
if ( is_array( $result ) && isset( $result['success'] ) && ! $result['success'] ) {
696+
$error_code = $result['error'] ?? 'ability_failed';
739697

740-
$status_map = array(
741-
'session_not_found' => 404,
742-
'session_access_denied' => 403,
743-
);
698+
$status_map = array(
699+
'session_not_found' => 404,
700+
'session_access_denied' => 403,
701+
);
744702

745-
$status = $status_map[ $error_code ] ?? 500;
703+
return new WP_Error(
704+
$error_code,
705+
$result['error'] ?? 'Ability execution failed.',
706+
array( 'status' => $status_map[ $error_code ] ?? 500 )
707+
);
708+
}
746709

747-
return new WP_Error( $error_code, $result['error'] ?? $default_error, array( 'status' => $status ) );
710+
return rest_ensure_response(
711+
array(
712+
'success' => true,
713+
'data' => $result,
714+
)
715+
);
748716
}
749717
}

0 commit comments

Comments
 (0)