$token)); } public function save_post_css() { // Vérifier que les données POST existent if (!isset($_POST['nonce']) || !isset($_POST['post_id']) || !isset($_POST['css_content'])) { wp_send_json_error('Missing required data'); } // Déséchapper et assainir les données $nonce = sanitize_text_field(wp_unslash($_POST['nonce'])); $post_id = intval($_POST['post_id']); $css_content = wp_unslash($_POST['css_content']); $css_type = isset($_POST['css_type']) ? sanitize_text_field(wp_unslash($_POST['css_type'])) : 'page'; // Vérifier le nonce if (!wp_verify_nonce($nonce, 'aibui_nonce')) { wp_die('Security check failed'); } // Vérifier que l'utilisateur peut éditer ce post if (!current_user_can('edit_post', $post_id)) { wp_send_json_error('Insufficient permissions'); } if ($css_type === 'page') { // Pour les pages, remplacer complètement le CSS de page update_post_meta($post_id, 'ai_builder_page_css_content', $css_content); // Récupérer le CSS de blocs existant $block_css = get_post_meta($post_id, 'ai_builder_block_css_content', true); // Combiner page CSS + block CSS pour le CSS final $final_css = $css_content; if (!empty($block_css)) { $final_css .= "\n" . $block_css; } update_post_meta($post_id, 'ai_builder_css_content', $final_css); error_log("CSS Debug - Saving PAGE CSS. Page length: " . strlen($css_content) . ", Block length: " . strlen($block_css) . ", Final length: " . strlen($final_css)); } else if ($css_type === 'block') { // Pour les blocs, ajouter au CSS existant $page_css = get_post_meta($post_id, 'ai_builder_page_css_content', true); $block_css = get_post_meta($post_id, 'ai_builder_block_css_content', true); if (empty($page_css)) { $page_css = ''; } if (empty($block_css)) { $block_css = ''; } // Ajouter le nouveau CSS de bloc $block_css .= "\n/* Block CSS - " . date('Y-m-d H:i:s') . " */\n" . $css_content . "\n"; // Sauvegarder le CSS de bloc update_post_meta($post_id, 'ai_builder_block_css_content', $block_css); // Combiner page CSS + block CSS pour le CSS final $final_css = $page_css; if (!empty($block_css)) { $final_css .= "\n" . $block_css; } update_post_meta($post_id, 'ai_builder_css_content', $final_css); error_log("CSS Debug - Saving BLOCK CSS. Page length: " . strlen($page_css) . ", Block length: " . strlen($block_css) . ", Final length: " . strlen($final_css)); } wp_send_json_success('CSS saved successfully'); } public function get_post_css() { // Vérifier que les données POST existent if (!isset($_POST['nonce']) || !isset($_POST['post_id'])) { wp_send_json_error('Missing required data'); } // Déséchapper et assainir les données $nonce = sanitize_text_field(wp_unslash($_POST['nonce'])); $post_id = intval($_POST['post_id']); // Vérifier le nonce if (!wp_verify_nonce($nonce, 'aibui_nonce')) { wp_die('Security check failed'); } // Vérifier que l'utilisateur peut lire ce post if (!current_user_can('read_post', $post_id)) { wp_send_json_error('Insufficient permissions'); } // Récupérer les CSS depuis les meta du post $page_css = get_post_meta($post_id, 'ai_builder_page_css_content', true); $block_css = get_post_meta($post_id, 'ai_builder_block_css_content', true); $combined_css = get_post_meta($post_id, 'ai_builder_css_content', true); // Log pour debug error_log("CSS Debug - Page CSS length: " . strlen($page_css)); error_log("CSS Debug - Block CSS length: " . strlen($block_css)); error_log("CSS Debug - Combined CSS length: " . strlen($combined_css)); wp_send_json_success(array( 'pageCss' => $page_css, 'blockCss' => $block_css, 'combinedCss' => $combined_css )); } public function save_meta_description() { if (!isset($_POST['nonce']) || !isset($_POST['post_id'])) { wp_send_json_error('Missing required data'); } $nonce = sanitize_text_field(wp_unslash($_POST['nonce'])); if (!wp_verify_nonce($nonce, 'aibui_nonce')) { wp_die('Security check failed'); } $post_id = intval($_POST['post_id']); if (!current_user_can('edit_post', $post_id)) { wp_send_json_error('Insufficient permissions'); } $raw = isset($_POST['meta_desc']) ? wp_unslash($_POST['meta_desc']) : ''; $san = trim(wp_strip_all_tags($raw)); if (strlen($san) > 320) { $san = mb_substr($san, 0, 320); } if ($san === '') { delete_post_meta($post_id, 'aibui_meta_description'); } else { update_post_meta($post_id, 'aibui_meta_description', $san); } wp_send_json_success('Meta description saved'); } // Capture wp_mail() errors and store briefly to surface via AJAX public function capture_mail_error($wp_error) { $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $key = 'aibui_cf_mailerr_' . md5($ip); set_transient($key, $wp_error instanceof WP_Error ? $wp_error->get_error_message() : 'Unknown mail error', 120); if (defined('WP_DEBUG') && WP_DEBUG) { error_log('[AIBUI] wp_mail_failed: ' . (is_object($wp_error) && method_exists($wp_error, 'get_error_message') ? $wp_error->get_error_message() : print_r($wp_error, true))); } } public function submit_contact_form() { if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'aibui_contact_form')) { wp_send_json_error('Invalid nonce'); } // Rate limiting per IP: 1 submission per 30 seconds $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown'; $key = 'aibui_cf_rl_' . md5($ip); $last = get_transient($key); if ($last) { wp_send_json_error('Too many requests. Please wait.'); } set_transient($key, time(), 30); $recipient = isset($_POST['recipient']) ? sanitize_email(wp_unslash($_POST['recipient'])) : ''; if (empty($recipient) || !is_email($recipient)) { $recipient = sanitize_email(get_option('admin_email')); } if (empty($recipient) || !is_email($recipient)) { wp_send_json_error('No valid recipient configured'); } $subject = sprintf('[%s] Nouveau message de contact', get_bloginfo('name')); $fields = []; $sender_email = ''; foreach ($_POST as $key => $value) { if (strpos($key, 'field_') === 0) { $label_key = 'label_' . $key; $type_key = 'type_' . $key; $req_key = 'required_' . $key; $label = isset($_POST[$label_key]) ? sanitize_text_field(wp_unslash($_POST[$label_key])) : 'Champ'; $type = isset($_POST[$type_key]) ? sanitize_text_field(wp_unslash($_POST[$type_key])) : 'text'; $is_required = isset($_POST[$req_key]) && wp_unslash($_POST[$req_key]) === '1'; $raw = wp_unslash($value); switch ($type) { case 'email': $san = sanitize_email($raw); if (!$sender_email && is_email($san)) { $sender_email = $san; } break; case 'number': $san = is_numeric($raw) ? $raw : ''; break; case 'date': $san = preg_match('/^\\d{4}-\\d{2}-\\d{2}$/', $raw) ? $raw : ''; break; case 'textarea': $san = sanitize_textarea_field($raw); break; default: $san = sanitize_text_field($raw); } if ($is_required && $san === '') { wp_send_json_error(sprintf('%s est requis', $label ? $label : 'Ce champ')); } $fields[] = ['label' => $label, 'type' => $type, 'value' => $san]; } } if (empty($fields)) { wp_send_json_error('No fields provided'); } // Build HTML email content $rows = ''; foreach ($fields as $f) { $val = $f['type'] === 'textarea' ? nl2br(esc_html($f['value'])) : esc_html($f['value']); $rows .= '