The conditionals. */ public static function get_conditionals() { return [ AI_Conditional::class ]; } /** * Class constructor. * * @param Content_Suggestion_Command_Handler $command_handler The command handler instance. */ public function __construct( Content_Suggestion_Command_Handler $command_handler ) { $this->command_handler = $command_handler; } /** * Registers routes with WordPress. * * @return void */ public function register_routes() { \register_rest_route( self::ROUTE_NAMESPACE, self::ROUTE_PREFIX, [ 'methods' => 'GET', 'args' => [ 'post_type' => [ 'required' => true, 'type' => 'string', 'description' => 'The post type to get content suggestions for.', ], 'language' => [ 'required' => true, 'type' => 'string', 'description' => 'The language the content is written in.', ], 'editor' => [ 'required' => true, 'type' => 'string', 'enum' => [ 'classic', 'elementor', 'gutenberg', ], 'description' => 'The current editor.', ], ], 'callback' => [ $this, 'get_suggestions' ], 'permission_callback' => [ $this, 'check_permissions' ], ], ); } /** * Runs the callback to get AI-generated content suggestions. * * @param WP_REST_Request $request The request object. * * @return WP_REST_Response The response of the get_suggestions action. */ public function get_suggestions( WP_REST_Request $request ): WP_REST_Response { try { $user = \wp_get_current_user(); $command = new Content_Suggestion_Command( $user, $request->get_param( 'post_type' ), $request->get_param( 'language' ), $request->get_param( 'editor' ), ); $data = $this->command_handler->handle( $command ); } catch ( Remote_Request_Exception $e ) { $message = [ 'message' => $e->getMessage(), 'errorIdentifier' => $e->get_error_identifier(), ]; if ( $e instanceof Payment_Required_Exception || $e instanceof Too_Many_Requests_Exception ) { $message['missingLicenses'] = $e->get_missing_licenses(); } return new WP_REST_Response( $message, $e->getCode(), ); } catch ( RuntimeException $e ) { return new WP_REST_Response( 'Failed to get content suggestions.', 500 ); } return new WP_REST_Response( $data->to_array() ); } /** * Checks if the user is logged in and can edit posts of the requested post type. * * The requested post_type is caller-controlled, so the permission must be evaluated * against that post type's own edit_posts meta-capability — not the generic * 'edit_posts' string, which would let a user with edit_posts but no edit_pages * (e.g. an Author) pull metadata for pages or arbitrary CPTs. * * @param WP_REST_Request $request The request object. * * @return bool Whether the user can edit posts of the requested post type. */ public function check_permissions( WP_REST_Request $request ): bool { $user = \wp_get_current_user(); if ( $user === null || $user->ID < 1 ) { return false; } $post_type = $request->get_param( 'post_type' ); $post_type_object = \get_post_type_object( $post_type ); if ( $post_type_object === null ) { return false; } return \user_can( $user, $post_type_object->cap->edit_posts ); } }