db = WP_Domain_Mapping_DB::get_instance(); // 添加菜单页面 add_action('network_admin_menu', array($this, 'add_menu_page'), 30); // 添加AJAX处理程序 add_action('wp_ajax_dm_check_domain_health', array($this, 'ajax_check_domain_health')); // 添加计划任务钩子 add_action('dm_domain_health_check', array($this, 'scheduled_health_check')); // 初始化计划任务 $this->initialize_cron(); // 处理手动健康检查 add_action('admin_init', array($this, 'handle_manual_check')); // 处理设置保存 add_action('admin_init', array($this, 'handle_settings_save')); } /** * 初始化定时健康检查 */ private function initialize_cron() { // 注册激活时的钩子 register_activation_hook(WP_DOMAIN_MAPPING_BASENAME, array($this, 'schedule_health_check')); // 注册停用时的钩子 register_deactivation_hook(WP_DOMAIN_MAPPING_BASENAME, array($this, 'unschedule_health_check')); } /** * 添加健康监控菜单 */ public function add_menu_page() { add_submenu_page( 'settings.php', __('Domain Health', 'wp-domain-mapping'), __('Domain Health', 'wp-domain-mapping'), 'manage_network', 'domain-mapping-health', array($this, 'render_page') ); } /** * 计划健康检查任务 */ public function schedule_health_check() { if (!wp_next_scheduled('dm_domain_health_check')) { wp_schedule_event(time(), 'daily', 'dm_domain_health_check'); } } /** * 取消健康检查任务 */ public function unschedule_health_check() { $timestamp = wp_next_scheduled('dm_domain_health_check'); if ($timestamp) { wp_unschedule_event($timestamp, 'dm_domain_health_check'); } } /** * 处理手动健康检查 */ public function handle_manual_check() { if (isset($_POST['dm_manual_health_check']) && $_POST['dm_manual_health_check']) { // 验证nonce if (!isset($_POST['dm_manual_health_check_nonce']) || !wp_verify_nonce($_POST['dm_manual_health_check_nonce'], 'dm_manual_health_check')) { wp_die(__('Security check failed.', 'wp-domain-mapping')); } // 检查权限 if (!current_user_can('manage_network')) { wp_die(__('You do not have sufficient permissions to perform this action.', 'wp-domain-mapping')); } // 执行健康检查 $this->run_health_check_for_all_domains(); // 重定向回健康页面 wp_redirect(add_query_arg(array('page' => 'domain-mapping-health', 'checked' => 1), network_admin_url('settings.php'))); exit; } } /** * 处理设置保存 */ public function handle_settings_save() { if (isset($_POST['dm_health_settings']) && $_POST['dm_health_settings']) { // 验证nonce if (!isset($_POST['dm_health_settings_nonce']) || !wp_verify_nonce($_POST['dm_health_settings_nonce'], 'dm_health_settings')) { wp_die(__('Security check failed.', 'wp-domain-mapping')); } // 检查权限 if (!current_user_can('manage_network')) { wp_die(__('You do not have sufficient permissions to perform this action.', 'wp-domain-mapping')); } // 保存设置 $health_check_enabled = isset($_POST['health_check_enabled']) ? (bool) $_POST['health_check_enabled'] : false; $health_notifications_enabled = isset($_POST['health_notifications_enabled']) ? (bool) $_POST['health_notifications_enabled'] : false; $notification_email = isset($_POST['notification_email']) ? sanitize_email($_POST['notification_email']) : ''; $ssl_expiry_threshold = isset($_POST['ssl_expiry_threshold']) ? intval($_POST['ssl_expiry_threshold']) : 14; update_site_option('dm_health_check_enabled', $health_check_enabled); update_site_option('dm_health_notifications_enabled', $health_notifications_enabled); update_site_option('dm_notification_email', $notification_email); update_site_option('dm_ssl_expiry_threshold', $ssl_expiry_threshold); // 如果启用了自动检查,确保计划任务已设置 if ($health_check_enabled) { $this->schedule_health_check(); } else { $this->unschedule_health_check(); } // 重定向回健康页面 wp_redirect(add_query_arg(array('page' => 'domain-mapping-health', 'settings-updated' => 1), network_admin_url('settings.php'))); exit; } } /** * 渲染健康监控页面 */ public function render_page() { // 检查权限 if (!current_user_can('manage_network')) { wp_die(__('You do not have sufficient permissions to access this page.', 'wp-domain-mapping')); } // 获取所有域名 global $wpdb; $table = $wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_DOMAINS; $domains = $wpdb->get_results(" SELECT d.*, b.domain as original_domain, b.path FROM {$table} d JOIN {$wpdb->blogs} b ON d.blog_id = b.blog_id ORDER BY d.blog_id ASC, d.active DESC "); // 获取健康检查结果(如果有) $health_results = get_site_option('dm_domain_health_results', array()); // 渲染页面 ?>

' . __('Domain health check completed.', 'wp-domain-mapping') . '

'; } if (isset($_GET['settings-updated']) && $_GET['settings-updated']) { echo '

' . __('Settings saved.', 'wp-domain-mapping') . '

'; } ?>


domain); $health_data = isset($health_results[$domain_key]) ? $health_results[$domain_key] : null; $site_name = get_blog_option($domain->blog_id, 'blogname', __('Unknown', 'wp-domain-mapping')); ?>
domain); ?> active) : ?>
original_domain . $domain->path); ?>

check_domain_health($domain); // 保存结果 $this->save_health_check_result($domain, $result); // 返回结果 wp_send_json_success($result); } /** * 计划任务:执行所有域名健康检查 */ public function scheduled_health_check() { // 检查是否启用了自动健康检查 if (!get_site_option('dm_health_check_enabled', true)) { return; } $this->run_health_check_for_all_domains(); } /** * 对所有域名执行健康检查 */ private function run_health_check_for_all_domains() { global $wpdb; $table = $wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_DOMAINS; // 获取所有域名 $domains = $wpdb->get_col("SELECT domain FROM {$table}"); // 初始化通知信息 $issues = array(); // 检查每个域名 foreach ($domains as $domain) { $result = $this->check_domain_health($domain); $this->save_health_check_result($domain, $result); // 检查是否有问题 if ($this->has_health_issues($result)) { $issues[$domain] = $result; } } // 如果启用了通知并且有问题,发送通知 if (!empty($issues) && get_site_option('dm_health_notifications_enabled', true)) { $this->send_health_notification($issues); } return true; } /** * 检查域名健康状态 * * @param string $domain 要检查的域名 * @return array 健康检查结果 */ private function check_domain_health($domain) { $result = array( 'domain' => $domain, 'last_check' => current_time('mysql'), 'dns_status' => 'error', 'dns_message' => __('DNS check not performed', 'wp-domain-mapping'), 'resolved_ip' => '', 'ssl_valid' => false, 'ssl_expiry' => '', 'accessible' => false, 'response_code' => 0 ); // 获取服务器IP或CNAME $server_ip = get_site_option('dm_ipaddress', ''); $server_cname = get_site_option('dm_cname', ''); // 检查DNS设置 $domain_ip = gethostbyname($domain); $result['resolved_ip'] = $domain_ip; if ($domain_ip && $domain_ip !== $domain) { if ($server_ip && strpos($server_ip, $domain_ip) !== false) { $result['dns_status'] = 'success'; $result['dns_message'] = __('Domain A record is correctly pointing to server IP.', 'wp-domain-mapping'); } elseif ($server_cname && function_exists('dns_get_record')) { $dns_records = @dns_get_record($domain, DNS_CNAME); $has_valid_cname = false; if ($dns_records) { foreach ($dns_records as $record) { if (isset($record['target']) && ( $record['target'] === $server_cname || strpos($record['target'], $server_cname) !== false )) { $has_valid_cname = true; break; } } } if ($has_valid_cname) { $result['dns_status'] = 'success'; $result['dns_message'] = __('Domain CNAME record is correctly configured.', 'wp-domain-mapping'); } else { $result['dns_message'] = __('Domain is not pointing to the correct server.', 'wp-domain-mapping'); } } else { $result['dns_message'] = __('Cannot verify DNS configuration.', 'wp-domain-mapping'); } } else { $result['dns_message'] = __('Domain does not resolve to an IP address.', 'wp-domain-mapping'); } // 检查网站可访问性和SSL $response = $this->test_domain_connection($domain); if ($response) { $result['accessible'] = $response['accessible']; $result['response_code'] = $response['response_code']; $result['ssl_valid'] = $response['ssl_valid']; $result['ssl_expiry'] = $response['ssl_expiry']; } return $result; } /** * 测试域名连接 * * @param string $domain 域名 * @return array|false 连接测试结果 */ private function test_domain_connection($domain) { if (!function_exists('curl_init')) { return false; } $result = array( 'accessible' => false, 'response_code' => 0, 'ssl_valid' => false, 'ssl_expiry' => '' ); // 测试HTTPS连接 $ch = curl_init('https://' . $domain); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $response = curl_exec($ch); $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $result['response_code'] = $response_code; if ($response !== false && $response_code > 0) { $result['accessible'] = ($response_code >= 200 && $response_code < 400); $result['ssl_valid'] = ($response !== false); // 获取SSL证书信息 $ssl_info = curl_getinfo($ch, CURLINFO_CERTINFO); if (!empty($ssl_info) && isset($ssl_info[0]['Expire date'])) { $result['ssl_expiry'] = $ssl_info[0]['Expire date']; } } curl_close($ch); // 如果HTTPS失败,尝试HTTP if (!$result['accessible']) { $ch = curl_init('http://' . $domain); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); $response = curl_exec($ch); $response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($response !== false && $response_code > 0) { $result['accessible'] = ($response_code >= 200 && $response_code < 400); $result['response_code'] = $response_code; } curl_close($ch); } return $result; } /** * 保存健康检查结果 * * @param string $domain 域名 * @param array $result 健康检查结果 */ private function save_health_check_result($domain, $result) { $health_results = get_site_option('dm_domain_health_results', array()); $domain_key = md5($domain); $health_results[$domain_key] = $result; update_site_option('dm_domain_health_results', $health_results); } /** * 检查结果是否有健康问题 * * @param array $result 健康检查结果 * @return bool 是否有问题 */ private function has_health_issues($result) { // 检查DNS问题 if ($result['dns_status'] !== 'success') { return true; } // 检查SSL问题 if (!$result['ssl_valid']) { return true; } // 检查SSL即将到期 if (!empty($result['ssl_expiry'])) { $expiry_date = strtotime($result['ssl_expiry']); $threshold = get_site_option('dm_ssl_expiry_threshold', 14); $threshold_date = strtotime('+' . $threshold . ' days'); if ($expiry_date <= $threshold_date) { return true; } } // 检查可访问性问题 if (!$result['accessible']) { return true; } return false; } /** * 发送健康问题通知 * * @param array $issues 有问题的域名及其健康检查结果 */ private function send_health_notification($issues) { $notification_email = get_site_option('dm_notification_email', get_option('admin_email')); if (empty($notification_email)) { return; } $site_name = get_bloginfo('name'); $subject = sprintf(__('[%s] Domain Mapping Health Alert', 'wp-domain-mapping'), $site_name); // 构建邮件内容 $message = sprintf(__('Domain health issues were detected on %s.', 'wp-domain-mapping'), $site_name) . "\n\n"; $message .= __('The following domains have issues:', 'wp-domain-mapping') . "\n\n"; foreach ($issues as $domain => $result) { $message .= sprintf(__('Domain: %s', 'wp-domain-mapping'), $domain) . "\n"; // 添加DNS状态 if ($result['dns_status'] !== 'success') { $message .= " - " . sprintf(__('DNS Issue: %s', 'wp-domain-mapping'), $result['dns_message']) . "\n"; } // 添加SSL状态 if (!$result['ssl_valid']) { $message .= " - " . __('SSL Certificate is invalid or missing.', 'wp-domain-mapping') . "\n"; } elseif (!empty($result['ssl_expiry'])) { $expiry_date = strtotime($result['ssl_expiry']); $threshold = get_site_option('dm_ssl_expiry_threshold', 14); $threshold_date = strtotime('+' . $threshold . ' days'); if ($expiry_date <= $threshold_date) { $message .= " - " . sprintf( __('SSL Certificate expires on %s (within %d days).', 'wp-domain-mapping'), date('Y-m-d', $expiry_date), $threshold ) . "\n"; } } // 添加可访问性状态 if (!$result['accessible']) { $message .= " - " . __('Site is not accessible.', 'wp-domain-mapping') . "\n"; if ($result['response_code'] > 0) { $message .= " " . sprintf(__('HTTP Response Code: %d', 'wp-domain-mapping'), $result['response_code']) . "\n"; } } $message .= "\n"; } // 添加解决方案链接 $message .= sprintf( __('To view and manage these issues, please visit: %s', 'wp-domain-mapping'), network_admin_url('settings.php?page=domain-mapping-health') ) . "\n"; // 发送邮件 wp_mail($notification_email, $subject, $message); } }