SILENT KILLERPanel

Current Path: > home > codekrsu > > ameliagraphics.com > wp-content > plugins > essential-blocks > > includes > Admin


Operation   : Linux premium131.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64
Software     : Apache
Server IP    : 162.0.232.56 | Your IP: 216.73.216.111
Domains      : 1034 Domain(s)
Permission   : [ 0755 ]

Files and Folders in: /home/codekrsu//ameliagraphics.com/wp-content/plugins/essential-blocks//includes/Admin

NameTypeSizeLast ModifiedActions
Admin.php File 44627 bytes July 27 2025 13:25:28.
OpenAI.php File 36174 bytes July 27 2025 13:25:28.
QuickSetup.php File 5445 bytes April 23 2025 15:48:10.
whats-new-notice.php File 4631 bytes July 27 2025 13:25:28.

Reading File: /home/codekrsu//ameliagraphics.com/wp-content/plugins/essential-blocks//includes/Admin/OpenAI.php

<?php

namespace EssentialBlocks\Admin;

/**
 * OpenAI API Integration for Essential Blocks
 *
 * This class handles the integration with OpenAI API for content generation
 */
class OpenAI
{
    /**
     * API Key for OpenAI
     *
     * @var string
     */
    private $api_key;

    /**
     * Maximum number of tokens to generate
     *
     * @var int
     */
    private $max_tokens = 1500;

    /**
     * API Endpoint for OpenAI Chat Completions
     *
     * @var string
     */
    private $api_endpoint = 'https://api.openai.com/v1/chat/completions';

    /**
     * API Endpoint for OpenAI Image Generation (DALL-E)
     *
     * @var string
     */
    private $image_api_endpoint = 'https://api.openai.com/v1/images/generations';

    /**
     * Model to use for OpenAI text generation
     * //TODO: Add support for other models
     *
     * @var string
     */
    private $model = 'gpt-4o-mini';

    /**
     * Model to use for OpenAI image generation
     *
     * @var string
     */
    private $image_model = 'dall-e-3';

    /**
     * Default image size for DALL-E
     *
     * @var string
     */
    private $image_size = '1024x1024';

    /**
     * Default image quality for DALL-E
     *
     * @var string
     */
    private $image_quality = 'standard';

    /**
     * Constructor
     */
    public function __construct()
    {
        // Get API key from options
        $eb_write_with_ai = (array) get_option( 'eb_write_with_ai', [  ] );
        if ( ! empty( $eb_write_with_ai[ 'apiKey' ] ) ) {
            $this->set_api_key( $eb_write_with_ai[ 'apiKey' ] );
        }

        if ( isset( $eb_write_with_ai[ 'maxTokens' ] ) && intval( $eb_write_with_ai[ 'maxTokens' ] ) > 0 ) {
            $this->max_tokens = intval( $eb_write_with_ai[ 'maxTokens' ] );
        }
    }

    /**
     * Set API Key
     *
     * @param string $api_key
     * @return void
     */
    public function set_api_key( $api_key )
    {
        $this->api_key = $api_key;
    }

    /**
     * Set Max Tokens
     *
     * @param int $max_tokens
     * @return void
     */
    public function set_max_tokens( $max_tokens )
    {
        $this->max_tokens = intval( $max_tokens );
    }

    /**
     * Validate API Key
     *
     * Makes a simple request to the OpenAI API to validate the API key
     *
     * @param string $api_key The API key to validate
     * @return array Response with status and message
     */
    public function validate_api_key( $api_key )
    {
        if ( empty( $api_key ) ) {
            return [
                'success' => false,
                'message' => __( 'API key is required.', 'essential-blocks' )
             ];
        }

        // Make a simple request to the OpenAI API to validate the key
        $response = wp_remote_post(
            'https://api.openai.com/v1/chat/completions',
            [
                'headers' => [
                    'Content-Type'  => 'application/json',
                    'Authorization' => 'Bearer ' . $api_key
                 ],
                'body'    => wp_json_encode( [
                    'model'      => $this->model,
                    'messages'   => [
                        [
                            'role'    => 'user',
                            'content' => 'Hello'
                         ]
                     ],
                    'max_tokens' => 5
                 ] ),
                'timeout' => 15
             ]
        );

        // Check for errors
        if ( is_wp_error( $response ) ) {
            return [
                'success' => false,
                'message' => $response->get_error_message()
             ];
        }

        // Parse the response
        $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
        $response_code = wp_remote_retrieve_response_code( $response );

        // Check if the response is valid
        if ( $response_code !== 200 ) {
            $error_message = isset( $response_body[ 'error' ][ 'message' ] )
            ? $response_body[ 'error' ][ 'message' ]
            : __( 'Invalid API key or API error.', 'essential-blocks' );

            return [
                'success' => false,
                'message' => $error_message
             ];
        }

        return [
            'success' => true,
            'message' => __( 'API key is valid.', 'essential-blocks' )
         ];
    }

    /**
     * Generate content using OpenAI API
     *
     * @param string $prompt The complete prompt for content generation
     * @return array Response with status and content
     */
    public function generate_content( $prompt, $writePageContent = 'writePageContent' )
    {
        // Get AI settings
        $eb_write_with_ai = (array) get_option( 'eb_write_with_ai', [  ] );

        // Check if AI is enabled
        $is_ai_enabled_for_page_content = isset( $eb_write_with_ai[ 'writePageContent' ] ) ? $eb_write_with_ai[ 'writePageContent' ] : true;
        $is_ai_enabled_for_richtext     = isset( $eb_write_with_ai[ 'writeRichtext' ] ) ? $eb_write_with_ai[ 'writeRichtext' ] : true;
        $is_ai_enabled_for_input_fields = isset( $eb_write_with_ai[ 'writeInputFields' ] ) ? $eb_write_with_ai[ 'writeInputFields' ] : true;
        if ( $writePageContent === 'writePageContent' && ! $is_ai_enabled_for_page_content ) {
            return [
                'success' => false,
                'message' => __( 'AI page content generation is disabled. Please enable it in the settings.', 'essential-blocks' )
             ];
        } elseif ( $writePageContent === 'writeRichtext' && ! $is_ai_enabled_for_richtext ) {
            return [
                'success' => false,
                'message' => __( 'AI richtext content generation is disabled. Please enable it in the settings.', 'essential-blocks' )
             ];
        } elseif ( $writePageContent === 'writeInputFields' && ! $is_ai_enabled_for_input_fields ) {
            return [
                'success' => false,
                'message' => __( 'AI input fieldcontent generation is disabled. Please enable it in the settings.', 'essential-blocks' )
             ];
        }

        // Check if API key is set
        if ( empty( $this->api_key ) ) {
            return [
                'success' => false,
                'message' => __( 'OpenAI API key is not set. Please set it in the settings.', 'essential-blocks' )
             ];
        }

        // Prepare the request body
        $body = [
            'model'       => $this->model,
            'messages'    => [
                [
                    'role'    => 'user',
                    'content' => $prompt
                 ]
             ],
            'temperature' => 0.7,
            'max_tokens'  => $this->max_tokens
         ];

        // Make the API request
        $response = wp_remote_post(
            $this->api_endpoint,
            [
                'headers'     => [
                    'Content-Type'  => 'application/json',
                    'Authorization' => 'Bearer ' . $this->api_key
                 ],
                'body'        => wp_json_encode( $body ),
                'timeout'     => 60,
                'data_format' => 'body'
             ]
        );

        // error_log( print_r( $response, true ) );

        // Check for errors
        if ( is_wp_error( $response ) ) {
            return [
                'success' => false,
                'message' => $response->get_error_message()
             ];
        }

        // Parse the response
        $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
        $response_code = wp_remote_retrieve_response_code( $response );

        // Check if the response is valid
        if ( $response_code !== 200 || ! isset( $response_body[ 'choices' ][ 0 ][ 'message' ][ 'content' ] ) ) {
            $error_message = isset( $response_body[ 'error' ][ 'message' ] )
            ? $response_body[ 'error' ][ 'message' ]
            : __( 'Unknown error occurred while generating content.', 'essential-blocks' );

            return [
                'success'  => false,
                'message'  => $error_message,
                'response' => $response_body
             ];
        }

        // Return the generated content
        return [
            'success' => true,
            'content' => $response_body[ 'choices' ][ 0 ][ 'message' ][ 'content' ],
            'usage'   => isset( $response_body[ 'usage' ] ) ? $response_body[ 'usage' ] : null
         ];
    }

    /**
     * Convert string compression values to numeric values
     *
     * @param string $compression The compression level (high, medium, low, or numeric value)
     * @return int The numeric compression value
     */
    private function convert_compression_to_numeric( $compression )
    {
        // If it's already numeric, return as integer
        if ( is_numeric( $compression ) ) {
            return intval( $compression );
        }

        // Convert string values to numeric
        switch ( strtolower( trim( $compression ) ) ) {
            case 'high':
                return 100;
            case 'medium':
                return 75;
            case 'low':
                return 50;
            case 'standard':
            default:
                return 100; // Default to high quality
        }
    }

    /**
     * Generate image using OpenAI DALL-E API
     *
     * @param string $prompt The prompt for image generation
     * @param string $model The model to use (dall-e-2, dall-e-3)
     * @param string $size Image size (varies by model)
     * @param string $quality Image quality (standard, hd)
     * @param string $style Image style (vivid, natural) - DALL-E 3 only
     * @param string $writePageContent Context for AI settings check
     * @param string $background Background handling option
     * @param string $output_format Image output format (png, jpeg, webp)
     * @param string $output_compression Compression level for the output
     * @return array Response with status and image URL/base64
     */
    public function generate_image( $prompt, $model = 'gpt-image-1', $size = '1024x1024', $quality = 'standard', $style = 'vivid', $writePageContent = 'writePageContent', $background = '', $output_format = 'png', $output_compression = 'standard', $image_count = 2 )
    {
        // Get AI settings
        $eb_write_with_ai = (array) get_option( 'eb_write_with_ai', [  ] );

        // Check if AI is enabled for image generation
        $is_ai_enabled_for_image = isset( $eb_write_with_ai[ 'generateImage' ] ) ? $eb_write_with_ai[ 'generateImage' ] : true;

        if ( ! $is_ai_enabled_for_image ) {
            return [
                'success' => false,
                'message' => __( 'AI Image generation is disabled. Please enable it in the settings.', 'essential-blocks' )
             ];
        }

        // Check if API key is set
        if ( empty( $this->api_key ) ) {
            return [
                'success' => false,
                'message' => __( 'OpenAI API key is not set. Please set it in the settings.', 'essential-blocks' )
             ];
        }

        // Validate prompt
        if ( empty( $prompt ) || ! is_string( $prompt ) ) {
            return [
                'success' => false,
                'message' => __( 'Image prompt is required and must be a valid string.', 'essential-blocks' )
             ];
        }

        // Validate and sanitize prompt length (DALL-E has a 1000 character limit)
        if ( strlen( $prompt ) > 1000 ) {
            return [
                'success' => false,
                'message' => __( 'Image prompt must be 1000 characters or less.', 'essential-blocks' )
             ];
        }

        // Implement intelligent model selection based on parameters
        // $model = $this->determine_optimal_model( $model, $size, $quality, $style, $background, $output_format, $output_compression );

        // Validate model
        $valid_models = [ 'dall-e-2', 'dall-e-3', 'gpt-image-1' ];
        if ( ! in_array( $model, $valid_models ) ) {
            $model = $this->image_model; // fallback to default
        }

        // Validate image size based on model
        if ( $model === 'dall-e-2' ) {
            $valid_sizes = [ '256x256', '512x512', '1024x1024' ];
        } else { // dall-e-3
            $valid_sizes = [ '1024x1024', '1792x1024', '1024x1792' ];
        }

        if ( ! in_array( $size, $valid_sizes ) ) {
            $size = $model === 'dall-e-2' ? '1024x1024' : '1024x1024'; // fallback to default
        }

        // Filter and validate parameters based on selected model
        $filtered_params = $this->filter_parameters_by_model( $model, $size, $quality, $style, $background, $output_format, $output_compression );

        // Extract filtered parameters
        $size               = $filtered_params[ 'size' ];
        $quality            = $filtered_params[ 'quality' ];
        $style              = $filtered_params[ 'style' ];
        $background         = $filtered_params[ 'background' ];
        $output_format      = $filtered_params[ 'output_format' ];
        $output_compression = $filtered_params[ 'output_compression' ];

        // Convert output_compression from string to numeric if needed
        $output_compression = $this->convert_compression_to_numeric( $output_compression );

        // Validate and set image count based on model capabilities
        $validated_image_count = $image_count;
        if ( $model === 'dall-e-3' && $image_count > 1 ) {
            $validated_image_count = 1; // DALL-E 3 only supports 1 image per request
        } elseif ( $image_count < 1 || $image_count > 10 ) {
            $validated_image_count = 2; // Default fallback
        }

        // Prepare the request body with filtered parameters
        $body = [
            'model'           => $model,
            'prompt'          => $prompt,
            'n'               => $validated_image_count, // number of images to generate
            'size'            => $size,
            'response_format' => 'b64_json' // url or b64_json
         ];

        // Add model-specific parameters based on capabilities
        switch ( $model ) {
            case 'dall-e-2':
                // DALL-E 2 only supports basic parameters
                break;

            case 'dall-e-3':
                // DALL-E 3 supports quality and style
                if ( ! empty( $quality ) && $quality !== 'standard' ) {
                    $body[ 'quality' ] = $quality;
                }
                if ( ! empty( $style ) && $style !== 'none' ) {
                    $body[ 'style' ] = $style;
                }
                // Note: 'n' is already set above with validated count (always 1 for dall-e-3)
                break;

            case 'gpt-image-1':
                // GPT-Image-1 supports additional parameters
                if ( ! empty( $background ) && $background !== 'auto' ) {
                    $body[ 'background' ] = $background;
                }
                if ( ! empty( $output_format ) && $output_format !== 'png' ) {
                    $body[ 'output_format' ] = $output_format;
                }
                if ( ! empty( $output_compression ) ) {
                    $body[ 'output_compression' ] = $output_compression;
                }
                if ( ! empty( $quality ) && $quality !== 'medium' ) {
                    $body[ 'quality' ] = $quality;
                }
                unset( $body[ 'response_format' ] );
                break;
        }
        error_log( 'GPT Model: ' . $model );
        error_log( 'GPT Body: ' . print_r( $body, true ) );

        // return;
        // wp_die();

        // Make the API request
        $response = wp_remote_post(
            $this->image_api_endpoint,
            [
                'headers'     => [
                    'Content-Type'  => 'application/json',
                    'Authorization' => 'Bearer ' . $this->api_key
                 ],
                'body'        => wp_json_encode( $body ),
                'timeout'     => 180,
                'data_format' => 'body'
             ]
        );

        error_log( 'Response-----' . print_r( $response, true ) );

        // Check for errors
        if ( is_wp_error( $response ) ) {
            return [
                'success' => false,
                'message' => $response->get_error_message()
             ];
        }

        // Parse the response
        $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
        $response_code = wp_remote_retrieve_response_code( $response );

        // Check if the response is valid - handle both 'url' and 'b64_json' formats
        if ( $response_code !== 200 || ! isset( $response_body[ 'data' ][ 0 ] ) ) {
            $error_message = isset( $response_body[ 'error' ][ 'message' ] )
            ? $response_body[ 'error' ][ 'message' ]
            : __( 'Unknown error occurred while generating image.', 'essential-blocks' );

            return [
                'success'  => false,
                'message'  => $error_message,
                'response' => $response_body
             ];
        }

        // Check if first image has either url or b64_json
        $first_image = $response_body[ 'data' ][ 0 ];
        if ( ! isset( $first_image[ 'url' ] ) && ! isset( $first_image[ 'b64_json' ] ) ) {
            return [
                'success'  => false,
                'message'  => __( 'Invalid image data received from OpenAI API.', 'essential-blocks' ),
                'response' => $response_body
             ];
        }

        // Process all generated images
        $images = [  ];
        foreach ( $response_body[ 'data' ] as $index => $image_data ) {
            // Handle both URL and base64 formats
            $image_url = null;
            $image_b64 = null;

            if ( isset( $image_data[ 'url' ] ) ) {
                $image_url = $image_data[ 'url' ];
            } elseif ( isset( $image_data[ 'b64_json' ] ) ) {
                $image_b64 = $image_data[ 'b64_json' ];
            }

            $revised_prompt = isset( $image_data[ 'revised_prompt' ] ) ? $image_data[ 'revised_prompt' ] : $prompt;

            // Generate metadata for each image
            $metadata = $this->generate_image_metadata( $revised_prompt, $prompt );

            $images[  ] = [
                'image_url'      => $image_url,
                'image_b64'      => $image_b64,
                'revised_prompt' => $revised_prompt,
                'title'          => $metadata[ 'title' ],
                'alt_tag'        => $metadata[ 'alt_tag' ],
                'caption'        => $metadata[ 'caption' ],
                'description'    => $metadata[ 'description' ]
             ];
        }

        // Extract usage information from the API response
        $usage_info = $this->extract_image_usage_info( $response_body, $model, $validated_image_count );
        error_log( 'Usage Info: ' . print_r( $usage_info, true ) );

        // Return all generated images with usage information
        return [
            'success' => true,
            'images'  => $images,
            'usage'   => $usage_info
         ];
    }

    /**
     * Extract usage information from OpenAI image generation API response
     *
     * @param array $response_body The API response body
     * @param string $model The model used for generation
     * @param int $image_count The number of images generated
     * @return array Usage information with formatted message
     */
    private function extract_image_usage_info( $response_body, $model, $image_count )
    {
        // Check if usage information is available in the response
        if ( isset( $response_body[ 'usage' ] ) ) {
            $usage = $response_body[ 'usage' ];

            // Extract token information
            $input_tokens  = isset( $usage[ 'input_tokens' ] ) ? intval( $usage[ 'input_tokens' ] ) : 0;
            $output_tokens = isset( $usage[ 'output_tokens' ] ) ? intval( $usage[ 'output_tokens' ] ) : 0;
            $total_tokens  = isset( $usage[ 'total_tokens' ] ) ? intval( $usage[ 'total_tokens' ] ) : ( $input_tokens + $output_tokens );

            // Create user-friendly usage message
            $usage_message = sprintf(
                __( 'Using %s model, you consumed %d input tokens and %d output tokens for generating %d image(s).', 'essential-blocks' ),
                strtoupper( $model ),
                $input_tokens,
                $output_tokens,
                $image_count
            );

            return [
                'input_tokens'  => $input_tokens,
                'output_tokens' => $output_tokens,
                'total_tokens'  => $total_tokens,
                'message'       => $usage_message,
                'raw_usage'     => $usage
             ];
        }

        // Fallback when usage information is not available
        $fallback_message = sprintf(
            __( 'Successfully generated %d image(s) using %s model. Token usage information not available.', 'essential-blocks' ),
            $image_count,
            strtoupper( $model )
        );

        return [
            'input_tokens'  => null,
            'output_tokens' => null,
            'total_tokens'  => null,
            'message'       => $fallback_message,
            'raw_usage'     => null
         ];
    }

    /**
     * Determine optimal model based on parameters
     *
     * @param string $requested_model The originally requested model
     * @param string $size Image size
     * @param string $quality Image quality
     * @param string $style Image style
     * @param string $background Background setting
     * @param string $output_format Output format
     * @param string $output_compression Output compression
     * @return string The optimal model to use
     */
    private function determine_optimal_model( $requested_model, $size, $quality, $style, $background, $output_format, $output_compression )
    {
        // Priority 1: If background is not 'auto', must use gpt-image-1
        if ( ! empty( $background ) && $background !== 'auto' ) {
            return 'gpt-image-1';
        }

        // Priority 2: If output_format or output_compression is not default, must use gpt-image-1
        if ( ( ! empty( $output_format ) && $output_format !== 'png' ) ||
            ( ! empty( $output_compression ) && $output_compression !== 'standard' ) ) {
            return 'gpt-image-1';
        }

        // Priority 3: If style is 'vivid' or 'natural', must use dall-e-3
        if ( ! empty( $style ) && ( $style === 'vivid' || $style === 'natural' ) ) {
            return 'dall-e-3';
        }

        // Priority 4: Size-based selection
        $dalle_e2_sizes   = [ '256x256', '512x512' ];
        $dalle_e3_sizes   = [ '1792x1024', '1024x1792' ];
        $gpt_image1_sizes = [ '1536x1024', '1024x1536', 'auto' ];

        if ( in_array( $size, $dalle_e2_sizes ) ) {
            return 'dall-e-2';
        }

        if ( in_array( $size, $dalle_e3_sizes ) ) {
            return 'dall-e-3';
        }

        if ( in_array( $size, $gpt_image1_sizes ) ) {
            return 'gpt-image-1';
        }

        // For 1024x1024 or other sizes, default to gpt-image-1 unless style forces dall-e-3
        return 'gpt-image-1';
    }

    /**
     * Filter parameters based on model capabilities
     *
     * @param string $model The selected model
     * @param string $size Image size
     * @param string $quality Image quality
     * @param string $style Image style
     * @param string $background Background setting
     * @param string $output_format Output format
     * @param string $output_compression Output compression
     * @return array Filtered parameters
     */
    private function filter_parameters_by_model( $model, $size, $quality, $style, $background, $output_format, $output_compression )
    {
        $filtered = [
            'size'               => $size,
            'quality'            => $quality,
            'style'              => $style,
            'background'         => $background,
            'output_format'      => $output_format,
            'output_compression' => $output_compression
         ];

        switch ( $model ) {
            case 'dall-e-2':
                // DALL-E 2: Only supports size and prompt
                $filtered[ 'quality' ]            = 'standard'; // Reset to default
                $filtered[ 'style' ]              = 'none'; // Reset to none
                $filtered[ 'background' ]         = 'auto'; // Reset to auto
                $filtered[ 'output_format' ]      = 'png'; // Reset to default
                $filtered[ 'output_compression' ] = 'standard'; // Reset to default

                // Validate size for DALL-E 2
                $valid_sizes = [ '256x256', '512x512', '1024x1024' ];
                if ( ! in_array( $size, $valid_sizes ) ) {
                    $filtered[ 'size' ] = '1024x1024'; // Default fallback
                }
                break;

            case 'dall-e-3':
                // DALL-E 3: Supports quality, style, size, prompt
                $filtered[ 'background' ]         = 'auto'; // Reset to auto
                $filtered[ 'output_format' ]      = 'png'; // Reset to default
                $filtered[ 'output_compression' ] = 'standard'; // Reset to default

                // Validate quality for DALL-E 3
                $valid_qualities = [ 'standard', 'hd' ];
                if ( ! in_array( $quality, $valid_qualities ) ) {
                    $filtered[ 'quality' ] = 'standard';
                }

                // Validate style for DALL-E 3
                $valid_styles = [ 'vivid', 'natural' ];
                if ( ! in_array( $style, $valid_styles ) ) {
                    $filtered[ 'style' ] = 'vivid'; // Default for DALL-E 3
                }

                // Validate size for DALL-E 3
                $valid_sizes = [ '1024x1024', '1792x1024', '1024x1792' ];
                if ( ! in_array( $size, $valid_sizes ) ) {
                    $filtered[ 'size' ] = '1024x1024'; // Default fallback
                }
                break;

            case 'gpt-image-1':
                // GPT-Image-1: Supports all parameters

                // Validate quality for GPT-Image-1
                $valid_qualities = [ 'high', 'medium', 'low' ];
                if ( ! in_array( $quality, $valid_qualities ) ) {
                    $filtered[ 'quality' ] = 'medium'; // Default for GPT-Image-1
                }

                // Validate background
                $valid_backgrounds = [ 'auto', 'transparent', 'opaque' ];
                if ( ! in_array( $background, $valid_backgrounds ) ) {
                    $filtered[ 'background' ] = 'auto';
                }

                // Validate output format
                $valid_formats = [ 'png', 'jpeg', 'webp' ];
                if ( ! in_array( $output_format, $valid_formats ) ) {
                    $filtered[ 'output_format' ] = 'png';
                }

                // Validate output compression
                $valid_compressions = [ 'standard', 'high', 'low', 'medium' ];
                if ( ! in_array( $output_compression, $valid_compressions ) ) {
                    $filtered[ 'output_compression' ] = 'standard';
                }
                // Validate output compression for PNG
                else if ( $filtered[ 'output_format' ] === 'png' ) {
                    $filtered[ 'output_compression' ] = 'standard';
                }

                // Validate size for GPT-Image-1
                $valid_sizes = [ '1024x1024', '1536x1024', '1024x1536', 'auto' ];
                if ( ! in_array( $size, $valid_sizes ) ) {
                    $filtered[ 'size' ] = 'auto'; // Default fallback
                }

                // Reset style to none for GPT-Image-1
                $filtered[ 'style' ] = 'none';
                break;
        }

        return $filtered;
    }

    /**
     * Generate metadata for an image based on its prompt
     *
     * @param string $revised_prompt The revised prompt from DALL-E
     * @param string $original_prompt The original user prompt
     * @return array Array containing title, alt_tag, caption, and description
     */
    private function generate_image_metadata( $revised_prompt, $original_prompt )
    {
        // If API key is not available, return default metadata
        if ( empty( $this->api_key ) ) {
            return $this->get_default_image_metadata( $original_prompt );
        }

        // Create a prompt for generating metadata
        $metadata_prompt = "Based on this image description: \"{$revised_prompt}\"\n\n" .
            "Generate appropriate metadata for this image in the following JSON format:\n" .
            "{\n" .
            "  \"title\": \"A concise, descriptive title (max 60 characters)\",\n" .
            "  \"alt_tag\": \"Descriptive alt text for accessibility (max 125 characters)\",\n" .
            "  \"caption\": \"A brief caption describing the image (max 200 characters)\",\n" .
            "  \"description\": \"A detailed description of the image (max 300 characters)\"\n" .
            "}\n\n" .
            "Make sure the JSON is valid and all fields are filled. Focus on being descriptive but concise.";

        // Prepare the request body for metadata generation
        $body = [
            'model'       => $this->model,
            'messages'    => [
                [
                    'role'    => 'system',
                    'content' => 'You are an expert at creating image metadata. Always respond with valid JSON only, no additional text.'
                 ],
                [
                    'role'    => 'user',
                    'content' => $metadata_prompt
                 ]
             ],
            'temperature' => 0.3, // Lower temperature for more consistent output
            'max_tokens'  => 300
         ];

        // Make the API request for metadata
        $response = wp_remote_post(
            $this->api_endpoint,
            [
                'headers'     => [
                    'Content-Type'  => 'application/json',
                    'Authorization' => 'Bearer ' . $this->api_key
                 ],
                'body'        => wp_json_encode( $body ),
                'timeout'     => 30,
                'data_format' => 'body'
             ]
        );

        // Check for errors or invalid response
        if ( is_wp_error( $response ) ) {
            return $this->get_default_image_metadata( $original_prompt );
        }

        $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
        $response_code = wp_remote_retrieve_response_code( $response );

        if ( $response_code !== 200 || ! isset( $response_body[ 'choices' ][ 0 ][ 'message' ][ 'content' ] ) ) {
            return $this->get_default_image_metadata( $original_prompt );
        }

        // Parse the JSON response
        $metadata_json = $response_body[ 'choices' ][ 0 ][ 'message' ][ 'content' ];
        $metadata      = json_decode( $metadata_json, true );

        // Validate the metadata structure
        if ( ! is_array( $metadata ) ||
            ! isset( $metadata[ 'title' ] ) ||
            ! isset( $metadata[ 'alt_tag' ] ) ||
            ! isset( $metadata[ 'caption' ] ) ||
            ! isset( $metadata[ 'description' ] ) ) {
            return $this->get_default_image_metadata( $original_prompt );
        }

        // Sanitize and truncate the metadata fields
        return [
            'title'       => sanitize_text_field( substr( $metadata[ 'title' ], 0, 60 ) ),
            'alt_tag'     => sanitize_text_field( substr( $metadata[ 'alt_tag' ], 0, 125 ) ),
            'caption'     => sanitize_text_field( substr( $metadata[ 'caption' ], 0, 200 ) ),
            'description' => sanitize_text_field( substr( $metadata[ 'description' ], 0, 300 ) )
         ];
    }

    /**
     * Get default image metadata when AI generation fails
     *
     * @param string $prompt The original prompt
     * @return array Default metadata array
     */
    private function get_default_image_metadata( $prompt )
    {
        // Create basic metadata from the prompt
        $clean_prompt = sanitize_text_field( $prompt );
        $title        = substr( $clean_prompt, 0, 60 );

        return [
            'title'       => $title ?: __( 'AI Generated Image', 'essential-blocks' ),
            'alt_tag'     => substr( $clean_prompt, 0, 125 ) ?: __( 'AI generated image', 'essential-blocks' ),
            'caption'     => substr( $clean_prompt, 0, 200 ) ?: __( 'Image generated using AI', 'essential-blocks' ),
            'description' => substr( $clean_prompt, 0, 300 ) ?: __( 'This image was generated using artificial intelligence based on a text prompt.', 'essential-blocks' )
         ];
    }

    /**
     * Prepare system message based on tone and length
     *
     * @param string $tone
     * @param string $length
     * @return string
     */
    private function prepare_system_message( $tone, $length )
    {
        $tone_instructions   = $this->get_tone_instructions( $tone );
        $length_instructions = $this->get_length_instructions( $length );

        return "You are a professional content writer. " .
            "Write content that is {$tone_instructions}. " .
            "{$length_instructions} " .
            "Format the content with proper headings, paragraphs, and bullet points where appropriate. " .
            "The content should be engaging, well-structured, and optimized for web reading.";
    }

    /**
     * Prepare user message with prompt and keywords
     *
     * @param string $prompt
     * @param string $keywords
     * @return string
     */
    private function prepare_user_message( $prompt, $keywords )
    {
        $message = "Write content about: {$prompt}";

        if ( ! empty( $keywords ) ) {
            $message .= "\n\nInclude the following keywords in the content: {$keywords}";
        }

        return $message;
    }

    /**
     * Get tone instructions based on selected tone
     *
     * @param string $tone
     * @return string
     */
    private function get_tone_instructions( $tone )
    {
        switch ( $tone ) {
            case 'casual':
                return "conversational and friendly, using a casual tone";
            case 'formal':
                return "professional and formal, using proper language";
            case 'persuasive':
                return "persuasive and compelling, designed to convince the reader";
            case 'informative':
            default:
                return "informative and educational, focusing on providing valuable information";
        }
    }

    /**
     * Get length instructions based on selected length
     *
     * @param string $length
     * @return string
     */
    private function get_length_instructions( $length )
    {
        switch ( $length ) {
            case 'short':
                return "Keep the content concise and to the point, around 150-250 words.";
            case 'long':
                return "Create comprehensive content with detailed explanations, around 500-800 words.";
            case 'medium':
            default:
                return "Write a moderate-length content of approximately 300-500 words.";
        }
    }

    /**
     * Get max tokens based on selected length
     *
     * This method is kept for backward compatibility but is no longer used directly.
     * The max_tokens value from settings is used instead.
     *
     * @param string $length
     * @return int
     */
    private function get_max_tokens_by_length( $length )
    {
        switch ( $length ) {
            case 'short':
                return 350;
            case 'long':
                return 1200;
            case 'medium':
            default:
                return 800;
        }
    }
}

SILENT KILLER Tool