File "wpaicg_forms.php"
Full Path: /home/digimqhe/flashdigi.uk/comment-content/plugins/gpt3-ai-content-generator/classes/wpaicg_forms.php
File size: 74.51 KB
MIME-type: text/x-php
Charset: utf-8
<?php
declare(strict_types=1);
namespace WPAICG;
if (!defined('ABSPATH')) {
exit;
}
if (!class_exists('\\WPAICG\\WPAICG_Forms')) {
class WPAICG_Forms
{
private static $instance = null;
public $wpaicg_engine = 'gpt-4o-mini';
public $wpaicg_max_tokens = 2000;
public $wpaicg_temperature = 0;
public $wpaicg_top_p = 1;
public $wpaicg_best_of = 1;
public $wpaicg_frequency_penalty = 0;
public $wpaicg_presence_penalty = 0;
public $wpaicg_stop = [];
public static function get_instance()
{
if (is_null(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function __construct()
{
add_action('wp_ajax_wpaicg_update_template', [$this, 'wpaicg_update_template']);
add_action('wp_ajax_wpaicg_template_delete', [$this, 'wpaicg_template_delete']);
add_shortcode('wpaicg_form', [$this, 'wpaicg_form_shortcode']);
add_action('admin_menu', [$this, 'wpaicg_menu']);
// For saving logs
add_action('wp_ajax_wpaicg_form_log', [$this, 'wpaicg_form_log']);
add_action('wp_ajax_nopriv_wpaicg_form_log', [$this, 'wpaicg_form_log']);
// Duplicating forms
add_action('wp_ajax_wpaicg_form_duplicate', [$this, 'wpaicg_form_duplicate']);
add_action('wp_ajax_wpaicg_get_custom_forms_ids', [$this, 'wpaicg_get_custom_forms_ids']);
add_action('wp_ajax_wpaicg_export_single_form', [$this, 'wpaicg_export_single_form']);
add_action('wp_ajax_wpaicg_import_single_form', [$this, 'wpaicg_import_single_form']);
add_action('wp_ajax_wpaicg_delete_single_form', [$this, 'wpaicg_delete_single_form']);
// Schedules token removal
if (!wp_next_scheduled('wpaicg_remove_forms_tokens_limited')) {
wp_schedule_event(time(), 'hourly', 'wpaicg_remove_forms_tokens_limited');
}
add_action('wpaicg_remove_forms_tokens_limited', [$this, 'wpaicg_remove_tokens_limit']);
// Feedback
add_action('wp_ajax_wpaicg_save_feedback', [$this, 'wpaicg_save_feedback']);
add_action('wp_ajax_nopriv_wpaicg_save_feedback', [$this, 'wpaicg_save_feedback']);
add_action('wp_ajax_wpaicg_save_prompt_feedback', [$this, 'wpaicg_save_prompt_feedback']);
add_action('wp_ajax_nopriv_wpaicg_save_prompt_feedback', [$this, 'wpaicg_save_prompt_feedback']);
// Delete all logs
add_action('wp_ajax_wpaicg_delete_all_logs', [$this, 'wpaicg_delete_all_logs']);
// NEW: AJAX to load form preview
add_action('wp_ajax_wpaicg_get_form_preview', [$this, 'wpaicg_get_form_preview']);
// NEW: AJAX to create a new form
add_action('wp_ajax_wpaicg_create_new_form', [$this, 'wpaicg_create_new_form']);
// NEW: AJAX to get form data for editing
add_action('wp_ajax_wpaicg_get_form_data_for_editing', [$this, 'wpaicg_get_form_data_for_editing']);
// NEW: AJAX to save an edited form
add_action('wp_ajax_wpaicg_save_edited_form', [$this, 'wpaicg_save_edited_form']);
// NEW (Logs): get logs with pagination
add_action('wp_ajax_wpaicg_get_logs', [$this, 'wpaicg_get_logs']);
// IMPORTANT: handle Settings save via AJAX so the user stays on the same page
add_action('wp_ajax_wpaicg_save_form_settings', [$this, 'wpaicg_save_form_settings']);
// *********
// NEW: store file content in transient for large uploads
// *********
add_action('wp_ajax_wpaicg_store_file_content', [$this, 'wpaicg_store_file_content']);
add_action('wp_ajax_nopriv_wpaicg_store_file_content', [$this, 'wpaicg_store_file_content']);
}
/**
* Save “Token Management” form settings via AJAX.
* This prevents a redirect/refresh after clicking Save.
*/
public function wpaicg_save_form_settings()
{
// Check the nonce from the hidden input "wpaicg_limit_tokens_nonce"
if (!isset($_POST['security']) || !wp_verify_nonce($_POST['security'], 'wpaicg_limit_tokens_action')) {
wp_send_json_error(['msg' => __('Nonce verification failed.', 'gpt3-ai-content-generator')]);
}
// Ensure permission
if (!current_user_can('manage_options')) {
wp_send_json_error(['msg' => __('No permission to save settings.', 'gpt3-ai-content-generator')]);
}
// The “wpaicg_limit_tokens” array must exist
if (!isset($_POST['wpaicg_limit_tokens'])) {
wp_send_json_error(['msg' => __('Missing settings data.', 'gpt3-ai-content-generator')]);
}
// Sanitize and update
$wpaicg_limit_tokens = \WPAICG\wpaicg_util_core()->sanitize_text_or_array_field($_POST['wpaicg_limit_tokens']);
update_option('wpaicg_limit_tokens_form', $wpaicg_limit_tokens);
// Enable or disable token purchasing
if (isset($_POST['wpaicg_forms_enable_sale']) && !empty($_POST['wpaicg_forms_enable_sale'])) {
update_option('wpaicg_forms_enable_sale', sanitize_text_field($_POST['wpaicg_forms_enable_sale']));
} else {
delete_option('wpaicg_forms_enable_sale');
}
// NEW: Save KaTeX option
if (isset($_POST['wpaicg_form_katex']) && !empty($_POST['wpaicg_form_katex'])) {
update_option('wpaicg_form_katex', 1);
} else {
delete_option('wpaicg_form_katex');
}
// --------------------------------------------------------------------
// 2) Save "Internet Browsing" (Google API Key, CSE, region, language, etc.)
// We store them in the same standard WP options used by the Chatbot.
// --------------------------------------------------------------------
if (isset($_POST['wpaicg_google_api_key'])) {
update_option('wpaicg_google_api_key', sanitize_text_field($_POST['wpaicg_google_api_key']));
}
if (isset($_POST['wpaicg_google_search_engine_id'])) {
update_option('wpaicg_google_search_engine_id', sanitize_text_field($_POST['wpaicg_google_search_engine_id']));
}
if (isset($_POST['wpaicg_google_search_country'])) {
update_option('wpaicg_google_search_country', sanitize_text_field($_POST['wpaicg_google_search_country']));
}
if (isset($_POST['wpaicg_google_search_language'])) {
update_option('wpaicg_google_search_language', sanitize_text_field($_POST['wpaicg_google_search_language']));
}
if (isset($_POST['wpaicg_google_search_num'])) {
update_option('wpaicg_google_search_num', intval($_POST['wpaicg_google_search_num']));
}
// Respond success without reloading the page
wp_send_json_success(['message' => __('Settings updated successfully.', 'gpt3-ai-content-generator')]);
}
/**
* Store large file content in a transient instead of passing in the SSE URL.
*
* Updated to parse .docx files from base64 -> extracted text.
*/
public function wpaicg_store_file_content()
{
check_ajax_referer('wpaicg-ajax-nonce','nonce');
if(!isset($_POST['fileContent'])) {
wp_send_json_error(['message' => __('No file content found','gpt3-ai-content-generator')]);
}
$rawContent = wp_unslash($_POST['fileContent']);
/**
* If the user uploaded a doc/docx file, it's sent from JS as "base64:..."
* We'll parse .docx into text so that the transient stores actual text.
* For .doc, we currently still store the base64 string (unsupported).
*/
if (strpos($rawContent, 'base64:') === 0) {
// This implies docx or doc. We'll parse .docx.
// .doc is older binary format; for now we store it as base64.
$justBase64 = substr($rawContent, 7);
// Attempt docx extraction:
$extractedText = $this->wpaicg_try_extract_docx($justBase64);
// If extraction failed or not a valid docx,
// we keep the original base64 for doc fallback.
if (!empty($extractedText)) {
$rawContent = $extractedText;
}
} else {
// For txt/csv (or any textual file), we keep standard sanitization
$rawContent = sanitize_textarea_field($rawContent);
}
// Generate a unique transient key
$transient_key = 'wpaicg_upload_' . wp_generate_uuid4();
// Store for 1 hour
set_transient($transient_key, $rawContent, HOUR_IN_SECONDS);
wp_send_json_success(['transient_key'=>$transient_key]);
}
/**
* Attempt to parse a .docx file (base64-encoded) into text.
* If it fails or is invalid, return an empty string.
*/
private function wpaicg_try_extract_docx( string $base64Docx ): string {
// Decode base64 to raw .docx data
$binaryData = base64_decode( $base64Docx, true );
if ( ! $binaryData ) {
return '';
}
// Ensure we have ZipArchive available
if ( ! class_exists( '\\ZipArchive' ) ) {
return '';
}
// Create a temporary file
$tmpFile = tempnam( sys_get_temp_dir(), 'wpaicg_docx_' );
if ( ! $tmpFile ) {
return '';
}
// Save the binary data to the temp file
file_put_contents( $tmpFile, $binaryData );
$zip = new \ZipArchive();
if ( $zip->open( $tmpFile ) !== true ) {
wp_delete_file( $tmpFile );
return '';
}
// Attempt to read "word/document.xml" inside docx
$xmlContent = $zip->getFromName( 'word/document.xml' );
$zip->close();
wp_delete_file( $tmpFile );
if ( ! $xmlContent ) {
return '';
}
// Strip tags using WordPress-safe method
$text = wp_strip_all_tags( $xmlContent );
// Clean up any leftover entities or newlines
$text = html_entity_decode( $text, ENT_QUOTES | ENT_XML1, 'UTF-8' );
$text = preg_replace( "/[\r\n\t]+/", " ", $text );
$text = trim( $text );
return $text;
}
/**
* Normalize the form fields array so that "options" is stored as a
* pipe-delimited string (rather than an array).
*/
private function normalize_fields_array(array $fields): array
{
foreach ($fields as &$field) {
if (isset($field['options']) && is_array($field['options'])) {
$field['options'] = implode('|', $field['options']);
}
if (!isset($field['min'])) {
$field['min'] = '';
}
if (!isset($field['max'])) {
$field['max'] = '';
}
if (!isset($field['rows'])) {
$field['rows'] = '';
}
if (!isset($field['cols'])) {
$field['cols'] = '';
}
}
unset($field);
return $fields;
}
/********************************
* NEW: AJAX to get form data
* for editing a custom form
********************************/
public function wpaicg_get_form_data_for_editing()
{
check_ajax_referer('wpaicg_edit_form_nonce', 'nonce');
if (!current_user_can('wpaicg_forms_forms')) {
wp_send_json_error([
'message' => __('You do not have permission for this action.', 'gpt3-ai-content-generator')
]);
}
$form_id = isset($_POST['form_id']) ? intval($_POST['form_id']) : 0;
if (!$form_id) {
wp_send_json_error(['message' => __('Invalid form ID', 'gpt3-ai-content-generator')]);
}
// Make sure it's actually a custom form
$post = get_post($form_id);
if (!$post || $post->post_type !== 'wpaicg_form') {
wp_send_json_error([
'message' => __('This form does not exist or is not a custom form.', 'gpt3-ai-content-generator')
]);
}
// Gather meta
$prompt = get_post_meta($form_id, 'wpaicg_form_prompt', true);
$fields_json = get_post_meta($form_id, 'wpaicg_form_fields', true);
$description = $post->post_content;
$title = $post->post_title;
$engine = get_post_meta($form_id, 'wpaicg_form_engine', true);
// IMPORTANT: must retrieve from wpaicg_form_model_provider
$model_provider = get_post_meta($form_id, 'wpaicg_form_model_provider', true);
// advanced settings
$max_tokens = get_post_meta($form_id, 'wpaicg_form_max_tokens', true);
$top_p = get_post_meta($form_id, 'wpaicg_form_top_p', true);
$best_of = get_post_meta($form_id, 'wpaicg_form_best_of', true);
$frequency_penalty = get_post_meta($form_id, 'wpaicg_form_frequency_penalty', true);
$presence_penalty = get_post_meta($form_id, 'wpaicg_form_presence_penalty', true);
$stop = get_post_meta($form_id, 'wpaicg_form_stop', true);
// embeddings
$use_embeddings = get_post_meta($form_id, 'wpaicg_form_embeddings', true);
$vector_db = get_post_meta($form_id, 'wpaicg_form_vectordb', true);
$collections = get_post_meta($form_id, 'wpaicg_form_collections', true);
$pineconeindexes = get_post_meta($form_id, 'wpaicg_form_pineconeindexes', true);
$suffix_text = get_post_meta($form_id, 'wpaicg_form_suffix_text', true);
$suffix_position = get_post_meta($form_id, 'wpaicg_form_suffix_position', true);
$use_default_embed = get_post_meta($form_id, 'wpaicg_form_use_default_embedding_model', true);
$selected_provider = get_post_meta($form_id, 'wpaicg_form_selected_embedding_provider', true);
$selected_model = get_post_meta($form_id, 'wpaicg_form_selected_embedding_model', true);
$embeddings_limit = get_post_meta($form_id, 'wpaicg_form_embeddings_limit', true);
// interface
$interface_meta = [
'wpaicg_form_response',
'wpaicg_form_category',
'wpaicg_form_color',
'wpaicg_form_icon',
'wpaicg_form_editor',
'wpaicg_form_header',
'wpaicg_form_copy_button',
'wpaicg_form_ddraft',
'wpaicg_form_dclear',
'wpaicg_form_dnotice',
'wpaicg_form_ddownload',
'wpaicg_form_copy_text',
'wpaicg_form_feedback_buttons',
'wpaicg_form_generate_text',
'wpaicg_form_noanswer_text',
'wpaicg_form_draft_text',
'wpaicg_form_clear_text',
'wpaicg_form_stop_text',
'wpaicg_form_cnotice_text',
'wpaicg_form_download_text',
'wpaicg_form_bgcolor',
];
$interfaceData = [];
foreach ($interface_meta as $im) {
$interfaceData[$im] = get_post_meta($form_id, $im, true);
}
// decode fields
$fields = [];
if ($fields_json) {
$decoded = json_decode($fields_json, true);
if (is_array($decoded)) {
$fields = $decoded;
}
}
// NEW: internet browsing meta
$internet_browsing = get_post_meta($form_id, 'wpaicg_form_internet_browsing', true);
$internet_status = ($internet_browsing === 'yes') ? 'yes' : 'no';
wp_send_json_success([
'title' => $title,
'description' => $description,
'prompt' => $prompt,
'fields' => $fields,
'interface' => $interfaceData,
'engine' => $engine,
// must pass back the correct provider
'model_provider' => $model_provider,
'advanced_settings' => [
'max_tokens' => $max_tokens ?: 1500,
'top_p' => $top_p ?: 1,
'best_of' => $best_of ?: 1,
'frequency_penalty' => $frequency_penalty ?: 0,
'presence_penalty' => $presence_penalty ?: 0,
'stop' => $stop ?: '',
],
'embedding_settings' => [
'use_embeddings' => $use_embeddings ?: 'no',
'vectordb' => $vector_db ?: 'pinecone',
'collections' => $collections ?: '',
'pineconeindexes' => $pineconeindexes ?: '',
'suffix_text' => $suffix_text ?: 'Context:',
'suffix_position' => $suffix_position ?: 'after',
'use_default_embedding_model' => $use_default_embed ?: 'yes',
'selected_embedding_provider' => $selected_provider ?: '',
'selected_embedding_model' => $selected_model ?: '',
'embeddings_limit' => $embeddings_limit ?: 1,
],
'internet_browsing' => $internet_status
]);
}
/************************************
* NEW: AJAX to save an edited form
************************************/
public function wpaicg_save_edited_form()
{
check_ajax_referer('wpaicg_save_edited_form_nonce', 'nonce');
if (!current_user_can('wpaicg_forms_forms')) {
wp_send_json_error(['message' => __('You do not have permission for this action.', 'gpt3-ai-content-generator')]);
}
$form_id = isset($_POST['form_id']) ? intval($_POST['form_id']) : 0;
$title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
$description= isset($_POST['description']) ? sanitize_text_field($_POST['description']) : '';
$prompt = isset($_POST['prompt']) ? wp_kses_post($_POST['prompt']) : '';
$fields_json= isset($_POST['fields']) ? wp_unslash($_POST['fields']) : '';
$engine = isset($_POST['engine']) ? sanitize_text_field($_POST['engine']) : 'gpt-4o-mini';
// Must read the provider from the posted data
$provider = isset($_POST['provider']) ? sanitize_text_field($_POST['provider']) : '';
$model_settings = isset($_POST['model_settings']) ? (array) $_POST['model_settings'] : [];
$wpaicg_max_tokens = isset($model_settings['max_tokens']) ? intval($model_settings['max_tokens']) : 1500;
$wpaicg_top_p = isset($model_settings['top_p']) ? floatval($model_settings['top_p']) : 1;
$wpaicg_best_of = isset($model_settings['best_of']) ? intval($model_settings['best_of']) : 1;
$wpaicg_frequency_penalty = isset($model_settings['frequency_penalty']) ? floatval($model_settings['frequency_penalty']) : 0;
$wpaicg_presence_penalty = isset($model_settings['presence_penalty']) ? floatval($model_settings['presence_penalty']) : 0;
$wpaicg_stop = isset($model_settings['stop']) ? sanitize_text_field($model_settings['stop']) : '';
if (!$form_id || !$title || !$description || !$prompt) {
wp_send_json_error(['message' => __('Missing required data', 'gpt3-ai-content-generator')]);
}
$post = get_post($form_id);
if (!$post || $post->post_type !== 'wpaicg_form') {
wp_send_json_error(['message' => __('Not a valid custom form.', 'gpt3-ai-content-generator')]);
}
// Update the post
wp_update_post([
'ID' => $form_id,
'post_title' => $title,
'post_content' => $description,
]);
// Update meta
update_post_meta($form_id, 'wpaicg_form_engine', $engine);
// Correct: store provider in wpaicg_form_model_provider
update_post_meta($form_id, 'wpaicg_form_model_provider', $provider);
update_post_meta($form_id, 'wpaicg_form_prompt', $prompt);
update_post_meta($form_id, 'wpaicg_form_fields', $fields_json);
// advanced model
update_post_meta($form_id, 'wpaicg_form_max_tokens', $wpaicg_max_tokens);
update_post_meta($form_id, 'wpaicg_form_top_p', $wpaicg_top_p);
update_post_meta($form_id, 'wpaicg_form_best_of', $wpaicg_best_of);
update_post_meta($form_id, 'wpaicg_form_frequency_penalty', $wpaicg_frequency_penalty);
update_post_meta($form_id, 'wpaicg_form_presence_penalty', $wpaicg_presence_penalty);
update_post_meta($form_id, 'wpaicg_form_stop', $wpaicg_stop);
// Embedding settings
$embedding_settings = isset($_POST['embedding_settings']) ? (array) $_POST['embedding_settings'] : [];
$use_embeddings = !empty($embedding_settings['use_embeddings']) ? sanitize_text_field($embedding_settings['use_embeddings']) : 'no';
update_post_meta($form_id, 'wpaicg_form_embeddings', $use_embeddings);
$vector_db = !empty($embedding_settings['vectordb']) ? sanitize_text_field($embedding_settings['vectordb']) : 'pinecone';
update_post_meta($form_id, 'wpaicg_form_vectordb', $vector_db);
$collections = !empty($embedding_settings['collections']) ? sanitize_text_field($embedding_settings['collections']) : '';
update_post_meta($form_id, 'wpaicg_form_collections', $collections);
$pineconeindexes = !empty($embedding_settings['pineconeindexes']) ? sanitize_text_field($embedding_settings['pineconeindexes']) : '';
update_post_meta($form_id, 'wpaicg_form_pineconeindexes', $pineconeindexes);
$suffix_text = !empty($embedding_settings['suffix_text']) ? sanitize_text_field($embedding_settings['suffix_text']) : 'Context:';
update_post_meta($form_id, 'wpaicg_form_suffix_text', $suffix_text);
$suffix_position = !empty($embedding_settings['suffix_position']) ? sanitize_text_field($embedding_settings['suffix_position']) : 'after';
update_post_meta($form_id, 'wpaicg_form_suffix_position', $suffix_position);
$use_default = !empty($embedding_settings['use_default_embedding_model']) ? sanitize_text_field($embedding_settings['use_default_embedding_model']) : 'yes';
update_post_meta($form_id, 'wpaicg_form_use_default_embedding_model', $use_default);
$selected_provider = !empty($embedding_settings['selected_embedding_provider']) ? sanitize_text_field($embedding_settings['selected_embedding_provider']) : '';
update_post_meta($form_id, 'wpaicg_form_selected_embedding_provider', $selected_provider);
$selected_model = !empty($embedding_settings['selected_embedding_model']) ? sanitize_text_field($embedding_settings['selected_embedding_model']) : '';
update_post_meta($form_id, 'wpaicg_form_selected_embedding_model', $selected_model);
$embed_limit = !empty($embedding_settings['embeddings_limit']) ? intval($embedding_settings['embeddings_limit']) : 1;
update_post_meta($form_id, 'wpaicg_form_embeddings_limit', $embed_limit);
// Interface
$interface_meta = [
'wpaicg_form_response',
'wpaicg_form_category',
'wpaicg_form_color',
'wpaicg_form_icon',
'wpaicg_form_editor',
'wpaicg_form_header',
'wpaicg_form_copy_button',
'wpaicg_form_ddraft',
'wpaicg_form_dclear',
'wpaicg_form_dnotice',
'wpaicg_form_ddownload',
'wpaicg_form_copy_text',
'wpaicg_form_feedback_buttons',
'wpaicg_form_generate_text',
'wpaicg_form_noanswer_text',
'wpaicg_form_draft_text',
'wpaicg_form_clear_text',
'wpaicg_form_stop_text',
'wpaicg_form_cnotice_text',
'wpaicg_form_download_text',
'wpaicg_form_bgcolor',
];
if (isset($_POST['interface']) && is_array($_POST['interface'])) {
foreach ($interface_meta as $imKey) {
$val = isset($_POST['interface'][$imKey]) ? sanitize_text_field($_POST['interface'][$imKey]) : '';
update_post_meta($form_id, $imKey, $val);
}
}
// NEW: internet browsing
$internet_browsing = isset($_POST['internet_browsing']) ? sanitize_text_field($_POST['internet_browsing']) : 'no';
update_post_meta($form_id, 'wpaicg_form_internet_browsing', $internet_browsing);
wp_send_json_success([
'message' => __('Form updated successfully.', 'gpt3-ai-content-generator')
]);
}
/**
* Return the form's shortcode HTML so that the admin preview can show it inline.
*/
public function wpaicg_get_form_preview()
{
check_ajax_referer('wpaicg-ajax-nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'Insufficient permissions']);
}
$form_id = isset($_POST['form_id']) ? sanitize_text_field($_POST['form_id']) : '';
$form_custom = isset($_POST['custom']) ? sanitize_text_field($_POST['custom']) : 'no';
if (empty($form_id)) {
wp_send_json_error(['message' => 'Invalid form ID']);
}
$shortcode_html = do_shortcode('[wpaicg_form id="' . $form_id . '" custom="' . $form_custom . '" settings="no"]');
wp_send_json_success(['html' => $shortcode_html]);
}
public function wpaicg_delete_all_logs()
{
check_ajax_referer('wpaicg_delete_all_logs_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(['message' => 'You do not have sufficient permissions']);
return;
}
global $wpdb;
$wpaicgFormLogTable = $wpdb->prefix . 'wpaicg_form_logs';
$wpaicgFeedbackTable = $wpdb->prefix . 'wpaicg_form_feedback';
$resultLogs = $wpdb->query("TRUNCATE TABLE `$wpaicgFormLogTable`");
$resultFeedback = $wpdb->query("TRUNCATE TABLE `$wpaicgFeedbackTable`");
if ($resultLogs === false || $resultFeedback === false) {
wp_send_json_error(['message' => 'Failed to delete logs and feedback']);
} else {
wp_send_json_success(['message' => 'All logs and feedback have been deleted successfully']);
}
}
public function wpaicg_remove_tokens_limit()
{
global $wpdb;
$wpaicg_settings = get_option('wpaicg_limit_tokens_form', []);
$widget_reset_limit = isset($wpaicg_settings['reset_limit']) && !empty($wpaicg_settings['reset_limit'])
? $wpaicg_settings['reset_limit'] : 0;
if ($widget_reset_limit > 0) {
$widget_time = time() - ($widget_reset_limit * 86400);
$wpdb->query($wpdb->prepare(
"DELETE FROM " . $wpdb->prefix . "wpaicg_formtokens WHERE created_at < %s",
$widget_time
));
}
}
public function wpaicg_form_log()
{
global $wpdb;
$wpaicg_result = ['status' => 'success'];
$wpaicg_nonce = sanitize_text_field($_REQUEST['_wpnonce']);
if (!wp_verify_nonce($wpaicg_nonce, 'wpaicg-formlog')) {
$wpaicg_result['msg'] = esc_html__('Nonce verification failed', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
exit;
}
$required_fields = ['prompt_id', 'prompt_name', 'prompt_response', 'engine'];
foreach ($required_fields as $field) {
if (empty($_REQUEST[$field])) {
wp_send_json($wpaicg_result);
exit;
}
}
$userID = is_user_logged_in() ? get_current_user_id() : '';
if (isset($_REQUEST['id']) && !empty($_REQUEST['id'])) {
$prompt_id = sanitize_text_field($_REQUEST['id']);
}
$wpaicg_prompt = WPAICG_Playground::get_instance()->get_defined_prompt($prompt_id);
$log = [
'prompt' => wp_kses_post($wpaicg_prompt),
'data' => wp_kses_post($_REQUEST['prompt_response']),
'prompt_id'=> sanitize_text_field($_REQUEST['prompt_id']),
'name' => sanitize_text_field($_REQUEST['prompt_name']),
'model' => sanitize_text_field($_REQUEST['engine']),
'duration' => sanitize_text_field($_REQUEST['duration']),
'eventID' => sanitize_text_field($_REQUEST['eventID']),
'userID' => $userID,
'created_at' => time(),
];
if (!empty($_REQUEST['source_id'])) {
$log['source'] = sanitize_text_field($_REQUEST['source_id']);
}
$wpaicg_generator = WPAICG_Generator::get_instance();
$log['tokens'] = ceil($wpaicg_generator->wpaicg_count_words($log['data']) * 1000 / 750);
WPAICG_Account::get_instance()->save_log('forms', $log['tokens']);
$wpdb->insert($wpdb->prefix . 'wpaicg_form_logs', $log);
$wpaicg_playground = WPAICG_Playground::get_instance();
$wpaicg_tokens_handling = $wpaicg_playground->wpaicg_token_handling('form');
if ($wpaicg_tokens_handling['limit']) {
if ($wpaicg_tokens_handling['token_id']) {
$wpdb->update(
$wpdb->prefix . $wpaicg_tokens_handling['table'],
['tokens' => ($log['tokens'] + $wpaicg_tokens_handling['old_tokens'])],
['id' => $wpaicg_tokens_handling['token_id']]
);
} else {
$wpaicg_prompt_token_data = [
'tokens' => $log['tokens'],
'created_at' => time(),
];
if (is_user_logged_in()) {
$wpaicg_prompt_token_data['user_id'] = get_current_user_id();
} else {
$wpaicg_prompt_token_data['session_id'] = $wpaicg_tokens_handling['client_id'];
}
$wpdb->insert($wpdb->prefix . $wpaicg_tokens_handling['table'], $wpaicg_prompt_token_data);
}
}
wp_send_json($wpaicg_result);
}
function wpaicg_save_feedback() {
check_ajax_referer('wpaicg-ajax-nonce', 'nonce');
$formID = sanitize_text_field($_POST['formID']);
$eventID = sanitize_text_field($_POST['eventID']);
$feedback = sanitize_text_field($_POST['feedback']);
$comment = sanitize_textarea_field($_POST['comment']);
$formname = sanitize_text_field($_POST['formname']);
$sourceID = sanitize_text_field($_POST['sourceID']);
$formResponse = sanitize_text_field($_POST['response']);
global $wpdb;
$feedbackTable = $wpdb->prefix . 'wpaicg_form_feedback';
$inserted = $wpdb->insert($feedbackTable, [
'formID' => $formID,
'feedback' => $feedback,
'comment' => $comment,
'formname' => $formname,
'source' => $sourceID,
'response' => $formResponse,
'eventID' => $eventID,
'created_at' => current_time('mysql')
]);
if ($inserted) {
echo json_encode(['status' => 'success', 'msg' => esc_html__('Thank you for your feedback.', 'gpt3-ai-content-generator')]);
} else {
echo json_encode(['status' => 'error', 'msg' => esc_html__('Failed to save feedback.', 'gpt3-ai-content-generator')]);
}
wp_die();
}
function wpaicg_save_prompt_feedback() {
check_ajax_referer('wpaicg-ajax-nonce', 'nonce');
$formID = sanitize_text_field($_POST['formID']);
$eventID = sanitize_text_field($_POST['eventID']);
$feedback = sanitize_text_field($_POST['feedback']);
$comment = sanitize_textarea_field($_POST['comment']);
$formname = sanitize_text_field($_POST['formname']);
$sourceID = sanitize_text_field($_POST['sourceID']);
$formResponse = sanitize_text_field($_POST['response']);
global $wpdb;
$feedbackTable = $wpdb->prefix . 'wpaicg_prompt_feedback';
$inserted = $wpdb->insert($feedbackTable, [
'formID' => $formID,
'feedback' => $feedback,
'comment' => $comment,
'formname' => $formname,
'source' => $sourceID,
'response' => $formResponse,
'eventID' => $eventID,
'created_at' => current_time('mysql')
]);
if ($inserted) {
echo json_encode(['status' => 'success', 'msg' => esc_html__('Thank you for your feedback.', 'gpt3-ai-content-generator')]);
} else {
echo json_encode(['status' => 'error', 'msg' => esc_html__('Failed to save feedback.', 'gpt3-ai-content-generator')]);
}
wp_die();
}
public function wpaicg_template_delete()
{
$wpaicg_result = ['status' => 'success'];
if (!current_user_can('wpaicg_forms_forms')) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('You do not have permission for this action.', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
if (!wp_verify_nonce($_POST['nonce'], 'wpaicg-ajax-nonce')) {
$wpaicg_result['msg'] = esc_html__('Nonce verification failed', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
if (isset($_POST['id']) && !empty($_POST['id'])) {
wp_delete_post(sanitize_text_field($_POST['id']));
}
wp_send_json($wpaicg_result);
}
/**
* DUPLICATE FORMS (both custom and builtin).
*/
public function wpaicg_form_duplicate()
{
$wpaicg_result = ['status' => 'success'];
if (!current_user_can('wpaicg_forms_forms')) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('You do not have permission for this action.', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
if (!wp_verify_nonce($_POST['nonce'], 'wpaicg-ajax-nonce')) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Nonce verification failed', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$form_type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : '';
$builtin_id = isset($_POST['builtin_id']) ? intval($_POST['builtin_id']) : 0;
$db_id = isset($_POST['db_id']) ? intval($_POST['db_id']) : 0;
$current_user_id = get_current_user_id();
if (!$form_type) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Missing form type', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
// Duplicate from builtin .json file
if ($form_type === 'builtin' && $builtin_id > 0) {
$builtin_file = WPAICG_PLUGIN_DIR . 'admin/data/gptforms.json';
if (!file_exists($builtin_file)) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Built-in forms data file not found', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$json_content = file_get_contents($builtin_file);
$builtin_forms = json_decode($json_content, true);
if (!is_array($builtin_forms)) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Invalid built-in forms data', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$matched_form = null;
foreach ($builtin_forms as $bf) {
if (isset($bf['id']) && (int)$bf['id'] === $builtin_id) {
$matched_form = $bf;
break;
}
}
if (!$matched_form) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Built-in form not found', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$duplicated_title = isset($matched_form['title'])
? $matched_form['title'].' - Duplicated'
: 'Duplicated Form';
$duplicated_desc = isset($matched_form['description'])
? $matched_form['description']
: '';
// Insert new custom form
$new_form_id = wp_insert_post([
'post_author' => $current_user_id,
'post_title' => sanitize_text_field($duplicated_title),
'post_content' => wp_kses_post($duplicated_desc),
'post_status' => 'publish',
'post_type' => 'wpaicg_form',
]);
if (is_wp_error($new_form_id)) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Could not create duplicated form', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
// fields
$fieldsArr = isset($matched_form['fields']) ? $matched_form['fields'] : [];
$fieldsArr = $this->normalize_fields_array($fieldsArr);
$fieldsJson = json_encode($fieldsArr);
// Save meta
update_post_meta(
$new_form_id,
'wpaicg_form_prompt',
isset($matched_form['prompt']) ? wp_kses_post($matched_form['prompt']) : ''
);
update_post_meta($new_form_id, 'wpaicg_form_fields', $fieldsJson);
update_post_meta(
$new_form_id,
'wpaicg_form_response',
isset($matched_form['response']) ? $matched_form['response'] : 'div'
);
update_post_meta(
$new_form_id,
'wpaicg_form_category',
isset($matched_form['category']) ? $matched_form['category'] : ''
);
update_post_meta($new_form_id, 'wpaicg_form_engine', 'gpt-4o-mini');
update_post_meta($new_form_id, 'wpaicg_form_max_tokens', 1500);
update_post_meta($new_form_id, 'wpaicg_form_top_p', 1);
update_post_meta($new_form_id, 'wpaicg_form_best_of', 1);
update_post_meta(
$new_form_id,
'wpaicg_form_color',
isset($matched_form['color']) ? $matched_form['color'] : '#f9f9f9'
);
update_post_meta(
$new_form_id,
'wpaicg_form_icon',
isset($matched_form['icon']) ? $matched_form['icon'] : ''
);
// Additional defaults
update_post_meta($new_form_id, 'wpaicg_form_editor', 'div');
update_post_meta($new_form_id, 'wpaicg_form_header', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_embeddings', 'no');
update_post_meta($new_form_id, 'wpaicg_form_suffix_text', 'Context:');
update_post_meta($new_form_id, 'wpaicg_form_suffix_position', 'after');
update_post_meta($new_form_id, 'wpaicg_form_embeddings_limit', 1);
update_post_meta($new_form_id, 'wpaicg_form_use_default_embedding_model', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_copy_button', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_ddraft', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_dclear', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_dnotice', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_ddownload', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_copy_text', 'Copy');
update_post_meta($new_form_id, 'wpaicg_form_feedback_buttons', 'yes');
update_post_meta($new_form_id, 'wpaicg_form_generate_text', 'Generate');
update_post_meta($new_form_id, 'wpaicg_form_noanswer_text', 'Number of Answers');
update_post_meta($new_form_id, 'wpaicg_form_draft_text', 'Save Draft');
update_post_meta($new_form_id, 'wpaicg_form_clear_text', 'Clear');
update_post_meta($new_form_id, 'wpaicg_form_stop_text', 'Stop');
update_post_meta($new_form_id, 'wpaicg_form_cnotice_text', 'Please register to save your result');
update_post_meta($new_form_id, 'wpaicg_form_download_text', 'Download');
update_post_meta($new_form_id, 'wpaicg_form_category', 'generation');
update_post_meta($new_form_id, 'wpaicg_form_bgcolor', '#f9f9f9');
// NEW: also store default provider for duplicated built-in forms
update_post_meta($new_form_id, 'wpaicg_form_model_provider', 'OpenAI');
$wpaicg_result['msg'] = esc_html__('Built-in form duplicated successfully.', 'gpt3-ai-content-generator');
$wpaicg_result['new_id'] = $new_form_id;
wp_send_json($wpaicg_result);
}
// Duplicate from an existing custom form
if ($form_type === 'custom' && $db_id > 0) {
$promptbase = get_post($db_id);
if (!$promptbase || $promptbase->post_type !== 'wpaicg_form') {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Form not found or invalid', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$new_title = $promptbase->post_title . ' - Duplicated';
$wpaicg_prompt_id = wp_insert_post([
'post_author' => $current_user_id,
'post_title' => $new_title,
'post_type' => 'wpaicg_form',
'post_content' => $promptbase->post_content,
'post_status' => 'publish',
]);
if (is_wp_error($wpaicg_prompt_id)) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Error duplicating custom form', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
$post_meta = get_post_meta($promptbase->ID);
if ($post_meta) {
foreach ($post_meta as $meta_key => $meta_values) {
if ('_wp_old_slug' === $meta_key) {
continue;
}
if ('wpaicg_form_fields' === $meta_key) {
continue;
}
foreach ($meta_values as $meta_value) {
add_post_meta($wpaicg_prompt_id, $meta_key, $meta_value);
}
}
}
$fieldsJson = get_post_meta($db_id, 'wpaicg_form_fields', true);
if ($fieldsJson) {
$decodedFields = json_decode($fieldsJson, true);
if (is_array($decodedFields)) {
$decodedFields = $this->normalize_fields_array($decodedFields);
$fieldsJson = json_encode($decodedFields);
}
update_post_meta($wpaicg_prompt_id, 'wpaicg_form_fields', $fieldsJson);
}
$wpaicg_result['msg'] = esc_html__('Custom form duplicated successfully.', 'gpt3-ai-content-generator');
$wpaicg_result['new_id'] = $wpaicg_prompt_id;
wp_send_json($wpaicg_result);
}
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('Invalid duplication request', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
public function wpaicg_update_template()
{
$wpaicg_result = ['status' => 'error', 'msg' => esc_html__('Something went wrong', 'gpt3-ai-content-generator')];
if (!current_user_can('wpaicg_forms_forms')) {
$wpaicg_result['status'] = 'error';
$wpaicg_result['msg'] = esc_html__('You do not have permission for this action.', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
if (!wp_verify_nonce($_POST['_wpnonce'], 'wpaicg_formai_save')) {
$wpaicg_result['msg'] = esc_html__('Nonce verification failed', 'gpt3-ai-content-generator');
wp_send_json($wpaicg_result);
}
if (
isset($_POST['title']) && !empty($_POST['title']) &&
isset($_POST['description']) && !empty($_POST['description']) &&
isset($_POST['prompt']) && !empty($_POST['prompt'])
) {
$title = sanitize_text_field($_POST['title']);
$description = sanitize_text_field($_POST['description']);
if (isset($_POST['id']) && !empty($_POST['id'])) {
$wpaicg_prompt_id = sanitize_text_field($_POST['id']);
wp_update_post([
'ID' => $wpaicg_prompt_id,
'post_title' => $title,
'post_content' => $description
]);
} else {
$wpaicg_prompt_id = wp_insert_post([
'post_title' => $title,
'post_type' => 'wpaicg_form',
'post_content' => $description,
'post_status' => 'publish'
]);
}
$template_fields = [
'prompt','fields','response','category','engine','max_tokens','temperature',
'top_p','best_of','frequency_penalty','presence_penalty','stop','color','icon',
'editor','bgcolor','header','embeddings','vectordb','collections','pineconeindexes',
'suffix_text','suffix_position','embeddings_limit','use_default_embedding_model',
'selected_embedding_model','selected_embedding_provider','dans','ddraft','dclear',
'dnotice','ddownload','copy_button','copy_text','feedback_buttons','generate_text',
'noanswer_text','draft_text','clear_text','stop_text','cnotice_text','download_text',
// Must include model_provider here as well
'model_provider'
];
foreach ($template_fields as $template_field) {
if (isset($_POST[$template_field]) && !empty($_POST[$template_field])) {
if ($template_field === 'prompt') {
$value = wp_kses($_POST['prompt'], wp_kses_allowed_html('post'));
} else {
$value = wpaicg_util_core()->sanitize_text_or_array_field($_POST[$template_field]);
}
$key = sanitize_text_field($template_field);
if ($key === 'fields') {
$value = json_encode($value, JSON_UNESCAPED_UNICODE);
}
update_post_meta($wpaicg_prompt_id, 'wpaicg_form_' . $key, $value);
} elseif (
in_array($template_field, ['bgcolor','header','dans','ddraft','dclear','dnotice','ddownload','copy_button','feedback_buttons'], true) &&
(!isset($_POST[$template_field]) || empty($_POST[$template_field]))
) {
delete_post_meta($wpaicg_prompt_id, 'wpaicg_form_' . $template_field);
}
}
$wpaicg_result['status'] = 'success';
$wpaicg_result['id'] = $wpaicg_prompt_id;
}
wp_send_json($wpaicg_result);
}
/**
* Adds submenu pages for AI Forms
*/
public function wpaicg_menu()
{
$module_settings = get_option( 'wpaicg_module_settings' );
if ( $module_settings === false ) {
$module_settings = array_map(
fn() => true,
\WPAICG\WPAICG_Util::get_instance()->wpaicg_modules
);
}
$modules = \WPAICG\WPAICG_Util::get_instance()->wpaicg_modules;
if ( isset( $module_settings['ai_forms'] ) && $module_settings['ai_forms'] ) {
add_submenu_page(
'wpaicg',
esc_html( $modules['ai_forms']['title'] ),
esc_html( $modules['ai_forms']['title'] ),
$modules['ai_forms']['capability'],
$modules['ai_forms']['menu_slug'],
[ $this, $modules['ai_forms']['callback'] ],
$modules['ai_forms']['position']
);
}
}
/**
* Callback for shortcodes: [wpaicg_form id="..."]
*/
public function wpaicg_form_shortcode($atts)
{
$is_pro = \WPAICG\wpaicg_util_core()->wpaicg_is_pro();
// Conditionally enqueue the main AI Forms JS if not already enqueued
if ( ! wp_script_is('wpaicg-markedjs', 'enqueued') ) {
// If your form JS uses Marked.js for parsing, enqueue it now
wp_enqueue_script(
'wpaicg-markedjs',
WPAICG_PLUGIN_URL . 'public/js/marked.js',
array(),
null,
true
);
}
// Conditionally load jsPDF only
if ($is_pro && !wp_script_is('wpaicg-jspdf', 'enqueued')) {
$jspdf_path = WPAICG_PLUGIN_DIR . 'lib/js/jspdf.umd.min.js';
if (file_exists($jspdf_path)) {
wp_enqueue_script(
'wpaicg-jspdf',
WPAICG_PLUGIN_URL . 'lib/js/jspdf.umd.min.js',
array(),
null,
true
);
}
}
if ( ! wp_script_is('wpaicg-gpt-form', 'enqueued') ) {
// Enqueue the AI Form JS file only when the shortcode is rendered
wp_enqueue_script(
'wpaicg-gpt-form',
WPAICG_PLUGIN_URL . 'public/js/wpaicg-form-shortcode.js',
array('wpaicg-markedjs'), // so that Marked.js loads first
null,
true
);
}
// --- The rest of the shortcode logic remains identical ---
ob_start();
include WPAICG_PLUGIN_DIR . 'admin/extra/wpaicg_form_shortcode.php';
return ob_get_clean();
}
/**
* The callback used by existing AI Forms page
*/
public function wpaicg_forms()
{
include WPAICG_PLUGIN_DIR . 'admin/extra/wpaicg_forms.php';
}
private function wpaicg_safe_unserialize($data)
{
if (!is_serialized($data)) {
return $data;
}
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
$unserialized = @unserialize($data, ['allowed_classes' => false]);
} else {
$unserialized = @unserialize($data);
}
if ($unserialized === false && $data !== serialize(false)) {
return $data;
}
if (is_object($unserialized)) {
return null;
}
return $unserialized;
}
/**
* Return an array of all custom wpaicg_form post IDs (published).
*/
public function wpaicg_get_custom_forms_ids()
{
check_ajax_referer('wpaicg-get-forms-ids-nonce','nonce'); // or can be a more generic nonce
if(!current_user_can('manage_options')){
wp_send_json_error('No permission');
}
global $wpdb;
$ids = $wpdb->get_col("
SELECT ID
FROM {$wpdb->posts}
WHERE post_type = 'wpaicg_form'
AND post_status = 'publish'
ORDER BY post_date DESC
");
wp_send_json_success(['forms'=>$ids]);
}
/**
* Export a single form's data as JSON
*/
public function wpaicg_export_single_form()
{
check_ajax_referer('wpaicg-export-single-nonce','nonce');
if(!current_user_can('manage_options')){
wp_send_json_error('No permission');
}
$form_id = isset($_POST['form_id']) ? intval($_POST['form_id']) : 0;
if(!$form_id){
wp_send_json_error('Invalid form_id');
}
$post = get_post($form_id);
if(!$post || $post->post_type !== 'wpaicg_form'){
wp_send_json_error('No such custom form');
}
// Gather meta
$meta = get_post_meta($form_id);
// Flatten meta so that each meta_key => single value (or array if needed)
$safeMeta = [];
foreach($meta as $k => $v){
if(count($v) === 1){
$safeMeta[$k] = maybe_unserialize($v[0]);
} else {
// multiple values
$safeMeta[$k] = array_map('maybe_unserialize',$v);
}
}
// Return a simpler structure
$exportData = [
'title' => $post->post_title,
'content' => $post->post_content,
'meta' => $safeMeta,
];
wp_send_json_success($exportData);
}
/**
* Import a single form from provided JSON data
*/
public function wpaicg_import_single_form()
{
check_ajax_referer('wpaicg-import-single-nonce','nonce');
if(!current_user_can('manage_options')){
wp_send_json_error('No permission');
}
if(!isset($_POST['form_data'])){
wp_send_json_error('No form_data');
}
$rawData = json_decode(stripslashes($_POST['form_data']), true);
if(!is_array($rawData)){
wp_send_json_error('Invalid JSON data');
}
$title = isset($rawData['title']) ? sanitize_text_field($rawData['title']) : 'Untitled';
$content = isset($rawData['content']) ? wp_kses_post($rawData['content']) : '';
$metaArr = isset($rawData['meta']) ? $rawData['meta'] : [];
// Insert new custom form
$post_id = wp_insert_post([
'post_title' => $title,
'post_type' => 'wpaicg_form',
'post_content' => $content,
'post_status' => 'publish',
], true);
if(is_wp_error($post_id)){
wp_send_json_error('Could not import form: ' . $title);
}
if(is_array($metaArr)){
foreach($metaArr as $mKey => $mVal){
if(is_array($mVal) && isset($mVal[0])){
// Possibly an array with multiple values
foreach($mVal as $single){
add_post_meta($post_id, sanitize_text_field($mKey), maybe_serialize($single));
}
} else {
// single value
update_post_meta($post_id, sanitize_text_field($mKey), maybe_serialize($mVal));
}
}
}
wp_send_json_success(['imported_id'=>$post_id]);
}
/**
* Delete a single custom form by ID
*/
public function wpaicg_delete_single_form()
{
check_ajax_referer('wpaicg-delete-single-nonce','nonce');
if(!current_user_can('manage_options')){
wp_send_json_error('No permission');
}
$form_id = isset($_POST['form_id']) ? intval($_POST['form_id']) : 0;
if(!$form_id){
wp_send_json_error('Invalid form ID');
}
$post = get_post($form_id);
if(!$post || $post->post_type !== 'wpaicg_form'){
wp_send_json_error('Not a valid custom form');
}
wp_delete_post($form_id, true);
wp_send_json_success();
}
/**
* NEW: AJAX handler to create a brand-new form from the drag-and-drop builder.
*/
public function wpaicg_create_new_form()
{
check_ajax_referer('wpaicg_create_form_nonce', 'nonce');
if (!current_user_can('wpaicg_forms_forms')) {
wp_send_json_error([
'message' => esc_html__('You do not have permission for this action.', 'gpt3-ai-content-generator')
]);
}
$title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
$description = isset($_POST['description']) ? sanitize_text_field($_POST['description']) : '';
$prompt = isset($_POST['prompt']) ? wp_kses_post($_POST['prompt']) : '';
// Must read provider from posted data
$provider = isset($_POST['provider']) ? sanitize_text_field($_POST['provider']) : '';
$fields_json = isset($_POST['fields']) ? wp_unslash($_POST['fields']) : '';
$engine = isset($_POST['engine']) ? sanitize_text_field($_POST['engine']) : 'gpt-4o-mini';
$model_settings = isset($_POST['model_settings']) ? (array) $_POST['model_settings'] : [];
$wpaicg_max_tokens = isset($model_settings['max_tokens']) ? intval($model_settings['max_tokens']) : 1500;
$wpaicg_top_p = isset($model_settings['top_p']) ? floatval($model_settings['top_p']) : 1;
$wpaicg_best_of = isset($model_settings['best_of']) ? intval($model_settings['best_of']) : 1;
$wpaicg_frequency_penalty = isset($model_settings['frequency_penalty']) ? floatval($model_settings['frequency_penalty']) : 0;
$wpaicg_presence_penalty = isset($model_settings['presence_penalty']) ? floatval($model_settings['presence_penalty']) : 0;
$wpaicg_stop = isset($model_settings['stop']) ? sanitize_text_field($model_settings['stop']) : '';
if (empty($title) || empty($description) || empty($prompt)) {
wp_send_json_error([
'message' => esc_html__('Required fields missing: title, description, or prompt', 'gpt3-ai-content-generator')
]);
}
$post_id = wp_insert_post([
'post_title' => $title,
'post_type' => 'wpaicg_form',
'post_content' => $description,
'post_status' => 'publish'
]);
if (is_wp_error($post_id)) {
wp_send_json_error([
'message' => esc_html__('Failed to create new form', 'gpt3-ai-content-generator')
]);
}
// Correct: store provider in wpaicg_form_model_provider
update_post_meta($post_id, 'wpaicg_form_model_provider', $provider);
update_post_meta($post_id, 'wpaicg_form_prompt', $prompt);
if (!empty($fields_json)) {
update_post_meta($post_id, 'wpaicg_form_fields', $fields_json);
}
update_post_meta($post_id, 'wpaicg_form_engine', $engine);
update_post_meta($post_id, 'wpaicg_form_max_tokens', $wpaicg_max_tokens);
update_post_meta($post_id, 'wpaicg_form_top_p', $wpaicg_top_p);
update_post_meta($post_id, 'wpaicg_form_best_of', $wpaicg_best_of);
update_post_meta($post_id, 'wpaicg_form_frequency_penalty', $wpaicg_frequency_penalty);
update_post_meta($post_id, 'wpaicg_form_presence_penalty', $wpaicg_presence_penalty);
update_post_meta($post_id, 'wpaicg_form_stop', $wpaicg_stop);
// Embedding
$embedding_settings = isset($_POST['embedding_settings']) ? (array) $_POST['embedding_settings'] : [];
$use_embeddings = !empty($embedding_settings['use_embeddings']) ? sanitize_text_field($embedding_settings['use_embeddings']) : 'no';
update_post_meta($post_id, 'wpaicg_form_embeddings', $use_embeddings);
$vector_db = !empty($embedding_settings['vectordb']) ? sanitize_text_field($embedding_settings['vectordb']) : 'pinecone';
update_post_meta($post_id, 'wpaicg_form_vectordb', $vector_db);
$collections = !empty($embedding_settings['collections']) ? sanitize_text_field($embedding_settings['collections']) : '';
update_post_meta($post_id, 'wpaicg_form_collections', $collections);
$pineconeindexes = !empty($embedding_settings['pineconeindexes']) ? sanitize_text_field($embedding_settings['pineconeindexes']) : '';
update_post_meta($post_id, 'wpaicg_form_pineconeindexes', $pineconeindexes);
$suffix_text = !empty($embedding_settings['suffix_text']) ? sanitize_text_field($embedding_settings['suffix_text']) : 'Context:';
update_post_meta($post_id, 'wpaicg_form_suffix_text', $suffix_text);
$suffix_position = !empty($embedding_settings['suffix_position']) ? sanitize_text_field($embedding_settings['suffix_position']) : 'after';
update_post_meta($post_id, 'wpaicg_form_suffix_position', $suffix_position);
$use_default = !empty($embedding_settings['use_default_embedding_model']) ? sanitize_text_field($embedding_settings['use_default_embedding_model']) : 'yes';
update_post_meta($post_id, 'wpaicg_form_use_default_embedding_model', $use_default);
$selected_provider = !empty($embedding_settings['selected_embedding_provider']) ? sanitize_text_field($embedding_settings['selected_embedding_provider']) : '';
update_post_meta($post_id, 'wpaicg_form_selected_embedding_provider', $selected_provider);
$selected_model = !empty($embedding_settings['selected_embedding_model']) ? sanitize_text_field($embedding_settings['selected_embedding_model']) : '';
update_post_meta($post_id, 'wpaicg_form_selected_embedding_model', $selected_model);
$embed_limit = !empty($embedding_settings['embeddings_limit']) ? intval($embedding_settings['embeddings_limit']) : 1;
update_post_meta($post_id, 'wpaicg_form_embeddings_limit', $embed_limit);
// Interface
$interfaceFields = [
'wpaicg_form_response' => 'div',
'wpaicg_form_category' => '',
'wpaicg_form_color' => '#f9f9f9',
'wpaicg_form_icon' => '',
'wpaicg_form_editor' => 'div',
'wpaicg_form_header' => 'yes',
'wpaicg_form_copy_button' => 'yes',
'wpaicg_form_ddraft' => 'yes',
'wpaicg_form_dclear' => 'yes',
'wpaicg_form_dnotice' => 'yes',
'wpaicg_form_ddownload' => 'yes',
'wpaicg_form_copy_text' => 'Copy',
'wpaicg_form_feedback_buttons' => 'yes',
'wpaicg_form_generate_text' => 'Generate',
'wpaicg_form_noanswer_text' => 'Number of Answers',
'wpaicg_form_draft_text' => 'Save Draft',
'wpaicg_form_clear_text' => 'Clear',
'wpaicg_form_stop_text' => 'Stop',
'wpaicg_form_cnotice_text' => 'Please register to save your result',
'wpaicg_form_download_text' => 'Download',
'wpaicg_form_bgcolor' => '#f9f9f9',
];
if (isset($_POST['interface']) && is_array($_POST['interface'])) {
foreach ($interfaceFields as $ik => $defaultVal) {
$val = isset($_POST['interface'][$ik]) ? sanitize_text_field($_POST['interface'][$ik]) : $defaultVal;
update_post_meta($post_id, $ik, $val);
}
} else {
foreach ($interfaceFields as $ik => $df) {
update_post_meta($post_id, $ik, $df);
}
}
// NEW: Internet Browsing toggle (yes/no)
$internet_browsing = isset($_POST['internet_browsing']) ? sanitize_text_field($_POST['internet_browsing']) : 'no';
update_post_meta($post_id, 'wpaicg_form_internet_browsing', $internet_browsing);
wp_send_json_success([
'message' => esc_html__('Form created successfully', 'gpt3-ai-content-generator'),
'id' => $post_id
]);
}
/******************************************************
* NEW: GET LOGS WITH PAGINATION & INSTANT SEARCH
******************************************************/
public function wpaicg_get_logs() {
check_ajax_referer( 'wpaicg-ajax-nonce', 'nonce' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error( [ 'message' => 'No permission' ] );
}
global $wpdb;
$table_name = $wpdb->prefix . 'wpaicg_form_logs';
$feedbackTable = $wpdb->prefix . 'wpaicg_form_feedback';
$search = isset( $_POST['search'] ) ? sanitize_text_field( $_POST['search'] ) : '';
$page = isset( $_POST['page'] ) ? intval( $_POST['page'] ) : 1;
$per_page = 10;
$offset = ( $page - 1 ) * $per_page;
$total = 0;
$rows = [];
if ( ! empty( $search ) ) {
$like = '%' . $wpdb->esc_like( $search ) . '%';
$total = $wpdb->get_var(
$wpdb->prepare(
"
SELECT COUNT(*)
FROM {$table_name} l
LEFT JOIN {$feedbackTable} f ON l.eventID = f.eventID
WHERE name LIKE %s OR model LIKE %s OR prompt LIKE %s OR data LIKE %s OR duration LIKE %s OR tokens LIKE %s
",
$like, $like, $like, $like, $like, $like
)
);
$rows = $wpdb->get_results(
$wpdb->prepare(
"
SELECT l.*, f.feedback, f.comment
FROM {$table_name} l
LEFT JOIN {$feedbackTable} f ON l.eventID = f.eventID
WHERE name LIKE %s OR model LIKE %s OR prompt LIKE %s OR data LIKE %s OR duration LIKE %s OR tokens LIKE %s
ORDER BY created_at DESC
LIMIT %d, %d
",
$like, $like, $like, $like, $like, $like, $offset, $per_page
)
);
} else {
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static query with no user input
$total = $wpdb->get_var(
"SELECT COUNT(*) FROM {$table_name} l LEFT JOIN {$feedbackTable} f ON l.eventID = f.eventID"
);
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static query with safe LIMIT clause
$rows = $wpdb->get_results(
$wpdb->prepare(
"
SELECT l.*, f.feedback, f.comment
FROM {$table_name} l
LEFT JOIN {$feedbackTable} f ON l.eventID = f.eventID
ORDER BY created_at DESC
LIMIT %d, %d
",
$offset,
$per_page
)
);
}
$total_pages = max( 1, (int) ceil( $total / $per_page ) );
if ( $page < 1 ) {
$page = 1;
}
if ( $page > $total_pages ) {
$page = $total_pages;
}
$html_rows = '';
if ( $rows ) {
foreach ( $rows as $row ) {
$id = $row->id;
$name = esc_html( $row->name );
$model = esc_html( $row->model );
$duration = esc_html( $row->duration );
$tokens = intval( $row->tokens );
$feedbackVal = isset( $row->feedback ) ? $row->feedback : '';
$feedbackDisplay = $feedbackVal === 'thumbs_up' ? '👍' : ( $feedbackVal === 'thumbs_down' ? '👎' : '' );
$comment = isset( $row->comment ) ? esc_html( $row->comment ) : '';
$fullPrompt = $row->prompt;
$fullResponse = $row->data;
$cleanResponse = wp_strip_all_tags( $fullResponse );
$truncatedData = function_exists( 'mb_strlen' )
? ( mb_strlen( $cleanResponse ) > 25 ? mb_substr( $cleanResponse, 0, 25 ) . '...' : $cleanResponse )
: ( strlen( $cleanResponse ) > 25 ? substr( $cleanResponse, 0, 25 ) . '...' : $cleanResponse );
$created = date_i18n( 'Y-m-d H:i:s', $row->created_at );
$html_rows .= "<tr>
<td>{$id}</td>
<td>{$name}</td>
<td>{$model}</td>
<td>{$duration}</td>
<td>{$tokens}</td>
<td>
<span class='wpaicg_log_view'
data-fullprompt='" . esc_attr( $fullPrompt ) . "'
data-fullresponse='" . esc_attr( $fullResponse ) . "'>
" . esc_html( $truncatedData ) . "
</span>
</td>
<td>{$feedbackDisplay}</td>
<td>{$comment}</td>
<td>{$created}</td>
</tr>";
}
} else {
$html_rows = '<tr><td colspan="9">' . esc_html__( 'No logs found', 'gpt3-ai-content-generator' ) . '</td></tr>';
}
$pagination_html = $this->wpaicg_build_pagination_html( $page, $total_pages );
wp_send_json_success( [
'table_rows' => $html_rows,
'pagination' => $pagination_html,
'total' => $total,
] );
}
private function wpaicg_build_pagination_html(int $current_page, int $total_pages): string
{
if ($total_pages <= 1) {
return '';
}
$html = '<div class="wpaicg_logs_pagination">';
// Page 1
if ($current_page > 1) {
$html .= '<span class="wpaicg_logs_page_link" data-page="1">1</span>';
} else {
$html .= '<span class="wpaicg_logs_page_link active" data-page="1">1</span>';
}
if ($current_page > 3) {
$html .= '<span class="wpaicg_logs_page_ellipsis">…</span>';
}
$start = max(2, $current_page - 1);
$end = min($total_pages - 1, $current_page + 1);
for ($i = $start; $i <= $end; $i++) {
if ($i === 1 || $i === $total_pages) {
continue;
}
if ($i === $current_page) {
$html .= '<span class="wpaicg_logs_page_link active" data-page="'.$i.'">'.$i.'</span>';
} else {
$html .= '<span class="wpaicg_logs_page_link" data-page="'.$i.'">'.$i.'</span>';
}
}
if ($current_page < $total_pages - 2) {
$html .= '<span class="wpaicg_logs_page_ellipsis">…</span>';
}
if ($current_page < $total_pages) {
$html .= '<span class="wpaicg_logs_page_link" data-page="'.$total_pages.'">'.$total_pages.'</span>';
} else {
if ($total_pages > 1) {
$html .= '<span class="wpaicg_logs_page_link active" data-page="'.$total_pages.'">'.$total_pages.'</span>';
}
}
$html .= '</div>';
return $html;
}
}
WPAICG_Forms::get_instance();
}