'POST', 'callback' => array( $this, 'generate' ), 'permission_callback' => array( $this, 'check_edit_permission' ), 'args' => array( 'prompt' => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field', ), 'model' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '', ), 'aspect_ratio' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '1:1', ), 'image_size' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '1K', ), 'count' => array( 'type' => 'integer', 'default' => 1, 'minimum' => 1, 'maximum' => 4, ), ), ) ); register_rest_route( self::NAMESPACE, '/save', array( 'methods' => 'POST', 'callback' => array( $this, 'save' ), 'permission_callback' => array( $this, 'check_upload_permission' ), 'args' => array( 'image_data' => array( 'required' => true, 'type' => 'string', ), 'mime_type' => array( 'type' => 'string', 'default' => 'image/png', ), 'prompt' => array( 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_textarea_field', ), 'model' => array( 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field', ), ), ) ); register_rest_route( self::NAMESPACE, '/edit', array( 'methods' => 'POST', 'callback' => array( $this, 'edit' ), 'permission_callback' => array( $this, 'check_upload_permission' ), 'args' => array( 'attachment_id' => array( 'required' => true, 'type' => 'integer', ), 'prompt' => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field', ), ), ) ); } /** * Permission check: user can edit posts. * * @return bool */ public function check_edit_permission() { return current_user_can( 'edit_posts' ); } /** * Permission check: user can upload files. * * @return bool */ public function check_upload_permission() { return current_user_can( 'upload_files' ); } /** * Generate images. * * @param WP_REST_Request $request Request object. * @return WP_REST_Response|WP_Error */ public function generate( $request ) { $api = new Nano_Banana_API(); $images = $api->generate_image( $request['prompt'], array( 'model' => $request['model'], 'aspect_ratio' => $request['aspect_ratio'], 'image_size' => $request['image_size'], 'count' => $request['count'], ) ); if ( is_wp_error( $images ) ) { return $images; } $results = array(); foreach ( $images as $image ) { $results[] = array( 'data' => base64_encode( $image['data'] ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode 'mimeType' => $image['mime_type'], ); } $model = ! empty( $request['model'] ) ? $request['model'] : get_option( 'nano_banana_model' ); Nano_Banana_History::log_generation( $request['prompt'], $model, count( $images ) ); return rest_ensure_response( $results ); } /** * Save an image to the Media Library. * * @param WP_REST_Request $request Request object. * @return WP_REST_Response|WP_Error */ public function save( $request ) { $image_data = array( 'data' => base64_decode( $request['image_data'] ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode 'mime_type' => $request['mime_type'], ); $api = new Nano_Banana_API(); $attach_id = $api->save_to_media_library( $image_data, $request['prompt'], $request['model'] ); if ( is_wp_error( $attach_id ) ) { return $attach_id; } return rest_ensure_response( array( 'attachmentId' => $attach_id, 'url' => wp_get_attachment_url( $attach_id ), ) ); } /** * Edit an existing image. * * @param WP_REST_Request $request Request object. * @return WP_REST_Response|WP_Error */ public function edit( $request ) { $attachment_id = $request['attachment_id']; if ( ! current_user_can( 'edit_post', $attachment_id ) ) { return new WP_Error( 'forbidden', __( 'You do not have permission to edit this attachment.', '45squared-ai-powered-image-generator' ), array( 'status' => 403 ) ); } if ( ! wp_attachment_is_image( $attachment_id ) ) { return new WP_Error( 'invalid_attachment', __( 'Not a valid image attachment.', '45squared-ai-powered-image-generator' ), array( 'status' => 400 ) ); } $file_path = get_attached_file( $attachment_id ); if ( ! $file_path || ! file_exists( $file_path ) ) { return new WP_Error( 'file_not_found', __( 'Source image not found.', '45squared-ai-powered-image-generator' ), array( 'status' => 404 ) ); } $api = new Nano_Banana_API(); $result = $api->edit_image( $file_path, $request['prompt'] ); if ( is_wp_error( $result ) ) { return $result; } $model = get_option( 'nano_banana_model', 'gemini-3.1-flash-image-preview' ); $attach_id = $api->save_to_media_library( $result, $request['prompt'] . ' (edited)', $model ); if ( is_wp_error( $attach_id ) ) { return $attach_id; } Nano_Banana_History::log_generation( $request['prompt'], $model, 1, 'edit' ); return rest_ensure_response( array( 'attachmentId' => $attach_id, 'url' => wp_get_attachment_url( $attach_id ), ) ); } }