[^/]+)', and WP_REST_Server::dispatch() takes the first regex match in // registration order — so any literal registered after it is unreachable // (BUG-REST-ROUTE-ORDER-LITERAL-BEFORE-WILDCARD). AcrossAI_Abilities_Read_Controller::instance()->register_literal_routes(); AcrossAI_Abilities_Category_Controller::instance()->register_routes(); AcrossAI_Abilities_Write_Controller::instance()->register_routes(); AcrossAI_Abilities_Read_Controller::instance()->register_routes(); AcrossAI_Abilities_Exposure_Controller::instance()->register_routes(); AcrossAI_Quick_Connect_Controller::instance()->register_routes(); } /** * Verify manage_options capability and a valid REST nonce. * * Referenced by every sub-controller route as: * array( AcrossAI_Abilities_Rest_Controller::instance(), 'check_permission' ) * * @since 0.1.0 * @param \WP_REST_Request $request Incoming request. * @return bool|\WP_Error */ public function check_permission( \WP_REST_Request $request ) { if ( ! current_user_can( 'manage_options' ) ) { return new \WP_Error( 'rest_forbidden', __( 'You do not have permission to manage abilities.', 'acrossai-abilities-manager' ), array( 'status' => 403 ) ); } $nonce = $request->get_header( 'X-WP-Nonce' ); if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) { return new \WP_Error( 'rest_forbidden', __( 'Nonce verification failed.', 'acrossai-abilities-manager' ), array( 'status' => 403 ) ); } return true; } }