Current File : /home/kelaby89/www/wp/wp-content/plugins/trx_addons/addons/ai-helper/support/Elementor/Helper.php
<?php
namespace TrxAddons\AiHelper\Elementor;

use TrxAddons\AiHelper\Utils;

if ( ! class_exists( 'Helper' ) ) {

    /**
	 * Main class for AI Helper Elementor
	 */
	class Helper extends ContentGenerator {

		private const CONTENT_KEYS = array(
			'title', 'title_text', 'heading', 'sub_heading', 'text', 'description_text', 'description', 'content', 'editor',
			'tab_title', 'tab_content', 'accordion_title', 'accordion_content',
			'counter_title', 'counter_subtitle', 'starting_number', 'ending_number', 'rating',
			'team_member_name', 'team_member_position', 'person_name', 'company_name',
			'menu_title', 'menu_description', 'menu_price', 'original_price',
			'bg_text', 'caption', 'button_text'
		);
	
		/**
		 * Constructor
		 */
		function __construct() {
			// Enqueue scripts and styles for the elementor
			add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
			add_action( 'elementor/editor/after_enqueue_styles', array( $this, 'enqueue_styles' ) );
			add_filter( 'trx_addons_filter_localize_script_admin', array( $this, 'localize_script' ) );

			// AJAX callback for the 'Elementor Generate text' buttons
			add_action( 'wp_ajax_trx_addons_ai_helper_elementor_generate_text', array( $this, 'elementor_generate_text' ) );
			// AJAX callback to fetch answer from the assistant
			add_action( 'wp_ajax_trx_addons_ai_helper_elementor_generate_text_fetch', array( $this, 'fetch_answer' ) );
		}

		/**
		 * Enqueue scripts for the elementor
		 * 
		 * @hooked 'elementor/editor/after_enqueue_scripts'
		 */
		function enqueue_scripts() {
			if ( self::is_allowed() ) {
				wp_enqueue_script( 'trx_addons-ai-helper-elementor-generate-text', trx_addons_get_file_url( TRX_ADDONS_PLUGIN_ADDONS . 'ai-helper/support/Elementor/assets/js/index.js' ), array( 'jquery' ), null, true );
			}
		}

		/**
		 * Enqueue styles for the elementor
		 * 
		 * @hooked 'elementor/editor/after_enqueue_styles'
		 */
		function enqueue_styles() {
			if ( self::is_allowed() ) {
				wp_enqueue_style( 'trx_addons-ai-helper-elementor-generate-text', trx_addons_get_file_url( TRX_ADDONS_PLUGIN_ADDONS . 'ai-helper/support/Elementor/assets/css/index.css' ) );
			}
		}

		/**
		 * Localize script to show messages
		 * 
		 * @hooked 'trx_addons_filter_localize_script_admin'
		 * 
		 * @param array $vars  Array of variables to be passed to the script
		 * 
		 * @return array  Modified array of variables
		 */
		function localize_script( $vars ) {
			if ( self::is_allowed() ) {
				$vars['elm_ai_generate_text_btn_label'] = esc_html__( "Generate texts with AI", 'trx_addons' );
				$vars['elm_ai_generate_text_modal_close'] = esc_html__( "Close", 'trx_addons' );
				$vars['elm_ai_generate_text_modal_submit'] = esc_html__( "Generate", 'trx_addons' );
				$vars['elm_ai_generate_text_modal_purpose_label'] = esc_html__( "Purpose of the block", 'trx_addons' );
				$vars['elm_ai_generate_text_modal_purpose_pl'] = esc_html__( "About Us", 'trx_addons' );
			}
			return $vars;
		}

		/**
		 * Send a query to API to process text
		 * 
		 * @hooked 'wp_ajax_trx_addons_ai_helper_elementor_generate_text'
		 */
		function elementor_generate_text() {

			trx_addons_verify_nonce();

			$answer = array(
				'error' => '',
				'data' => array(
					'fields' => array(),
					'message' => ''
				)
			);

			$content = json_decode( trx_addons_get_value_gp( 'content' ), true );
			$purpose = trx_addons_get_value_gp( 'purpose' );
			
			if ( ! empty( $content ) ) {
				// Translate the purpose to the English
				if ( ! empty( $purpose ) && trx_addons_str_is_not_english( $purpose ) ) {
					$purpose = Utils::translate( $purpose );
				}

				// Extract fields from the content to fill with AI.
				// In the $content all extracted fields marked with the prefix '[ref_id]N[/ref_id] Original value'
				$fields = $this->parse_content( $content );

				// Load the schema and system prompt for the AI
				$schema = trx_addons_fgc( trx_addons_get_file_dir( TRX_ADDONS_PLUGIN_ADDONS . 'ai-helper/support/Elementor/assets/ai-templates/fields-schema.json' ) );
				$system_prompt = trx_addons_fgc( trx_addons_get_file_dir( TRX_ADDONS_PLUGIN_ADDONS . 'ai-helper/support/Elementor/assets/ai-templates/fields-sp.json' ) );
				
				// Get the API object
				$api = Utils::get_chat_api( $this->get_model() );

				// Process fields in batches
				$result = array();
				$batch_size = 5;
				for ( $i = 0; $i < count( $fields ); $i += $batch_size) {
					$batch = array_slice( $fields, $i, $batch_size );
				
					$response = $api->query(
						array(
							'model' => $this->get_model(),
							'system_prompt' => $system_prompt,
							'prompt' => sprintf(
											"This is company_info:\n%s\n\nContent purpose is:\n%s\n\nContent fields to fill:\n%s",	// Default prompt for AI, not need to be translated!
											json_encode( $this->company_info(), JSON_UNESCAPED_UNICODE),
											! empty( $purpose ) ? $purpose : 'Regular block',										// Default purpose for AI, not need to be translated!
											json_encode( $batch, JSON_UNESCAPED_UNICODE )
							),
							'response_format' => json_decode( $schema, true ),
							'role' => 'elementor_content_generator',
							'n' => 1,
							'temperature' => 0.2,
							'max_tokens' => 4000,
						)
					);
					
					$answer = $this->parse_response( $response, $answer );

					if ( ! empty( $answer['data']['fields'] ) ) {
						$result = array_merge( $result, ! empty( $answer['data']['fields']['fields'] ) ? $answer['data']['fields']['fields'] : $answer['data']['fields'] );
						$answer['data']['fields'] = array();
					} else if ( ! empty( $answer['error'] ) ) {
						break;
					}
				}

				if ( empty( $answer['error'] ) ) {
					$answer['data']['fields'] = $this->merge_content( $content, $result );
				}

			} else {
				$answer['error'] = esc_html__( 'The json with the row content is broken!', 'trx_addons' );
			}

			// Return response to the AJAX handler
			trx_addons_ajax_response( $answer );
		}

		/**
		 * Parse the row content (array) and extract all fields to fill with AI.
		 * Extracted fields in the original content marked with the prefix '[ref_id]N[/ref_id] Original content'
		 *
		 * @param  mixed $content The row content
		 * @param  int   $id      The start ref_id for the fields
		 * 
		 * @return array The array with all fields to fill
		 */
		function parse_content( &$content, $id = 0 ) {
			$fields = array();
			$widget = '';
			// Parse widget's settings
			if ( ! empty( $content['elType'] ) && $content['elType'] == 'widget' ) {
				if ( isset( $content['widgetType'] ) ) {
					$widget = $content['widgetType'];
				}
				if ( ! empty( $content['settings'] ) && is_array( $content['settings'] ) ) {
					$fields = $this->parse_settings( $content['settings'], $id, $widget );
				}
			}
			// Parse inner elements
			if ( ! empty( $content['elements'] ) && is_array( $content['elements'] ) ) {
				for ( $i = 0; $i < count( $content['elements'] ); $i++ ) {
					$fields2 = $this->parse_content( $content['elements'][ $i ], $id );
					$fields = array_merge( $fields, $fields2 );
					$id += count( $fields2 );
				}
			}
			return $fields;
		}

		/**
		 * Parse the settings of the widget and extract all fields to fill with AI.
		 * Extracted fields in the original content marked with the prefix '[ref_id]N[/ref_id] Original content'
		 * 
		 * @param  mixed $settings The widget settings
		 * @param  int   $id       The start ref_id for the fields
		 * @param  string $widget  The widget type
		 * 
		 * @return array The array with all fields to fill
		 */
		function parse_settings( &$settings, $id, $widget ) {
			$fields = array();
			foreach ( $settings as $key => $value ) {
				if ( in_array( $key, self::CONTENT_KEYS ) && is_string( $value ) ) {
					$id++;
					$fields[] = array(
						'ref_id' => (string)$id,
						'widget' => $widget,
						'field' => $key,
						'value' => $value
					);
					$settings[ $key ] = "[ref_id]{$id}[/ref_id] {$value}";
				} else if ( is_array( $value ) ) {
					$fields2 = $this->parse_settings( $settings[ $key ], $id, $widget );
					$fields = array_merge( $fields, $fields2 );
					$id += count( $fields2 );
				}
			}
			return $fields;
		}


		/**
		 * Merge the generated fields with the original content:
		 * replace the original fields with the prefix '[ref_id]N[/ref_id] Original content'
		 * with the generated values
		 *
		 * @param  mixed $content The row content
		 * @param  array $fields  The array with the generated fields
		 * 
		 * @return array The row content with the generated fields
		 */
		function merge_content( $content, $fields ) {
			if ( is_array( $content ) && is_array( $fields ) ) {
				foreach ( $content as $key => $value ) {
					if ( in_array( $key, self::CONTENT_KEYS ) && is_string( $value ) ) {
						if ( preg_match( '/\[ref_id\](\d+)\[\/ref_id\].*/', $value, $matches ) ) {
							$ref_id = $matches[1];
							$found = false;
							foreach ( $fields as $field ) {
								if ( $field['ref_id'] == $ref_id ) {
									$content[ $key ] = wp_unslash( $field['value'] );
									$found = true;
									break;
								}
							}
							if ( ! $found ) {
								$content[ $key ] = str_replace( "[ref_id]{$ref_id}[/ref_id] ", '', $value );
							}
						}
					} else if ( is_array( $value ) ) {
						$content[ $key ] = $this->merge_content( $value, $fields );
					}
				}
			}
			return $content;
		}

		/**
		 * Get the company info for the AI (from the plugin's options)
		 * 
		 * @return array The company info
		 */
		function company_info() {
			// Get the company info from the plugin's options
			$company_info = array(
				'organization_model' => array(
					'company_name' => trx_addons_get_option( 'ai_helper_company_name' ),
					'industry' => trx_addons_get_option( 'ai_helper_company_industry' ),
					'contacts' => array(
						'address' => trx_addons_get_option( 'ai_helper_company_address' ),
						'phone' => trx_addons_get_option( 'ai_helper_company_phone' ),
						'email' => trx_addons_get_option( 'ai_helper_company_email' ),
					),
					'description' => trx_addons_get_option( 'ai_helper_company_description' ),
					'mission' => trx_addons_get_option( 'ai_helper_company_mission' ),
					'history' => trx_addons_get_option( 'ai_helper_company_history' ),
					'values' => array_map( 'trim', explode( "\n", trx_addons_get_option( 'ai_helper_company_values' ) ) ),
					'services' => array(),
					'team' => array(),
				),
			);
			// Add services
			$services = trx_addons_get_option( 'ai_helper_company_services' );
			if ( is_array( $services ) ) {
				foreach ( $services as $service ) {
					$company_info['organization_model']['services'][] = array(
						'service_name' => $service['name'],
						'service_description' => $service['description'],
						'service_features' => array_map( 'trim', explode( "\n", $service['features'] ) ),
					);
				}
			}
			// Add team members
			$team = trx_addons_get_option( 'ai_helper_company_team' );
			if ( is_array( $team ) ) {
				foreach ( $team as $member ) {
					$company_info['organization_model']['team'][] = array(
						'name' => $member['name'],
						'position' => $member['position'],
						'bio' => $member['bio'],
					);
				}
			}

			return $company_info;
		}
   }
}
Page not found – Hello World !