prefix . 'friend_links'; // 检查表是否存在 if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { wp_die('友情链接表不存在,请先添加一些链接。'); } $links = $wpdb->get_results("SELECT * FROM $table_name ORDER BY sort_order ASC"); // 检查是否有数据 if (empty($links)) { wp_die('没有找到任何链接数据,请先添加一些链接。'); } // 清除所有输出缓冲 while (ob_get_level()) { ob_end_clean(); } header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=friend-links-export-' . date('Y-m-d') . '.csv'); header('Pragma: no-cache'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Content-Transfer-Encoding: binary'); $output = fopen('php://output', 'w'); // 添加BOM头解决中文乱码 fwrite($output, chr(0xEF).chr(0xBB).chr(0xBF)); // 写入四列标题 fputcsv($output, array( '网站名称', '网站URL', '图标URL', '链接描述' )); foreach ($links as $link) { // 对每列数据应用极端清理 fputcsv($output, array( flm_sanitize_export_text($link->name), flm_sanitize_export_url($link->url), flm_sanitize_export_url($link->icon), flm_sanitize_export_text($link->description) )); } fclose($output); exit; } } // 自动获取favicon function flm_get_favicon($url) { $domain = parse_url($url, PHP_URL_HOST); if ($domain) { $domain = preg_replace('/^www\./', '', $domain); return 'https://favicon.im/' . urlencode($domain); } return ''; } // 极端严格的URL清理(用于导出) function flm_sanitize_export_url($url) { if (empty($url)) return ''; // 先解码HTML实体 $url = html_entity_decode($url); // 移除所有HTML标签和特殊字符 $url = strip_tags($url); $url = str_replace(array("\r", "\n", "\t", "\\", "'", '"', " ", "<", ">"), '', $url); // 使用正则提取纯URL if (preg_match('/(https?:\/\/[^\s\"\'<>]+)/i', $url, $matches)) { $url = $matches[1]; } // 最终过滤和验证 $url = filter_var($url, FILTER_SANITIZE_URL); if (!preg_match('/^https?:\/\//i', $url)) { $url = 'http://' . ltrim($url, '/'); } return rtrim($url, '/'); } // 极端严格的文本清理(用于导出) function flm_sanitize_export_text($text) { if (empty($text)) return ''; // 彻底移除所有HTML/JavaScript代码 $text = html_entity_decode($text); $text = strip_tags($text); $text = str_replace(array("\r", "\n", "\t", "\\", "'", '"', "<", ">"), '', $text); return sanitize_text_field($text); } // 管理页面内容 function flm_admin_page() { global $wpdb; $table_name = $wpdb->prefix . 'friend_links'; // 显示提示信息 echo '

💡 提示:卸载插件时会删除数据,禁用插件不会丢失数据。

'; // 显示数据库修复结果 if (isset($_GET['flm_fix_success'])) { echo '

✅ 数据库修复成功!description字段已添加,现在可以正常保存链接信息了。

'; } elseif (isset($_GET['flm_fix_error'])) { echo '

❌ 数据库修复失败,请检查数据库权限。

'; } elseif (isset($_GET['flm_fix_exists'])) { echo '

ℹ️ 数据库表结构正常,无需修复。

'; } // 数据库修复按钮 echo '

⚠️ 数据库修复:点击修复数据库表结构(如果保存功能不工作)

'; // 处理表单提交 if (isset($_POST['flm_action'])) { check_admin_referer('flm_nonce'); switch ($_POST['flm_action']) { case 'add_link': if (!empty($_POST['name']) && !empty($_POST['url'])) { $name = sanitize_text_field($_POST['name']); $url = esc_url_raw($_POST['url']); // 验证URL格式 if (!filter_var($url, FILTER_VALIDATE_URL)) { echo '

请输入有效的URL地址!

'; break; } $auto_get_icon = isset($_POST['auto_get_icon']) ? true : false; $icon = ''; if ($auto_get_icon) { $icon = flm_get_favicon($url); } elseif (!empty($_POST['icon'])) { $icon = esc_url_raw($_POST['icon']); } $description = !empty($_POST['description']) ? sanitize_textarea_field($_POST['description']) : ''; $existing = $wpdb->get_row($wpdb->prepare( "SELECT id FROM $table_name WHERE url = %s", $url )); if (!$existing) { // 获取当前最大的sort_order值 $max_sort_order = $wpdb->get_var("SELECT MAX(sort_order) FROM $table_name"); $new_sort_order = $max_sort_order ? intval($max_sort_order) + 1 : 0; $wpdb->insert($table_name, array( 'name' => $name, 'url' => $url, 'icon' => $icon, 'description' => $description, 'sort_order' => $new_sort_order )); echo '

链接添加成功!

'; } else { echo '

该URL的链接已存在!

'; } } break; case 'update_links': if (!empty($_POST['link_ids'])) { $update_errors = 0; $update_count = 0; // 直接使用数组格式 $link_ids = array_values($_POST['link_ids']); $link_names = isset($_POST['link_names']) ? array_values($_POST['link_names']) : array(); $link_urls = isset($_POST['link_urls']) ? array_values($_POST['link_urls']) : array(); $link_icons = isset($_POST['link_icons']) ? array_values($_POST['link_icons']) : array(); $link_descriptions = isset($_POST['link_descriptions']) ? array_values($_POST['link_descriptions']) : array(); foreach ($link_ids as $index => $id) { // 确保数组索引存在 if (!isset($link_names[$index]) || !isset($link_urls[$index])) { $update_errors++; continue; } $name = sanitize_text_field($link_names[$index]); $url = esc_url_raw($link_urls[$index]); // 验证URL格式 if (!filter_var($url, FILTER_VALIDATE_URL)) { $update_errors++; continue; } $icon = isset($link_icons[$index]) ? esc_url_raw($link_icons[$index]) : ''; $description = isset($link_descriptions[$index]) ? sanitize_textarea_field($link_descriptions[$index]) : ''; $update_data = array( 'name' => $name, 'url' => $url, 'icon' => $icon, 'description' => $description, 'sort_order' => $index ); $result = $wpdb->update($table_name, $update_data, array('id' => intval($id))); if ($result === false) { echo '

数据库错误:ID ' . $id . ' 更新失败: ' . $wpdb->last_error . '

'; $update_errors++; } else { $update_count++; } } if ($update_errors > 0) { echo '

更新完成!成功更新 ' . $update_count . ' 条链接,跳过 ' . $update_errors . ' 条记录

'; } else { echo '

链接更新成功!共更新 ' . $update_count . ' 条记录

'; } } break; case 'delete_link': if (!empty($_POST['link_id'])) { $wpdb->delete($table_name, array('id' => intval($_POST['link_id']))); echo '

链接删除成功!

'; } break; case 'export_links': // 使用WordPress的admin_url进行重定向导出 $export_url = admin_url('admin.php?page=friend-links-manager&action=export&nonce=' . wp_create_nonce('flm_export_nonce')); wp_redirect($export_url); exit; break; case 'save_settings': $desktop_columns = isset($_POST['desktop_columns']) ? intval($_POST['desktop_columns']) : 3; $random_display = isset($_POST['random_display']) ? 1 : 0; $show_descriptions = isset($_POST['show_descriptions']) ? 1 : 0; update_option('flm_desktop_columns', $desktop_columns); update_option('flm_random_display', $random_display); update_option('flm_show_descriptions', $show_descriptions); echo '

设置保存成功!

'; break; case 'import_links': if (!empty($_FILES['import_file']['tmp_name'])) { $file = $_FILES['import_file']['tmp_name']; $handle = fopen($file, 'r'); $import_count = 0; $update_count = 0; $error_count = 0; // 跳过标题行 fgetcsv($handle); $sort_order = 0; while (($data = fgetcsv($handle)) !== false) { if (count($data) < 2 || empty($data[0]) || empty($data[1])) { $error_count++; continue; } $name = sanitize_text_field($data[0]); $url = esc_url_raw($data[1]); $icon = isset($data[2]) ? esc_url_raw($data[2]) : flm_get_favicon($data[1]); $description = isset($data[3]) ? sanitize_textarea_field($data[3]) : ''; if (!filter_var($url, FILTER_VALIDATE_URL)) { $error_count++; continue; } if (!empty($name) && !empty($url)) { $existing = $wpdb->get_row($wpdb->prepare( "SELECT id FROM $table_name WHERE url = %s", $url )); if ($existing) { $wpdb->update($table_name, array( 'name' => $name, 'icon' => $icon, 'description' => $description ), array('id' => $existing->id)); $update_count++; } else { $wpdb->insert($table_name, array( 'name' => $name, 'url' => $url, 'icon' => $icon, 'description' => $description, 'sort_order' => $sort_order )); $import_count++; } $sort_order++; } } fclose($handle); $message = sprintf( '导入完成!新增 %d 条链接,更新 %d 条已有链接', $import_count, $update_count ); if ($error_count > 0) { $message .= sprintf(',跳过 %d 条格式不正确的记录', $error_count); } echo '

' . $message . '

'; } break; case 'save_settings': $desktop_columns = isset($_POST['desktop_columns']) ? intval($_POST['desktop_columns']) : 3; $random_display = isset($_POST['random_display']) ? 1 : 0; $show_descriptions = isset($_POST['show_descriptions']) ? 1 : 0; update_option('flm_desktop_columns', $desktop_columns); update_option('flm_random_display', $random_display); update_option('flm_show_descriptions', $show_descriptions); echo '

设置保存成功!

'; break; } } // 获取所有链接 $links = $wpdb->get_results("SELECT * FROM $table_name ORDER BY sort_order ASC"); ?>

友情链接管理

添加新链接

prefix . 'friend_links'; $wpdb->delete($table_name, array('id' => intval($_POST['link_id']))); wp_send_json_success(); } wp_send_json_error(); } // 处理AJAX排序更新请求 add_action('wp_ajax_flm_update_sort_order', 'flm_ajax_update_sort_order'); function flm_ajax_update_sort_order() { check_ajax_referer('flm_nonce', 'nonce'); if (!empty($_POST['link_ids']) && is_array($_POST['link_ids'])) { global $wpdb; $table_name = $wpdb->prefix . 'friend_links'; foreach ($_POST['link_ids'] as $index => $link_id) { $link_id = intval($link_id); if ($link_id > 0) { $wpdb->update($table_name, array('sort_order' => $index), array('id' => $link_id), array('%d'), array('%d') ); } } wp_send_json_success(); } wp_send_json_error(); } // 处理AJAX批量删除请求 add_action('wp_ajax_flm_batch_delete_links', 'flm_ajax_batch_delete_links'); function flm_ajax_batch_delete_links() { check_ajax_referer('flm_nonce', 'nonce'); if (!empty($_POST['link_ids']) && is_array($_POST['link_ids'])) { global $wpdb; $table_name = $wpdb->prefix . 'friend_links'; $deleted_count = 0; $error_count = 0; foreach ($_POST['link_ids'] as $link_id) { $link_id = intval($link_id); if ($link_id > 0) { $result = $wpdb->delete($table_name, array('id' => $link_id), array('%d')); if ($result !== false) { $deleted_count++; } else { $error_count++; } } } if ($deleted_count > 0) { wp_send_json_success(array( 'deleted_count' => $deleted_count, 'error_count' => $error_count )); } else { wp_send_json_error('没有链接被删除'); } } wp_send_json_error('无效的请求参数'); }