功能强大且用户友好的 WooCommerce 产品比较工具。
<?php /** * Plugin Name: BDFG WooCommerce Compare * Plugin URI: https://beiduofengou.net/2024/02/15/bdfg-woocommerce-compare/ * Description: A professional and user-friendly WooCommerce product comparison tool developed by beiduofengou * Version: 2.3.1 * Author: beiduofengou * Author URI: https://beiduofengou.net * Text Domain: bdfg-woo-compare * Domain Path: /languages * Requires at least: 5.8 * Requires PHP: 7.4 * WC requires at least: 5.0 * WC tested up to: 8.2 * License: GPL v2 or later * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @link https://beiduofengou.net * @since 1.0.0 */ if (!defined('ABSPATH')) { exit('Direct access not allowed.'); } if (!class_exists('BDFG_Woo_Compare')) { class BDFG_Woo_Compare { /** * 插件实例 * * @var BDFG_Woo_Compare */ private static $instance = null; /** * 插件版本 * * @var string */ private $version = '2.3.1'; /** * 系统要求 * * @var array */ private $requirements = array( 'php' => '7.4', 'wordpress' => '5.8', 'woocommerce' => '5.0' ); /** * 获取插件实例 * * @return BDFG_Woo_Compare */ public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * 构造函数 */ private function __construct() { $this->define_constants(); $this->init_hooks(); if ($this->check_requirements()) { $this->includes(); $this->init(); // 添加插件设置链接 add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'add_plugin_links')); // 添加插件更新检查 add_action('admin_init', array($this, 'check_version')); } } /** * 定义常量 */ private function define_constants() { // 版本信息 define('BDFG_COMPARE_VERSION', $this->version); define('BDFG_COMPARE_DB_VERSION', '1.0.3'); // 路径信息 define('BDFG_COMPARE_FILE', __FILE__); define('BDFG_COMPARE_PATH', plugin_dir_path(__FILE__)); define('BDFG_COMPARE_URL', plugin_dir_url(__FILE__)); define('BDFG_COMPARE_ASSETS_URL', BDFG_COMPARE_URL . 'assets/'); define('BDFG_COMPARE_TEMPLATES_PATH', BDFG_COMPARE_PATH . 'templates/'); // 其他配置 define('BDFG_COMPARE_MAX_PRODUCTS', 6); define('BDFG_COMPARE_COOKIE_NAME', 'bdfg_compare_list'); define('BDFG_COMPARE_SESSION_KEY', 'bdfg_compare_session'); } /** * 初始化钩子 */ private function init_hooks() { // 加载文本域 add_action('init', array($this, 'load_plugin_textdomain')); // 注册激活和停用钩子 register_activation_hook(__FILE__, array($this, 'activate')); register_deactivation_hook(__FILE__, array($this, 'deactivate')); // 添加定时清理任务 add_action('bdfg_daily_cleanup', array($this, 'cleanup_old_data')); } /** * 检查系统要求 * * @return bool */ private function check_requirements() { // PHP版本检查 if (version_compare(PHP_VERSION, $this->requirements['php'], '<')) { add_action('admin_notices', array($this, 'php_version_notice')); return false; } // WordPress版本检查 if (version_compare(get_bloginfo('version'), $this->requirements['wordpress'], '<')) { add_action('admin_notices', array($this, 'wordpress_version_notice')); return false; } // WooCommerce依赖检查 if (!class_exists('WooCommerce')) { add_action('admin_notices', array($this, 'woocommerce_missing_notice')); return false; } if (defined('WC_VERSION') && version_compare(WC_VERSION, $this->requirements['woocommerce'], '<')) { add_action('admin_notices', array($this, 'woocommerce_version_notice')); return false; } return true; } /** * 包含必要的文件 */ private function includes() { // 工具类 require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-utils.php'; // 核心功能 require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-core-functions.php'; require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-template-loader.php'; require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-ajax-handler.php'; // Session处理 require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-session.php'; // 前端功能 if (!is_admin() || wp_doing_ajax()) { require_once BDFG_COMPARE_PATH . 'public/class-bdfg-public.php'; } // 管理员功能 if (is_admin()) { require_once BDFG_COMPARE_PATH . 'admin/class-bdfg-admin.php'; require_once BDFG_COMPARE_PATH . 'admin/class-bdfg-settings.php'; } // 扩展功能 require_once BDFG_COMPARE_PATH . 'includes/class-bdfg-compare-extended.php'; } /** * 初始化插件 */ private function init() { // 初始化会话 BDFG_Session::init(); // 添加比较按钮 $button_position = get_option('bdfg_compare_button_position', 'woocommerce_after_add_to_cart_button'); add_action($button_position, array($this, 'add_compare_button'), 20); // 注册小工具 add_action('widgets_init', array($this, 'register_widgets')); // 注册短代码 add_shortcode('bdfg_compare', array($this, 'compare_shortcode')); } /** * 添加设置链接 */ public function add_plugin_links($links) { $plugin_links = array( '<a href="' . admin_url('admin.php?page=bdfg-compare-settings') . '">' . __('Settings', 'bdfg-woo-compare') . '</a>', '<a href="https://beiduofengou.net/docs/bdfg-woo-compare" target="_blank">' . __('Documentation', 'bdfg-woo-compare') . '</a>' ); return array_merge($plugin_links, $links); } /** * 加载语言文件 */ public function load_plugin_textdomain() { load_plugin_textdomain( 'bdfg-woo-compare', false, dirname(plugin_basename(__FILE__)) . '/languages/' ); } /** * 添加比较按钮 */ public function add_compare_button() { global $product; if (!$product) return; $button_text = get_option('bdfg_compare_button_text', __('Compare', 'bdfg-woo-compare')); $button_class = get_option('bdfg_compare_button_class', 'button bdfg-compare-btn'); echo sprintf( '<button type="button" class="%s" data-product-id="%d" data-nonce="%s">%s</button>', esc_attr($button_class), esc_attr($product->get_id()), wp_create_nonce('bdfg_compare_nonce'), esc_html($button_text) ); } /** * 比较短代码 */ public function compare_shortcode($atts) { $defaults = array( 'products' => '', 'fields' => '', 'show_remove' => 'yes' ); $atts = shortcode_atts($defaults, $atts, 'bdfg_compare'); ob_start(); include BDFG_COMPARE_TEMPLATES_PATH . 'compare-table.php'; return ob_get_clean(); } /** * 插件激活 */ public static function activate() { if (!current_user_can('activate_plugins')) { return; } // 创建数据表 self::create_tables(); // 设置默认选项 self::set_default_options(); // 添加定时任务 if (!wp_next_scheduled('bdfg_daily_cleanup')) { wp_schedule_event(time(), 'daily', 'bdfg_daily_cleanup'); } // 清理缓存 wp_cache_flush(); } /** * 创建数据表 */ private static function create_tables() { global $wpdb; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}bdfg_compare_lists ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL DEFAULT 0, name varchar(255) NOT NULL, products longtext NOT NULL, created datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, modified datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); } /** * 设置默认选项 */ private static function set_default_options() { $default_options = array( 'bdfg_compare_page_id' => 0, 'bdfg_compare_button_position' => 'woocommerce_after_add_to_cart_button', 'bdfg_compare_button_text' => __('Compare', 'bdfg-woo-compare'), 'bdfg_compare_fields' => array('image', 'title', 'price', 'description', 'sku', 'stock', 'weight', 'dimensions'), 'bdfg_compare_max_products' => 4, 'bdfg_compare_enable_share' => 'yes', 'bdfg_compare_enable_pdf' => 'yes', 'bdfg_compare_enable_email' => 'yes' ); foreach ($default_options as $option => $value) { if (get_option($option) === false) { update_option($option, $value); } } } /** * 插件停用 */ public static function deactivate() { if (!current_user_can('activate_plugins')) { return; } // 清理定时任务 wp_clear_scheduled_hook('bdfg_daily_cleanup'); // 清理临时数据 self::cleanup_temp_data(); } /** * 清理临时数据 */ private static function cleanup_temp_data() { global $wpdb; // 清理过期的会话数据 $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_bdfg_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_bdfg_%'"); // 清理缓存 wp_cache_flush(); } /** * 系统要求通知 */ public function php_version_notice() { $message = sprintf( __('BDFG WooCommerce Compare requires PHP version %s or higher. You are running version %s', 'bdfg-woo-compare'), $this->requirements['php'], PHP_VERSION ); echo '<div class="error"><p>' . esc_html($message) . '</p></div>'; } public function wordpress_version_notice() { $message = sprintf( __('BDFG WooCommerce Compare requires WordPress version %s or higher.', 'bdfg-woo-compare'), $this->requirements['wordpress'] ); echo '<div class="error"><p>' . esc_html($message) . '</p></div>'; } public function woocommerce_missing_notice() { $message = __('BDFG WooCommerce Compare requires WooCommerce to be installed and activated.', 'bdfg-woo-compare'); echo '<div class="error"><p>' . esc_html($message) . '</p></div>'; } public function woocommerce_version_notice() { $message = sprintf( __('BDFG WooCommerce Compare requires WooCommerce version %s or higher.', 'bdfg-woo-compare'), $this->requirements['woocommerce'] ); echo '<div class="error"><p>' . esc_html($message) . '</p></div>'; } } // 初始化插件 add_action('plugins_loaded', array('BDFG_Woo_Compare', 'get_instance')); // 注册激活和停用钩子 register_activation_hook(__FILE__, array('BDFG_Woo_Compare', 'activate')); register_deactivation_hook(__FILE__, array('BDFG_Woo_Compare', 'deactivate')); }
includes/class-bdfg-core-functions.php
相关文章: WordPress 地图定位插件
<?php /** * BDFG WooCommerce Compare Core Functions * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @version 2.3.1 * @since 1.0.0 * @last_modified 2025-02-15 17:41:43 * @developer beiduofengou */ if (!defined('ABSPATH')) { exit('Direct access not allowed.'); } class BDFG_Core_Functions { /** * 单例实例 * * @var BDFG_Core_Functions */ private static $instance = null; /** * 缓存相关变量 */ private $compare_table_cache = array(); private $product_data_cache = array(); private $cache_expiry = 3600; // 缓存过期时间(秒) /** * 获取实例 */ public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * 构造函数 */ private function __construct() { // 初始化缓存 add_action('init', array($this, 'init_cache')); // 监听产品更新事件 $this->init_product_hooks(); // 注册AJAX处理器 $this->register_ajax_handlers(); } /** * 初始化产品相关钩子 */ private function init_product_hooks() { // 产品数据更新时清理缓存 add_action('woocommerce_update_product', array($this, 'clear_product_cache')); add_action('woocommerce_delete_product', array($this, 'clear_product_cache')); add_action('woocommerce_trash_product', array($this, 'clear_product_cache')); // 产品库存变化时更新缓存 add_action('woocommerce_product_set_stock', array($this, 'clear_product_cache')); add_action('woocommerce_variation_set_stock', array($this, 'clear_product_cache')); } /** * 注册AJAX处理器 */ private function register_ajax_handlers() { add_action('wp_ajax_bdfg_get_compare_data', array($this, 'ajax_get_compare_data')); add_action('wp_ajax_nopriv_bdfg_get_compare_data', array($this, 'ajax_get_compare_data')); add_action('wp_ajax_bdfg_update_field_visibility', array($this, 'ajax_update_field_visibility')); } /** * 初始化缓存 */ public function init_cache() { $this->compare_table_cache = get_transient('bdfg_compare_table_cache'); if (false === $this->compare_table_cache) { $this->compare_table_cache = array(); } } /** * 获取比较字段 * * @return array 比较字段配置 */ public function get_compare_fields() { $default_fields = array( 'image' => array( 'label' => __('Product Image', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_image'), 'priority' => 10, 'visible' => true ), 'title' => array( 'label' => __('Product Name', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_title'), 'priority' => 20, 'visible' => true ), 'price' => array( 'label' => __('Price', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_price'), 'priority' => 30, 'visible' => true ), 'description' => array( 'label' => __('Description', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_description'), 'priority' => 40, 'visible' => true ), 'sku' => array( 'label' => __('SKU', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_sku'), 'priority' => 50, 'visible' => true ), 'stock' => array( 'label' => __('Stock Status', 'bdfg-woo-compare'), 'callback' => array($this, 'get_stock_status'), 'priority' => 60, 'visible' => true ), 'weight' => array( 'label' => __('Weight', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_weight'), 'priority' => 70, 'visible' => true ), 'dimensions' => array( 'label' => __('Dimensions', 'bdfg-woo-compare'), 'callback' => array($this, 'get_product_dimensions'), 'priority' => 80, 'visible' => true ) ); return apply_filters('bdfg_compare_fields', $default_fields); } /** * 获取产品数据 * * @param int $product_id * @return array|bool 产品数据或false */ public function get_product_data($product_id) { // 检查缓存 if (isset($this->product_data_cache[$product_id])) { return $this->product_data_cache[$product_id]; } $cached_data = get_transient('bdfg_product_' . $product_id); if (false !== $cached_data) { $this->product_data_cache[$product_id] = $cached_data; return $cached_data; } $product = wc_get_product($product_id); if (!$product) { return false; } // 收集产品数据 $data = array( 'id' => $product_id, 'title' => $product->get_name(), 'url' => get_permalink($product_id), 'image' => $this->get_product_image($product), 'price' => array( 'regular' => $product->get_regular_price(), 'sale' => $product->get_sale_price(), 'html' => $product->get_price_html() ), 'sku' => $product->get_sku(), 'stock' => array( 'status' => $product->get_stock_status(), 'quantity' => $product->get_stock_quantity(), 'html' => $this->get_stock_status($product) ), 'description' => array( 'short' => $product->get_short_description(), 'full' => $product->get_description() ), 'dimensions' => array( 'length' => $product->get_length(), 'width' => $product->get_width(), 'height' => $product->get_height(), 'formatted' => $this->get_product_dimensions($product) ), 'weight' => array( 'value' => $product->get_weight(), 'formatted' => $this->get_product_weight($product) ), 'attributes' => $this->get_product_attributes($product), 'categories' => $this->get_product_categories($product), 'tags' => $this->get_product_tags($product), 'meta' => array( 'updated' => current_time('mysql'), 'currency' => get_woocommerce_currency() ) ); // 缓存数据 set_transient('bdfg_product_' . $product_id, $data, $this->cache_expiry); $this->product_data_cache[$product_id] = $data; return $data; } /** * 获取产品图片 */ public function get_product_image($product) { $image_id = $product->get_image_id(); if (!$image_id) { return wc_placeholder_img(); } return wp_get_attachment_image( $image_id, 'woocommerce_thumbnail', false, array( 'class' => 'bdfg-compare-product-image', 'alt' => $product->get_name() ) ); } /** * 获取库存状态 */ public function get_stock_status($product) { $availability = $product->get_availability(); $stock_html = '<div class="bdfg-stock-status stock ' . esc_attr($availability['class']) . '">'; $stock_html .= esc_html($availability['availability']); if ($product->managing_stock()) { $stock_html .= ' (' . $product->get_stock_quantity() . ')'; } $stock_html .= '</div>'; return $stock_html; } /** * 获取产品尺寸 */ public function get_product_dimensions($product) { if (!$product->has_dimensions()) { return '-'; } return wc_format_dimensions($product->get_dimensions(false)); } /** * 获取产品重量 */ public function get_product_weight($product) { $weight = $product->get_weight(); if (!$weight) { return '-'; } return wc_format_weight($weight); } /** * 获取产品属性 */ private function get_product_attributes($product) { $attributes = array(); if ($product->get_type() == 'variation') { $variation_attributes = $product->get_variation_attributes(); foreach ($variation_attributes as $attribute_name => $attribute_value) { $attributes[] = array( 'name' => wc_attribute_label(str_replace('attribute_', '', $attribute_name)), 'value' => $attribute_value ); } } else { foreach ($product->get_attributes() as $attribute) { if ($attribute->is_taxonomy()) { $terms = wp_get_post_terms($product->get_id(), $attribute->get_name(), 'all'); $attribute_value = array(); foreach ($terms as $term) { $attribute_value[] = $term->name; } $attributes[] = array( 'name' => wc_attribute_label($attribute->get_name()), 'value' => implode(', ', $attribute_value) ); } else { $attributes[] = array( 'name' => $attribute->get_name(), 'value' => $attribute->get_options() ); } } } return $attributes; } /** * 获取产品分类 */ private function get_product_categories($product) { $categories = array(); $terms = get_the_terms($product->get_id(), 'product_cat'); if ($terms && !is_wp_error($terms)) { foreach ($terms as $term) { $categories[] = array( 'id' => $term->term_id, 'name' => $term->name, 'slug' => $term->slug, 'url' => get_term_link($term) ); } } return $categories; } /** * 清理产品缓存 */ public function clear_product_cache($product_id) { delete_transient('bdfg_product_' . $product_id); unset($this->product_data_cache[$product_id]); $this->clear_table_cache(); } /** * AJAX处理器 - 获取比较数据 */ public function ajax_get_compare_data() { check_ajax_referer('bdfg_compare_nonce', 'nonce'); $product_ids = isset($_POST['products']) ? array_map('absint', $_POST['products']) : array(); if (empty($product_ids)) { wp_send_json_error(array( 'message' => __('No products selected', 'bdfg-woo-compare') )); } $data = array(); foreach ($product_ids as $product_id) { $product_data = $this->get_product_data($product_id); if ($product_data) { $data[] = $product_data; } } wp_send_json_success(array( 'products' => $data, 'fields' => $this->get_compare_fields() )); } /** * 清理所有缓存 */ public function clear_all_cache() { global $wpdb; // 清理产品缓存 $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_bdfg_product_%'"); $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_bdfg_product_%'"); // 清理表格缓存 delete_transient('bdfg_compare_table_cache'); // 重置内存缓存 $this->product_data_cache = array(); $this->compare_table_cache = array(); } }
includes/class-bdfg-compare-extended.php
<?php /** * BDFG WooCommerce Compare Extended Features * 高级比较功能扩展 * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @since 2.3.1 */ if (!defined('ABSPATH')) { exit('Direct access not allowed.'); } class BDFG_Compare_Extended { private static $instance = null; private $share_expiry = 7; // 分享链接有效期(天) private $watch_list_limit = 20; // 每个用户可关注的最大商品数 /** * 获取单例实例 */ public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * 构造函数 - 初始化钩子和过滤器 */ private function __construct() { // 分享功能 add_action('wp_ajax_bdfg_share_compare', array($this, 'generate_share_link')); add_action('wp_ajax_nopriv_bdfg_share_compare', array($this, 'generate_share_link')); add_action('template_redirect', array($this, 'handle_shared_compare')); // 保存功能 add_action('wp_ajax_bdfg_save_compare', array($this, 'save_compare_list')); add_action('wp_ajax_bdfg_load_saved_compare', array($this, 'load_saved_compare')); // 商品监控 add_action('woocommerce_product_set_regular_price', array($this, 'check_price_change'), 10, 2); add_action('woocommerce_product_set_sale_price', array($this, 'check_price_change'), 10, 2); add_action('wp_ajax_bdfg_watch_product', array($this, 'toggle_product_watch')); // 高亮差异 add_filter('bdfg_compare_field_value', array($this, 'highlight_differences'), 10, 3); // 自定义比较属性 add_filter('bdfg_compare_fields', array($this, 'add_custom_attributes')); // 定期清理过期数据 add_action('bdfg_daily_cleanup', array($this, 'cleanup_expired_data')); } /** * 生成分享链接 */ public function generate_share_link() { check_ajax_referer('bdfg_share_nonce', 'nonce'); // 获取比较列表 $session = BDFG_Compare_Session::get_instance(); $products = $session->get_products(); if (empty($products)) { wp_send_json_error(array( 'message' => __('No products to share', 'bdfg-woo-compare') )); } // 生成唯一分享ID $share_id = wp_generate_uuid4(); $share_data = array( 'products' => $products, 'created' => current_time('mysql'), 'expires' => date('Y-m-d H:i:s', strtotime("+{$this->share_expiry} days")) ); // 保存分享数据 set_transient("bdfg_share_{$share_id}", $share_data, $this->share_expiry * DAY_IN_SECONDS); // 生成分享URL $share_url = add_query_arg(array( 'bdfg-compare' => $share_id, 'utm_source' => 'share', 'utm_medium' => 'compare', 'utm_campaign' => 'product_comparison' ), home_url()); wp_send_json_success(array( 'share_url' => $share_url, 'expires' => human_time_diff(strtotime($share_data['expires'])) )); } /** * 处理分享链接访问 */ public function handle_shared_compare() { $share_id = isset($_GET['bdfg-compare']) ? sanitize_text_field($_GET['bdfg-compare']) : ''; if (!$share_id) { return; } // 获取分享数据 $share_data = get_transient("bdfg_share_{$share_id}"); if (!$share_data) { wp_die(__('This comparison link has expired or is invalid.', 'bdfg-woo-compare'), '', array('back_link' => true)); } // 加载比较页面 $session = BDFG_Compare_Session::get_instance(); $session->set_products($share_data['products']); wp_redirect(BDFG_Compare_Public::get_compare_page_url()); exit; } /** * 保存比较列表 */ public function save_compare_list() { if (!is_user_logged_in()) { wp_send_json_error(array( 'message' => __('Please login to save comparisons', 'bdfg-woo-compare') )); } check_ajax_referer('bdfg_save_nonce', 'nonce'); $name = isset($_POST['name']) ? sanitize_text_field($_POST['name']) : ''; if (empty($name)) { $name = sprintf(__('Comparison #%s', 'bdfg-woo-compare'), uniqid()); } // 获取当前比较列表 $session = BDFG_Compare_Session::get_instance(); $products = $session->get_products(); if (empty($products)) { wp_send_json_error(array( 'message' => __('No products to save', 'bdfg-woo-compare') )); } // 保存比较列表 $user_id = get_current_user_id(); $saved_lists = get_user_meta($user_id, 'bdfg_saved_comparisons', true); if (!is_array($saved_lists)) { $saved_lists = array(); } $saved_lists[] = array( 'id' => uniqid('bdfg_'), 'name' => $name, 'products' => $products, 'date' => current_time('mysql'), 'modified' => current_time('mysql') ); update_user_meta($user_id, 'bdfg_saved_comparisons', $saved_lists); wp_send_json_success(array( 'message' => __('Comparison saved successfully', 'bdfg-woo-compare'), 'list' => end($saved_lists) )); } /** * 监控商品价格变化 */ public function check_price_change($product_id, $price) { $old_price = get_post_meta($product_id, '_price', true); if ($old_price != $price) { $watchers = get_post_meta($product_id, 'bdfg_price_watchers', true); if (!empty($watchers)) { $this->notify_price_change($product_id, $old_price, $price, $watchers); } } } /** * 通知价格变化 */ private function notify_price_change($product_id, $old_price, $new_price, $watchers) { $product = wc_get_product($product_id); if (!$product) { return; } $subject = sprintf( __('[%s] Price Alert: %s', 'bdfg-woo-compare'), get_bloginfo('name'), $product->get_name() ); $template = 'emails/price-alert.php'; $template_data = array( 'product' => $product, 'old_price' => $old_price, 'new_price' => $new_price, 'product_url' => $product->get_permalink() ); foreach ($watchers as $user_id) { $user = get_user_by('id', $user_id); if (!$user) { continue; } // 使用WooCommerce邮件模板发送通知 WC()->mailer()->send( $user->user_email, $subject, wc_get_template_html($template, $template_data) ); } } /** * 清理过期数据 */ public function cleanup_expired_data() { global $wpdb; // 清理过期的分享链接 $expired_shares = $wpdb->get_col( $wpdb->prepare( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE %s AND option_value < %s", 'bdfg_share_%', current_time('mysql', 1) ) ); foreach ($expired_shares as $option_name) { delete_option($option_name); } // 清理过期的价格监控 $this->cleanup_watch_lists(); } // 其他辅助方法... } // 初始化扩展功能 BDFG_Compare_Extended::get_instance();
assets/js/bdfg-compare-public.js
相关文章: WooCommerce 客户分析报告插件
/** * BDFG WooCommerce Compare - Frontend JavaScript * * @package BDFG_Woo_Compare * @author beiduofengou * @version 2.3.1 */ (function($) { 'use strict'; var BDFG_Compare = { init: function() { this.modal = $('#bdfg-compare-modal'); this.compareBtn = $('.bdfg-compare-btn'); this.compareTable = $('.bdfg-compare-table'); this.noticeTimeout = null; this.bindEvents(); this.initTooltips(); }, bindEvents: function() { var self = this; // 添加到比较列表 $(document).on('click', '.bdfg-compare-btn', function(e) { e.preventDefault(); self.addToCompare($(this)); }); // 从比较列表中移除 $(document).on('click', '.bdfg-remove-compare', function(e) { e.preventDefault(); self.removeFromCompare($(this)); }); // 分享比较列表 $(document).on('click', '.bdfg-share-compare', function(e) { e.preventDefault(); self.shareCompare($(this)); }); // 导出比较列表 $(document).on('click', '.bdfg-export-pdf, .bdfg-export-csv', function(e) { e.preventDefault(); self.exportCompare($(this)); }); // 保存比较列表 $(document).on('click', '.bdfg-save-compare', function(e) { e.preventDefault(); self.saveCompare($(this)); }); // 关闭弹窗 $(document).on('click', '.bdfg-modal-close', function() { self.closeModal(); }); // ESC关闭弹窗 $(document).keyup(function(e) { if (e.key === "Escape") { self.closeModal(); } }); }, addToCompare: function(button) { var self = this; var productId = button.data('product-id'); $.ajax({ url: bdfgCompare.ajaxurl, type: 'POST', data: { action: 'bdfg_add_to_compare', product_id: productId, nonce: button.data('nonce') }, beforeSend: function() { button.addClass('loading'); }, success: function(response) { if (response.success) { self.showNotice(response.data.message, 'success'); self.updateCompareCount(response.data.count); button.addClass('added').text(bdfgCompare.i18n.added); } else { self.showNotice(response.data.message, 'error'); } }, error: function() { self.showNotice(bdfgCompare.i18n.error, 'error'); }, complete: function() { button.removeClass('loading'); } }); }, removeFromCompare: function(button) { var self = this; var productId = button.data('product-id'); if (!confirm(bdfgCompare.i18n.removeConfirm)) { return; } $.ajax({ url: bdfgCompare.ajaxurl, type: 'POST', data: { action: 'bdfg_remove_from_compare', product_id: productId, nonce: button.data('nonce') }, beforeSend: function() { button.addClass('loading'); }, success: function(response) { if (response.success) { self.showNotice(response.data.message, 'success'); self.updateCompareCount(response.data.count); self.updateCompareTable(response.data.html); } else { self.showNotice(response.data.message, 'error'); } }, error: function() { self.showNotice(bdfgCompare.i18n.error, 'error'); }, complete: function() { button.removeClass('loading'); } }); }, shareCompare: function(button) { var self = this; $.ajax({ url: bdfgCompare.ajaxurl, type: 'POST', data: { action: 'bdfg_share_compare', nonce: button.data('nonce') }, beforeSend: function() { button.addClass('loading'); }, success: function(response) { if (response.success) { self.showShareModal(response.data.share_url); } else { self.showNotice(response.data.message, 'error'); } }, error: function() { self.showNotice(bdfgCompare.i18n.error, 'error'); }, complete: function() { button.removeClass('loading'); } }); }, exportCompare: function(button) { var format = button.data('format'); var self = this; $.ajax({ url: bdfgCompare.ajaxurl, type: 'POST', data: { action: 'bdfg_export_compare', format: format, nonce: button.data('nonce') }, beforeSend: function() { button.addClass('loading'); }, success: function(response) { if (response.success) { window.location.href = response.data.file_url; } else { self.showNotice(response.data.message, 'error'); } }, error: function() { self.showNotice(bdfgCompare.i18n.error, 'error'); }, complete: function() { button.removeClass('loading'); } }); }, saveCompare: function(button) { var self = this; var name = prompt(bdfgCompare.i18n.savePrompt); if (name === null) { return; } $.ajax({ url: bdfgCompare.ajaxurl, type: 'POST', data: { action: 'bdfg_save_compare', name: name, nonce: button.data('nonce') }, beforeSend: function() { button.addClass('loading'); }, success: function(response) { if (response.success) { self.showNotice(response.data.message, 'success'); } else { self.showNotice(response.data.message, 'error'); } }, error: function() { self.showNotice(bdfgCompare.i18n.error, 'error'); }, complete: function() { button.removeClass('loading'); } }); }, showNotice: function(message, type) { var self = this; // 清除之前的通知 if (self.noticeTimeout) { clearTimeout(self.noticeTimeout); } // 移除现有通知 $('.bdfg-notice').remove(); // 创建新通知 var notice = $('<div/>', { 'class': 'bdfg-notice bdfg-notice-' + type, 'html': message }).appendTo('body'); // 显示动画 setTimeout(function() { notice.addClass('bdfg-notice-show'); }, 10); // 3秒后隐藏 self.noticeTimeout = setTimeout(function() { notice.removeClass('bdfg-notice-show'); setTimeout(function() { notice.remove(); }, 300); }, 3000); }, showShareModal: function(shareUrl) { var modalContent = '<div class="bdfg-modal-content">' + '<span class="bdfg-modal-close">×</span>' + '<h3>' + bdfgCompare.i18n.shareTitle + '</h3>' + '<div class="bdfg-share-url">' + '<input type="text" value="' + shareUrl + '" readonly>' + '<button class="bdfg-copy-url">' + bdfgCompare.i18n.copyUrl + '</button>' + '</div>' + '<div class="bdfg-social-share">' + '<a href="https://www.facebook.com/sharer/sharer.php?u=' + encodeURIComponent(shareUrl) + '" target="_blank" class="bdfg-share-facebook">Facebook</a>' + '<a href="https://twitter.com/intent/tweet?url=' + encodeURIComponent(shareUrl) + '" target="_blank" class="bdfg-share-twitter">Twitter</a>' + '</div>' + '</div>'; this.modal.html(modalContent).show(); // 复制链接功能 $('.bdfg-copy-url').on('click', function() { var urlInput = $(this).prev('input'); urlInput.select(); document.execCommand('copy'); $(this).text(bdfgCompare.i18n.copied); }); }, closeModal: function() { this.modal.hide().empty(); }, updateCompareCount: function(count) { $('.bdfg-compare-count').text(count); if (count > 0) { $('.bdfg-compare-widget').addClass('has-items'); } else { $('.bdfg-compare-widget').removeClass('has-items'); } }, updateCompareTable: function(html) { if (this.compareTable.length) { this.compareTable.replaceWith(html); } }, initTooltips: function() { $('.bdfg-tooltip').tooltipster({ theme: 'tooltipster-borderless', delay: 100, animationDuration: 200 }); } }; // 初始化 $(document).ready(function() { BDFG_Compare.init(); }); })(jQuery);
assets/css/bdfg-compare-public.css
/** * BDFG WooCommerce Compare - Frontend Styles * * @package BDFG_Woo_Compare * @author beiduofengou * @version 2.3.1 */ /* 比较按钮样式 */ .bdfg-compare-btn { margin: 10px 0; padding: 8px 15px; background-color: #f7f7f7; border: 1px solid #ddd; border-radius: 3px; cursor: pointer; transition: all 0.3s ease; } .bdfg-compare-btn:hover { background-color: #ebebeb; border-color: #ccc; } .bdfg-compare-btn.loading { opacity: 0.7; cursor: wait; } /* 比较表格样式 */ .bdfg-compare-wrapper { margin: 30px 0; overflow-x: auto; } .bdfg-compare-table { width: 100%; border-collapse: collapse; background: #fff; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .bdfg-compare-table th, .bdfg-compare-table td { padding: 15px; text-align: left; border: 1px solid #eee; vertical-align: top; } .bdfg-compare-table th { background: #f8f8f8; font-weight: 600; min-width: 150px; } .bdfg-compare-table td { min-width: 200px; } /* 图片样式 */ .bdfg-compare-image { text-align: center; margin-bottom: 10px; } .bdfg-compare-image img { max-width: 150px; height: auto; } /* 价格样式 */ .bdfg-compare-price { font-size: 1.1em; color: #77a464; font-weight: 600; } /* 差异高亮 */ .bdfg-highlight { background-color: #fff9c4; padding: 2px 5px; border-radius: 2px; } /* 操作按钮 */ .bdfg-compare-actions-top { margin-bottom: 20px; display: flex; gap: 10px; flex-wrap: wrap; } .bdfg-compare-actions-top button { padding: 8px 15px; background: #2271b1; color: #fff; border: none; border-radius: 3px; cursor: pointer; transition: all 0.3s ease; } .bdfg-compare-actions-top button:hover { background: #135e96; } /* 弹窗样式 */ .bdfg-modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 999999; } .bdfg-modal-content { position: relative; background: #fff; width: 90%; max-width: 600px; margin: 50px auto; padding: 20px; border-radius: 5px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); } .bdfg-modal-close { position: absolute; top: 10px; right: 10px; font-size: 24px; cursor: pointer; color: #666; } /* 响应式调整 */ @media screen and (max-width: 768px) { .bdfg-compare-table { font-size: 14px; } .bdfg-compare-table th, .bdfg-compare-table td { padding: 10px; } .bdfg-compare-image img { max-width: 100px; } }
templates/compare-table.php
相关文章: WordPress 智能缓存管理
<?php /** * Compare table template * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @version 2.3.1 */ if (!defined('ABSPATH')) { exit; } ?> <div class="bdfg-compare-wrapper"> <?php if (empty($products)) : ?> <div class="bdfg-compare-empty"> <p><?php esc_html_e('No products added to compare list.', 'bdfg-woo-compare'); ?></p> <a href="<?php echo esc_url(wc_get_page_permalink('shop')); ?>" class="button"> <?php esc_html_e('Browse products', 'bdfg-woo-compare'); ?> </a> </div> <?php else : ?> <div class="bdfg-compare-actions-top"> <button class="bdfg-share-compare" data-nonce="<?php echo wp_create_nonce('bdfg_share_nonce'); ?>"> <?php esc_html_e('Share Comparison', 'bdfg-woo-compare'); ?> </button> <div class="bdfg-export-buttons"> <button class="bdfg-export-pdf" data-format="pdf" data-nonce="<?php echo wp_create_nonce('bdfg_export_nonce'); ?>"> <?php esc_html_e('Export as PDF', 'bdfg-woo-compare'); ?> </button> <button class="bdfg-export-csv" data-format="csv" data-nonce="<?php echo wp_create_nonce('bdfg_export_nonce'); ?>"> <?php esc_html_e('Export as CSV', 'bdfg-woo-compare'); ?> </button> </div> <?php if (is_user_logged_in()) : ?> <button class="bdfg-save-compare" data-nonce="<?php echo wp_create_nonce('bdfg_save_nonce'); ?>"> <?php esc_html_e('Save Comparison', 'bdfg-woo-compare'); ?> </button> <?php endif; ?> </div> <table class="bdfg-compare-table"> <tbody> <?php foreach ($fields as $field_id => $field) : ?> <tr class="bdfg-compare-row bdfg-compare-<?php echo esc_attr($field_id); ?>"> <th class="bdfg-compare-label"> <?php echo esc_html($field['label']); ?> </th> <?php foreach ($products as $product) : ?> <td class="bdfg-compare-value"> <?php if (is_callable($field['callback'])) { echo call_user_func($field['callback'], $product); } ?> </td> <?php endforeach; ?> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> </div>
admin/class-bdfg-settings.php
<?php /** * BDFG WooCommerce Compare Settings * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @version 2.3.1 * @since 1.0.0 */ if (!defined('ABSPATH')) { exit; } class BDFG_Compare_Settings { /** * 设置页面钩子 */ private $settings_page; /** * 设置选项 */ private $options; /** * 构造函数 */ public function __construct() { add_action('admin_menu', array($this, 'add_settings_page')); add_action('admin_init', array($this, 'init_settings')); // 加载当前设置 $this->options = get_option('bdfg_compare_settings'); } /** * 添加设置菜单 */ public function add_settings_page() { $this->settings_page = add_submenu_page( 'woocommerce', __('Compare Settings', 'bdfg-woo-compare'), __('Compare', 'bdfg-woo-compare'), 'manage_options', 'bdfg-compare-settings', array($this, 'render_settings_page') ); // 加载设置页面的样式和脚本 add_action('load-' . $this->settings_page, array($this, 'enqueue_admin_assets')); } /** * 初始化设置 */ public function init_settings() { register_setting( 'bdfg_compare_settings', 'bdfg_compare_settings', array($this, 'sanitize_settings') ); // 常规设置 add_settings_section( 'bdfg_compare_general', __('General Settings', 'bdfg-woo-compare'), array($this, 'render_general_section'), 'bdfg_compare_settings' ); // 按钮设置 add_settings_section( 'bdfg_compare_button', __('Button Settings', 'bdfg-woo-compare'), array($this, 'render_button_section'), 'bdfg_compare_settings' ); // 表格设置 add_settings_section( 'bdfg_compare_table', __('Table Settings', 'bdfg-woo-compare'), array($this, 'render_table_section'), 'bdfg_compare_settings' ); // 添加设置字段 $this->add_settings_fields(); } /** * 添加设置字段 */ private function add_settings_fields() { // 常规设置字段 add_settings_field( 'max_products', __('Maximum Products', 'bdfg-woo-compare'), array($this, 'render_number_field'), 'bdfg_compare_settings', 'bdfg_compare_general', array( 'id' => 'max_products', 'desc' => __('Maximum number of products that can be compared', 'bdfg-woo-compare'), 'default' => 4 ) ); // 按钮设置字段 add_settings_field( 'button_position', __('Button Position', 'bdfg-woo-compare'), array($this, 'render_select_field'), 'bdfg_compare_settings', 'bdfg_compare_button', array( 'id' => 'button_position', 'options' => array( 'woocommerce_after_add_to_cart_button' => __('After Add to Cart', 'bdfg-woo-compare'), 'woocommerce_before_add_to_cart_button' => __('Before Add to Cart', 'bdfg-woo-compare'), 'woocommerce_after_shop_loop_item' => __('After Product', 'bdfg-woo-compare') ), 'default' => 'woocommerce_after_add_to_cart_button' ) ); } /** * 渲染设置页面 */ public function render_settings_page() { if (!current_user_can('manage_options')) { return; } ?> <div class="wrap bdfg-compare-settings"> <h1><?php echo esc_html(get_admin_page_title()); ?></h1> <?php settings_errors(); ?> <form action="options.php" method="post"> <?php settings_fields('bdfg_compare_settings'); do_settings_sections('bdfg_compare_settings'); submit_button(); ?> </form> </div> <?php } } // 初始化设置类 new BDFG_Compare_Settings();
includes/class-bdfg-template-loader.php
相关文章: WordPress优惠券提醒插件系统
<?php /** * BDFG WooCommerce Compare Template Loader * * @package BDFG_Woo_Compare * @author beiduofengou <[email protected]> * @version 2.3.1 */ if (!defined('ABSPATH')) { exit; } class BDFG_Template_Loader { /** * 获取模板路径 */ public static function locate_template($template_name) { $template = ''; // 主题中的模板优先 $template_path = 'bdfg-compare/'; // 在主题中查找 $template = locate_template( array( $template_path . $template_name, $template_name ) ); // 使用插件默认模板 if (!$template) { $template = BDFG_COMPARE_TEMPLATES_PATH . $template_name; } return apply_filters('bdfg_compare_locate_template', $template, $template_name); } /** * 获取模板内容 */ public static function get_template($template_name, $args = array()) { $template = self::locate_template($template_name); if (!file_exists($template)) { /* translators: %s template */ _doing_it_wrong(__FUNCTION__, sprintf(__('%s does not exist.', 'bdfg-woo-compare'), '<code>' . $template . '</code>'), '2.3.0'); return; } // 提取变量供模板使用 if ($args && is_array($args)) { extract($args); } include $template; } }