2, 'deptid' => 1, 'language' => $lang ), self::TICKET_URL ); } public static function init() { add_action('wp_ajax_mgenius_send_support', [__CLASS__, 'ajax_send']); add_action('wp_ajax_mgenius_get_support_report', [__CLASS__, 'ajax_get_report']); } /* ═══════════════════════════════════════════ RAPPORT SYSTÈME ═══════════════════════════════════════════ */ /** * Rapport complet, structuré. Liste blanche stricte : rien de sensible. * * @return array */ public static function build_report() { global $wp_version, $wpdb; $settings = class_exists('MGENIUS_Settings') ? MGENIUS_Settings::load_fresh() : []; $theme = wp_get_theme(); // — Mode actif if (empty($settings['maintenance_enabled'])) { $mode = 'off'; } else { $mode = (!empty($settings['page_mode']) && 'coming_soon' === $settings['page_mode']) ? 'coming_soon' : 'maintenance'; } // — Plugins actifs avec versions if (!function_exists('get_plugins')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = get_plugins(); $active_plugins = []; foreach ((array) get_option('active_plugins', []) as $plugin) { $active_plugins[] = isset($all_plugins[$plugin]) ? $all_plugins[$plugin]['Name'] . ' ' . $all_plugins[$plugin]['Version'] : $plugin; } if (is_multisite()) { foreach (array_keys((array) get_site_option('active_sitewide_plugins', [])) as $plugin) { $active_plugins[] = isset($all_plugins[$plugin]) ? $all_plugins[$plugin]['Name'] . ' ' . $all_plugins[$plugin]['Version'] . ' (network)' : $plugin . ' (network)'; } } // — mu-plugins $mu_plugins = []; if (function_exists('get_mu_plugins')) { foreach (get_mu_plugins() as $mu) { $mu_plugins[] = $mu['Name'] . (empty($mu['Version']) ? '' : ' ' . $mu['Version']); } } // — Diagnostic (échecs en tête : la moitié des tickets se résolvent là) $diagnostic = ['status' => 'never_run', 'checks' => []]; if (class_exists('MGENIUS_Diagnostic')) { $results = MGENIUS_Diagnostic::get_results(); if ($results && !empty($results['checks'])) { $fail = []; $warn = []; $rest = []; foreach ($results['checks'] as $id => $check) { $status = isset($check['status']) ? $check['status'] : 'unknown'; $line = $id . ': ' . $status . (empty($check['label']) ? '' : ' — ' . wp_strip_all_tags($check['label'])); if ('fail' === $status) { $fail[] = $line; } elseif ('warn' === $status) { $warn[] = $line; } else { $rest[] = $line; } } $diagnostic = [ 'status' => 'ok', 'last_scan' => empty($results['timestamp']) ? '' : gmdate('Y-m-d H:i', (int) $results['timestamp']) . ' UTC', 'checks' => array_merge($fail, $warn, $rest), ]; } } // — Réglages MG non sensibles uniquement (liste blanche) $safe_settings = [ 'theme' => (class_exists('MGENIUS_Settings') && method_exists('MGENIUS_Settings', 'get_active_theme') && MGENIUS_Settings::get_active_theme()) ? MGENIUS_Settings::get_active_theme() : (isset($settings['preset']) ? $settings['preset'] : 'none'), 'countdown' => !empty($settings['countdown_enabled']) ? 'on' : 'off', 'notifications' => !empty($settings['notification_enabled']) ? 'on' : 'off', 'visitor_access' => !empty($settings['visitor_access_enabled']) ? 'on' : 'off', 'schedule' => !empty($settings['schedule_enabled']) ? 'on' : 'off', 'http_503' => !empty($settings['seo_503_enabled']) ? 'on' : 'off', 'noindex' => !empty($settings['noindex_enabled']) ? 'on' : 'off', 'rgpd_mode' => !empty($settings['rgpd_mode']) ? 'on' : 'off', 'turnstile' => !empty($settings['turnstile_enabled']) ? 'on' : 'off', 'stats' => !empty($settings['stats_enabled']) ? 'on' : 'off', 'credit_displayed' => !empty($settings['show_powered_by']) ? 'on' : 'off', ]; return [ 'plugin' => [ 'version' => MGENIUS_VERSION, 'mode' => $mode, 'build' => 'wordpress.org', 'settings' => $safe_settings, ], 'wordpress' => [ 'version' => $wp_version, 'site_locale' => get_locale(), 'user_locale' => get_user_locale(), 'multisite' => is_multisite() ? 'yes' : 'no', 'debug' => (defined('WP_DEBUG') && WP_DEBUG) ? 'on' : 'off', 'memory_limit' => defined('WP_MEMORY_LIMIT') ? WP_MEMORY_LIMIT : '', 'wp_cron' => (defined('DISABLE_WP_CRON') && DISABLE_WP_CRON) ? 'disabled' : 'enabled', 'permalinks' => get_option('permalink_structure') ? 'pretty' : 'plain', 'timezone' => wp_timezone_string(), 'https' => is_ssl() ? 'yes' : 'no', 'home_url' => home_url('/'), ], 'theme' => [ 'name' => $theme->get('Name'), 'version' => $theme->get('Version'), 'parent' => $theme->parent() ? $theme->parent()->get('Name') . ' ' . $theme->parent()->get('Version') : 'none', ], 'plugins' => $active_plugins, 'mu_plugins' => $mu_plugins, 'cache' => self::detect_cache(), 'server' => [ 'php' => PHP_VERSION, 'software' => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '', 'mysql' => $wpdb->db_version(), 'memory_limit' => ini_get('memory_limit'), 'max_upload' => size_format(wp_max_upload_size()), 'curl' => function_exists('curl_version') ? 'yes' : 'no', 'openssl' => extension_loaded('openssl') ? 'yes' : 'no', 'object_cache' => wp_using_ext_object_cache() ? 'yes' : 'no', ], 'diagnostic' => $diagnostic, ]; } /** * Plugins de cache actifs (cause n° 1 des tickets « la page ne s'affiche pas »). * * @return array */ private static function detect_cache() { $known = [ 'wp-rocket/wp-rocket.php' => 'WP Rocket', 'litespeed-cache/litespeed-cache.php' => 'LiteSpeed Cache', 'wp-fastest-cache/wpFastestCache.php' => 'WP Fastest Cache', 'wp-fastest-cache-premium/wpFastestCachePremium.php' => 'WP Fastest Cache Premium', 'w3-total-cache/w3-total-cache.php' => 'W3 Total Cache', 'wp-super-cache/wp-cache.php' => 'WP Super Cache', 'seraphinite-accelerator/seraphinite-accelerator.php' => 'Seraphinite Accelerator', 'autoptimize/autoptimize.php' => 'Autoptimize', 'nitropack/main.php' => 'NitroPack', 'cache-enabler/cache-enabler.php' => 'Cache Enabler', 'sg-cachepress/sg-cachepress.php' => 'SiteGround Optimizer', 'breeze/breeze.php' => 'Breeze', ]; $found = []; $active = (array) get_option('active_plugins', []); foreach ($known as $file => $name) { if (in_array($file, $active, true)) { $found[] = $name; } } if (defined('WP_CACHE') && WP_CACHE) { $found[] = 'WP_CACHE constant on'; } return empty($found) ? ['none detected'] : $found; } /** * Rapport en texte lisible (corps du courriel + bouton « Copier »). * * @return string */ public static function report_as_text() { $r = self::build_report(); $lines = []; $lines[] = '=== 1001WEB MAINTENANCE & LAUNCH PAGES — SUPPORT REPORT ==='; $lines[] = ''; $lines[] = '[PLUGIN]'; $lines[] = 'Version: ' . $r['plugin']['version']; $lines[] = 'Mode: ' . $r['plugin']['mode']; foreach ($r['plugin']['settings'] as $k => $v) { $lines[] = ' ' . $k . ': ' . $v; } $lines[] = ''; $lines[] = '[WordPress]'; foreach ($r['wordpress'] as $k => $v) { $lines[] = $k . ': ' . $v; } $lines[] = ''; $lines[] = '[THEME]'; $lines[] = $r['theme']['name'] . ' ' . $r['theme']['version'] . ' (parent: ' . $r['theme']['parent'] . ')'; $lines[] = ''; $lines[] = '[CACHE]'; $lines[] = implode(', ', $r['cache']); $lines[] = ''; $lines[] = '[SERVER]'; foreach ($r['server'] as $k => $v) { $lines[] = $k . ': ' . $v; } $lines[] = ''; $lines[] = '[DIAGNOSTIC]'; if ('never_run' === $r['diagnostic']['status']) { $lines[] = 'Never run.'; } else { $lines[] = 'Last scan: ' . $r['diagnostic']['last_scan']; foreach ($r['diagnostic']['checks'] as $c) { $lines[] = ' ' . $c; } } $lines[] = ''; $lines[] = '[ACTIVE PLUGINS] (' . count($r['plugins']) . ')'; foreach ($r['plugins'] as $p) { $lines[] = ' ' . $p; } if (!empty($r['mu_plugins'])) { $lines[] = ''; $lines[] = '[MU-PLUGINS]'; foreach ($r['mu_plugins'] as $p) { $lines[] = ' ' . $p; } } $lines[] = ''; $lines[] = '=== END OF REPORT ==='; return implode("\n", $lines); } /* ═══════════════════════════════════════════ AJAX ═══════════════════════════════════════════ */ /** * Aperçu du rapport (lien « Voir le contenu » — transparence avant envoi). */ public static function ajax_get_report() { check_ajax_referer('mgenius_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Permission denied', '1001web-maintenance-launch-pages')]); } wp_send_json_success(['report' => self::report_as_text()]); } /** * Envoi de la demande d'assistance. * Échec d'envoi = on renvoie le rapport pour le filet copier/coller. */ public static function ajax_send() { check_ajax_referer('mgenius_nonce', 'nonce'); if (!current_user_can('manage_options')) { wp_send_json_error(['message' => __('Permission denied', '1001web-maintenance-launch-pages')]); } $report = self::report_as_text(); // Anti-spam simple : 1 envoi / 2 minutes if (get_transient('mgenius_support_sent')) { wp_send_json_error([ 'message' => __('A request was just sent. Please wait a couple of minutes before sending another.', '1001web-maintenance-launch-pages'), 'report' => $report, 'ticket_url' => self::ticket_url(), ]); } // Consentement exige aussi cote serveur. if (empty($_POST['consent'])) { wp_send_json_error(['message' => __('Please confirm that your information may be used to handle your request.', '1001web-maintenance-launch-pages')]); } $email = isset($_POST['email']) ? sanitize_email(wp_unslash($_POST['email'])) : ''; if (!is_email($email)) { wp_send_json_error(['message' => __('Please enter a valid email address.', '1001web-maintenance-launch-pages')]); } $description = isset($_POST['description']) ? sanitize_textarea_field(wp_unslash($_POST['description'])) : ''; if (strlen(trim($description)) < 10) { wp_send_json_error(['message' => __('Please describe the problem in a sentence or two.', '1001web-maintenance-launch-pages')]); } $problem_type = isset($_POST['problem_type']) ? sanitize_text_field(wp_unslash($_POST['problem_type'])) : 'other'; $since = isset($_POST['since']) ? sanitize_text_field(wp_unslash($_POST['since'])) : ''; $steps = isset($_POST['steps']) ? sanitize_textarea_field(wp_unslash($_POST['steps'])) : ''; $url = isset($_POST['url']) ? esc_url_raw(wp_unslash($_POST['url'])) : home_url('/'); $labels = [ 'page_not_showing' => 'Maintenance page does not show', 'page_stuck' => 'Page stays after turning maintenance off', 'design' => 'Appearance or design', 'countdown_emails' => 'Countdown or email notifications', 'access' => 'Access, passwords or tokens', 'other' => 'Something else', ]; $problem_label = isset($labels[$problem_type]) ? $labels[$problem_type] : $problem_type; $since_labels = [ 'after_plugin_update' => 'After a plugin update', 'after_other_plugin' => 'After installing another plugin', 'after_hosting_change' => 'After a hosting or server change', 'always' => 'It never worked', 'unknown' => 'Not sure', ]; $since_label = isset($since_labels[$since]) ? $since_labels[$since] : 'Not specified'; $site_host = wp_parse_url(home_url(), PHP_URL_HOST); $subject = sprintf('[MG Support] %s — %s — v%s', $problem_label, $site_host, MGENIUS_VERSION); $body = "PROBLEM: " . $problem_label . "\n"; $body .= "SINCE: " . $since_label . "\n"; $body .= "URL: " . $url . "\n"; $body .= "CONTACT: " . $email . "\n\n"; $body .= "DESCRIPTION:\n" . $description . "\n\n"; if ($steps) { $body .= "STEPS TO REPRODUCE:\n" . $steps . "\n\n"; } $body .= str_repeat('-', 60) . "\n\n" . $report; $headers = [ 'Content-Type: text/plain; charset=UTF-8', 'Reply-To: ' . $email, ]; $sent = wp_mail(self::SUPPORT_EMAIL, $subject, $body, $headers); if (!$sent) { wp_send_json_error([ 'message' => __('Your site could not send the email (a common server configuration issue). Copy the report below and open a ticket — we have everything we need.', '1001web-maintenance-launch-pages'), 'report' => $body, 'ticket_url' => self::ticket_url(), ]); } set_transient('mgenius_support_sent', 1, 2 * MINUTE_IN_SECONDS); wp_send_json_success([ 'message' => __('Request sent. We reply within 24–48 business hours, by email.', '1001web-maintenance-launch-pages'), ]); } }