WooCommerce 商店的高级产品定价和折扣管理。
<?php /** * Plugin Name: BDFG Dynamic Pricing * Plugin URI: https://beiduofengou.net/2024/10/16/bdfg-dynamic-pricing/ * Description: Advanced dynamic pricing and discount management system for WooCommerce. Create flexible pricing rules, boost sales with marketing features, and grow your business. * Version: 2.3.0 * Requires at least: 5.8 * Requires PHP: 7.4 * Author: BeiDuoFengOu * Author URI: https://beiduofengou.net * Text Domain: bdfg-dynamic-pricing * Domain Path: /languages * License: GPL v2 or later * License URI: https://www.gnu.org/licenses/gpl-2.0.html * WC requires at least: 5.0 * WC tested up to: 8.0 * * @package BDFG_Dynamic_Pricing * @author BeiDuoFengOu * @copyright 2024 BeiDuoFengOu */ if (!defined('ABSPATH')) { exit; // 防止直接访问 } // 定义插件常量 define('BDFG_VERSION', '2.3.0'); define('BDFG_PLUGIN_FILE', __FILE__); define('BDFG_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('BDFG_PLUGIN_URL', plugin_dir_url(__FILE__)); define('BDFG_PLUGIN_BASENAME', plugin_basename(__FILE__)); define('BDFG_MINIMUM_WP_VERSION', '5.8'); define('BDFG_MINIMUM_WC_VERSION', '5.0'); /** * 主插件类 */ final class BDFG_Dynamic_Pricing { /** * 插件实例 * * @var BDFG_Dynamic_Pricing */ private static $instance = null; /** * 插件设置 * * @var array */ private $settings; /** * 营销扩展实例 * * @var BDFG_Marketing_Notification_Extension */ private $marketing; /** * 获取插件单例实例 * * @return BDFG_Dynamic_Pricing */ public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * 构造函数 */ private function __construct() { $this->define_constants(); $this->check_requirements(); $this->includes(); $this->init_hooks(); // 加载设置 $this->settings = get_option('bdfg_settings', $this->get_default_settings()); // 如果启用了营销功能,初始化营销扩展 if ($this->is_marketing_enabled()) { $this->init_marketing(); } do_action('bdfg_loaded'); } /** * 定义额外的常量 */ private function define_constants() { define('BDFG_DB_VERSION', '2.3.0'); define('BDFG_ABSPATH', dirname(BDFG_PLUGIN_FILE) . '/'); } /** * 检查系统要求 */ private function check_requirements() { if (version_compare(get_bloginfo('version'), BDFG_MINIMUM_WP_VERSION, '<')) { add_action('admin_notices', array($this, 'wordpress_version_notice')); return; } if (!class_exists('WooCommerce')) { add_action('admin_notices', array($this, 'woocommerce_missing_notice')); return; } if (defined('WC_VERSION') && version_compare(WC_VERSION, BDFG_MINIMUM_WC_VERSION, '<')) { add_action('admin_notices', array($this, 'woocommerce_version_notice')); return; } } /** * 包含必要的文件 */ private function includes() { // 核心文件 require_once BDFG_PLUGIN_DIR . 'includes/class-bdfg-autoloader.php'; require_once BDFG_PLUGIN_DIR . 'includes/class-bdfg-installer.php'; require_once BDFG_PLUGIN_DIR . 'includes/class-bdfg-dynamic-pricing-extended.php'; require_once BDFG_PLUGIN_DIR . 'includes/class-bdfg-marketing-notification-extension.php'; // 管理员界面 if (is_admin()) { require_once BDFG_PLUGIN_DIR . 'includes/admin/class-bdfg-admin.php'; } // API和集成 require_once BDFG_PLUGIN_DIR . 'includes/api/class-bdfg-api.php'; require_once BDFG_PLUGIN_DIR . 'includes/integrations/class-bdfg-woocommerce.php'; } /** * 初始化钩子 */ private function init_hooks() { // 激活和停用钩子 register_activation_hook(BDFG_PLUGIN_FILE, array($this, 'activate')); register_deactivation_hook(BDFG_PLUGIN_FILE, array($this, 'deactivate')); // 初始化动作 add_action('plugins_loaded', array($this, 'load_plugin_textdomain')); add_action('init', array($this, 'init'), 0); // WooCommerce集成 add_action('woocommerce_loaded', array($this, 'woocommerce_loaded')); // 过滤器 add_filter('woocommerce_get_price_html', array($this, 'maybe_add_discount_badge'), 10, 2); add_filter('plugin_action_links_' . BDFG_PLUGIN_BASENAME, array($this, 'add_plugin_action_links')); // AJAX处理 add_action('wp_ajax_bdfg_save_rule', array($this, 'ajax_save_rule')); add_action('wp_ajax_bdfg_delete_rule', array($this, 'ajax_delete_rule')); } /** * 获取默认设置 * * @return array */ private function get_default_settings() { return array( 'general' => array( 'enable_dynamic_pricing' => 'yes', 'price_display_format' => 'both_prices', 'sale_badge_text' => __('Sale!', 'bdfg-dynamic-pricing'), 'enable_logging' => 'no' ), 'marketing' => array( 'enable_marketing_features' => 'yes', 'countdown_timer' => 'yes', 'stock_countdown' => 'yes', 'social_share_discount' => 'yes', 'email_notifications' => 'yes' ), 'advanced' => array( 'cache_duration' => 3600, 'debug_mode' => 'no', 'clean_on_uninstall' => 'no', 'performance_mode' => 'balanced' ) ); } /** * 插件激活 */ public function activate() { if (!class_exists('WooCommerce')) { deactivate_plugins(plugin_basename(BDFG_PLUGIN_FILE)); wp_die( __('BDFG Dynamic Pricing requires WooCommerce to be installed and activated.', 'bdfg-dynamic-pricing'), 'Plugin dependency check', array('back_link' => true) ); } // 运行数据库更新 BDFG_Installer::install(); // 添加默认设置 if (!get_option('bdfg_settings')) { update_option('bdfg_settings', $this->get_default_settings()); } // 记录安装时间 add_option('bdfg_installation_time', current_time('mysql')); // 刷新重写规则 flush_rewrite_rules(); do_action('bdfg_activated'); } /** * 插件停用 */ public function deactivate() { // 清理定时任务 wp_clear_scheduled_hook('bdfg_daily_maintenance'); wp_clear_scheduled_hook('bdfg_cleanup_old_statistics'); // 清理临时数据 $this->cleanup_temp_data(); // 刷新重写规则 flush_rewrite_rules(); do_action('bdfg_deactivated'); } /** * 加载文本域 */ public function load_plugin_textdomain() { load_plugin_textdomain( 'bdfg-dynamic-pricing', false, dirname(plugin_basename(BDFG_PLUGIN_FILE)) . '/languages/' ); } /** * 初始化插件 */ public function init() { // 检查版本并执行更新 $this->check_version(); // 初始化会话 $this->maybe_init_session(); // 初始化管理界面 if (is_admin()) { new BDFG_Admin($this); } do_action('bdfg_init'); } /** * 检查并初始化会话 */ private function maybe_init_session() { if (!session_id() && !headers_sent()) { session_start(); } } /** * WooCommerce加载完成后的操作 */ public function woocommerce_loaded() { // 添加价格过滤器 add_filter('woocommerce_product_get_price', array($this, 'apply_dynamic_pricing'), 10, 2); add_filter('woocommerce_product_get_regular_price', array($this, 'apply_dynamic_pricing'), 10, 2); add_filter('woocommerce_product_variation_get_price', array($this, 'apply_dynamic_pricing'), 10, 2); } /** * 应用动态定价 * * @param float $price * @param WC_Product $product * @return float */ public function apply_dynamic_pricing($price, $product) { if (!$this->should_apply_pricing($product)) { return $price; } $rules = $this->get_applicable_rules($product); foreach ($rules as $rule) { $price = $this->calculate_discounted_price($price, $rule); } return $price; } /** * 检查是否启用了营销功能 * * @return bool */ public function is_marketing_enabled() { return isset($this->settings['marketing']['enable_marketing_features']) && $this->settings['marketing']['enable_marketing_features'] === 'yes'; } /** * 清理临时数据 */ private function cleanup_temp_data() { global $wpdb; $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE 'bdfg_temp_%'"); } /** * 添加插件操作链接 * * @param array $links * @return array */ public function add_plugin_action_links($links) { $plugin_links = array( '<a href="' . admin_url('admin.php?page=bdfg-dynamic-pricing') . '">' . __('Settings', 'bdfg-dynamic-pricing') . '</a>', '<a href="https://beiduofengou.net/docs/bdfg-dynamic-pricing/" target="_blank">' . __('Documentation', 'bdfg-dynamic-pricing') . '</a>' ); return array_merge($plugin_links, $links); } /** * 显示WordPress版本提示 */ public function wordpress_version_notice() { $message = sprintf( esc_html__('BDFG Dynamic Pricing requires WordPress version %s or higher. Please upgrade WordPress to continue using the plugin.', 'bdfg-dynamic-pricing'), BDFG_MINIMUM_WP_VERSION ); echo '<div class="error"><p>' . $message . '</p></div>'; } /** * 显示WooCommerce缺失提示 */ public function woocommerce_missing_notice() { $message = sprintf( esc_html__('BDFG Dynamic Pricing requires WooCommerce to be installed and activated. You can download %s here.', 'bdfg-dynamic-pricing'), '<a href="https://woocommerce.com/" target="_blank">WooCommerce</a>' ); echo '<div class="error"><p>' . $message . '</p></div>'; } /** * 显示WooCommerce版本提示 */ public function woocommerce_version_notice() { $message = sprintf( esc_html__('BDFG Dynamic Pricing requires WooCommerce version %s or higher. Please upgrade WooCommerce to continue using the plugin.', 'bdfg-dynamic-pricing'), BDFG_MINIMUM_WC_VERSION ); echo '<div class="error"><p>' . $message . '</p></div>'; } } /** * 返回主插件实例 * * @return BDFG_Dynamic_Pricing */ function BDFG() { return BDFG_Dynamic_Pricing::get_instance(); } // 初始化插件 add_action('plugins_loaded', 'BDFG');
includes/class-bdfg-dynamic-pricing-extended.php
相关文章: WordPress优惠券提醒插件系统
<?php /** * BDFG Dynamic Pricing - Extended Features * * 提供高级功能扩展,包括数据导入导出、统计报告和批量操作 * * @package BDFG_Dynamic_Pricing * @subpackage Extensions * @version 2.3.0 * @since 2.0.0 * @author BeiDuoFengOu * @last_modified 2024-10-16 */ defined('ABSPATH') || exit; class BDFG_Dynamic_Pricing_Extended { /** * 父插件实例 * * @var BDFG_Dynamic_Pricing */ private $plugin; /** * 统计数据缓存 * * @var array */ private $stats_cache = array(); /** * 构造函数 * * @param BDFG_Dynamic_Pricing $plugin */ public function __construct($plugin) { $this->plugin = $plugin; $this->init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 添加菜单 add_action('admin_menu', array($this, 'add_admin_menus'), 20); // 导入导出功能 add_action('admin_post_bdfg_export_rules', array($this, 'handle_export_rules')); add_action('admin_post_bdfg_export_stats', array($this, 'handle_export_statistics')); add_action('wp_ajax_bdfg_import_rules', array($this, 'handle_import_rules')); // 批量处理 add_action('wp_ajax_bdfg_bulk_enable_rules', array($this, 'handle_bulk_enable_rules')); add_action('wp_ajax_bdfg_bulk_disable_rules', array($this, 'handle_bulk_disable_rules')); // 定时任务 add_action('bdfg_daily_maintenance', array($this, 'perform_daily_maintenance')); add_action('bdfg_cleanup_old_statistics', array($this, 'cleanup_old_statistics')); } /** * 添加管理菜单 */ public function add_admin_menus() { add_submenu_page( 'bdfg-dynamic-pricing', __('Import/Export', 'bdfg-dynamic-pricing'), __('Import/Export', 'bdfg-dynamic-pricing'), 'manage_woocommerce', 'bdfg-import-export', array($this, 'render_import_export_page') ); add_submenu_page( 'bdfg-dynamic-pricing', __('Statistics', 'bdfg-dynamic-pricing'), __('Statistics', 'bdfg-dynamic-pricing'), 'manage_woocommerce', 'bdfg-statistics', array($this, 'render_statistics_page') ); } /** * 渲染导入导出页面 */ public function render_import_export_page() { if (!current_user_can('manage_woocommerce')) { wp_die(__('You do not have sufficient permissions to access this page.', 'bdfg-dynamic-pricing')); } ?> <div class="wrap bdfg-admin"> <h1><?php echo esc_html__('Import/Export Rules', 'bdfg-dynamic-pricing'); ?></h1> <div class="bdfg-admin-content"> <!-- 导出部分 --> <div class="bdfg-card"> <h2><?php echo esc_html__('Export', 'bdfg-dynamic-pricing'); ?></h2> <p class="description"> <?php echo esc_html__('Export your pricing rules and settings for backup or transfer to another site.', 'bdfg-dynamic-pricing'); ?> </p> <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"> <?php wp_nonce_field('bdfg_export_rules', 'bdfg_export_nonce'); ?> <input type="hidden" name="action" value="bdfg_export_rules"> <p> <label> <input type="checkbox" name="include_statistics" value="1"> <?php echo esc_html__('Include statistics data', 'bdfg-dynamic-pricing'); ?> </label> </p> <button type="submit" class="button button-primary"> <?php echo esc_html__('Export Rules', 'bdfg-dynamic-pricing'); ?> </button> </form> </div> <!-- 导入部分 --> <div class="bdfg-card"> <h2><?php echo esc_html__('Import', 'bdfg-dynamic-pricing'); ?></h2> <p class="description"> <?php echo esc_html__('Import pricing rules from a JSON file.', 'bdfg-dynamic-pricing'); ?> </p> <form method="post" enctype="multipart/form-data" id="bdfg-import-form"> <?php wp_nonce_field('bdfg_import_rules', 'bdfg_import_nonce'); ?> <p> <input type="file" name="import_file" accept=".json" required> </p> <p> <label> <input type="checkbox" name="overwrite_existing" value="1"> <?php echo esc_html__('Overwrite existing rules', 'bdfg-dynamic-pricing'); ?> </label> </p> <button type="submit" class="button button-primary"> <?php echo esc_html__('Import Rules', 'bdfg-dynamic-pricing'); ?> </button> </form> <div id="bdfg-import-results"></div> </div> </div> </div> <?php } /** * 渲染统计页面 */ public function render_statistics_page() { if (!current_user_can('manage_woocommerce')) { wp_die(__('You do not have sufficient permissions to access this page.', 'bdfg-dynamic-pricing')); } // 获取日期范围 $start_date = isset($_GET['start_date']) ? sanitize_text_field($_GET['start_date']) : date('Y-m-d', strtotime('-30 days')); $end_date = isset($_GET['end_date']) ? sanitize_text_field($_GET['end_date']) : date('Y-m-d'); // 获取统计数据 $stats = $this->get_statistics_data($start_date, $end_date); ?> <div class="wrap bdfg-admin"> <h1><?php echo esc_html__('Discount Statistics', 'bdfg-dynamic-pricing'); ?></h1> <!-- 日期筛选器 --> <div class="bdfg-date-filter"> <form method="get"> <input type="hidden" name="page" value="bdfg-statistics"> <label> <?php echo esc_html__('Start Date:', 'bdfg-dynamic-pricing'); ?> <input type="date" name="start_date" value="<?php echo esc_attr($start_date); ?>"> </label> <label> <?php echo esc_html__('End Date:', 'bdfg-dynamic-pricing'); ?> <input type="date" name="end_date" value="<?php echo esc_attr($end_date); ?>"> </label> <button type="submit" class="button"> <?php echo esc_html__('Filter', 'bdfg-dynamic-pricing'); ?> </button> </form> </div> <!-- 统计概览 --> <div class="bdfg-stats-overview"> <div class="bdfg-stat-card"> <h3><?php echo esc_html__('Total Discounts', 'bdfg-dynamic-pricing'); ?></h3> <div class="stat-value"><?php echo wc_price($stats['total_discount']); ?></div> </div> <div class="bdfg-stat-card"> <h3><?php echo esc_html__('Total Orders', 'bdfg-dynamic-pricing'); ?></h3> <div class="stat-value"><?php echo esc_html($stats['total_orders']); ?></div> </div> <div class="bdfg-stat-card"> <h3><?php echo esc_html__('Average Discount', 'bdfg-dynamic-pricing'); ?></h3> <div class="stat-value"><?php echo wc_price($stats['avg_discount']); ?></div> </div> </div> <!-- 详细数据表格 --> <div class="bdfg-stats-table-wrapper"> <table class="wp-list-table widefat fixed striped"> <thead> <tr> <th><?php echo esc_html__('Date', 'bdfg-dynamic-pricing'); ?></th> <th><?php echo esc_html__('Orders', 'bdfg-dynamic-pricing'); ?></th> <th><?php echo esc_html__('Total Discount', 'bdfg-dynamic-pricing'); ?></th> <th><?php echo esc_html__('Average Discount', 'bdfg-dynamic-pricing'); ?></th> </tr> </thead> <tbody> <?php foreach ($stats['daily_stats'] as $day): ?> <tr> <td><?php echo esc_html($day->date); ?></td> <td><?php echo esc_html($day->order_count); ?></td> <td><?php echo wc_price($day->total_discount); ?></td> <td><?php echo wc_price($day->avg_discount); ?></td> </tr> <?php endforeach; ?> </tbody> </table> </div> </div> <?php } /** * 处理规则导出 */ public function handle_export_rules() { if (!current_user_can('manage_woocommerce') || !check_admin_referer('bdfg_export_rules', 'bdfg_export_nonce')) { wp_die(__('Permission denied', 'bdfg-dynamic-pricing')); } $include_stats = isset($_POST['include_statistics']) && $_POST['include_statistics'] === '1'; $data = $this->get_export_data($include_stats); // 设置响应头 header('Content-Type: application/json'); header('Content-Disposition: attachment; filename=bdfg-rules-' . date('Y-m-d') . '.json'); header('Pragma: no-cache'); header('Expires: 0'); echo wp_json_encode($data, JSON_PRETTY_PRINT); exit; } /** * 处理规则导入 */ public function handle_import_rules() { check_ajax_referer('bdfg_import_rules', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(__('Permission denied', 'bdfg-dynamic-pricing')); } $file = $_FILES['import_file']; if ($file['error'] || !is_uploaded_file($file['tmp_name'])) { wp_send_json_error(__('Error uploading file', 'bdfg-dynamic-pricing')); } $content = file_get_contents($file['tmp_name']); $data = json_decode($content, true); if (json_last_error() !== JSON_ERROR_NONE) { wp_send_json_error(__('Invalid JSON file', 'bdfg-dynamic-pricing')); } try { $this->process_import_data($data); wp_send_json_success(__('Rules imported successfully', 'bdfg-dynamic-pricing')); } catch (Exception $e) { wp_send_json_error($e->getMessage()); } } /** * 获取统计数据 * * @param string $start_date * @param string $end_date * @return array */ private function get_statistics_data($start_date, $end_date) { global $wpdb; $cache_key = md5("stats_{$start_date}_{$end_date}"); if (isset($this->stats_cache[$cache_key])) { return $this->stats_cache[$cache_key]; } $daily_stats = $wpdb->get_results($wpdb->prepare( "SELECT DATE(applied_date) as date, COUNT(DISTINCT order_id) as order_count, SUM(discount_amount) as total_discount, AVG(discount_amount) as avg_discount FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date BETWEEN %s AND %s GROUP BY DATE(applied_date) ORDER BY date DESC", $start_date, $end_date )); $total_stats = $wpdb->get_row($wpdb->prepare( "SELECT COUNT(DISTINCT order_id) as total_orders, SUM(discount_amount) as total_discount, AVG(discount_amount) as avg_discount FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date BETWEEN %s AND %s", $start_date, $end_date )); $stats = array( 'daily_stats' => $daily_stats, 'total_orders' => $total_stats->total_orders, 'total_discount' => $total_stats->total_discount, 'avg_discount' => $total_stats->avg_discount ); $this->stats_cache[$cache_key] = $stats; return $stats; } /** * 清理旧统计数据 */ public function cleanup_old_statistics() { global $wpdb; // 默认保留90天的数据 $days_to_keep = apply_filters('bdfg_statistics_retention_days', 90); $wpdb->query($wpdb->prepare( "DELETE FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date < DATE_SUB(NOW(), INTERVAL %d DAY)", $days_to_keep )); } /** * 获取导出数据 * * @param bool $include_stats * @return array */ private function get_export_data($include_stats = false) { global $wpdb; // 获取规则 $rules = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}bdfg_discount_rules ORDER BY priority ASC" ); $export_data = array( 'version' => BDFG_VERSION, 'generated_at' => current_time('mysql'), 'site_url' => get_site_url(), 'rules' => $rules, 'settings' => get_option('bdfg_settings') ); // 如果包含统计数据 if ($include_stats) { $stats = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date >= DATE_SUB(NOW(), INTERVAL 30 DAY)" ); $export_data['statistics'] = $stats; } return $export_data; } /** * 处理导入数据 * * @param array $data * @throws Exception */ private function process_import_data($data) { global $wpdb; // 验证数据格式 if (!isset($data['version']) || !isset($data['rules'])) { throw new Exception(__('Invalid import file format', 'bdfg-dynamic-pricing')); } // 开始事务 $wpdb->query('START TRANSACTION'); try { // 是否覆盖现有规则 $overwrite = isset($_POST['overwrite_existing']) && $_POST['overwrite_existing'] === '1'; if ($overwrite) { $wpdb->query("TRUNCATE TABLE {$wpdb->prefix}bdfg_discount_rules"); } // 导入规则 foreach ($data['rules'] as $rule) { $rule = (array) $rule; unset($rule['rule_id']); // 移除原始ID $wpdb->insert( $wpdb->prefix . 'bdfg_discount_rules', array_merge($rule, array( 'updated_at' => current_time('mysql') )), array( '%s', '%s', '%s', '%f', '%s', '%s', '%s', '%d', '%s', '%s', '%s' ) ); } // 导入设置 if (isset($data['settings'])) { update_option('bdfg_settings', $data['settings']); } $wpdb->query('COMMIT'); // 清理缓存 wp_cache_flush(); // 记录导入日志 $this->log_import_activity($data); } catch (Exception $e) { $wpdb->query('ROLLBACK'); throw $e; } } /** * 记录导入活动 * * @param array $data */ private function log_import_activity($data) { $log = array( 'type' => 'import', 'rules_count' => count($data['rules']), 'source_site' => isset($data['site_url']) ? $data['site_url'] : 'unknown', 'source_version' => isset($data['version']) ? $data['version'] : 'unknown', 'imported_at' => current_time('mysql'), 'imported_by' => get_current_user_id() ); $this->add_activity_log($log); } /** * 添加活动日志 * * @param array $log */ private function add_activity_log($log) { global $wpdb; $wpdb->insert( $wpdb->prefix . 'bdfg_activity_log', $log, array('%s', '%d', '%s', '%s', '%s', '%d') ); } /** * 处理批量启用规则 */ public function handle_bulk_enable_rules() { check_ajax_referer('bdfg_bulk_action', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(__('Permission denied', 'bdfg-dynamic-pricing')); } $rule_ids = isset($_POST['rule_ids']) ? array_map('intval', $_POST['rule_ids']) : array(); if (empty($rule_ids)) { wp_send_json_error(__('No rules selected', 'bdfg-dynamic-pricing')); } global $wpdb; $updated = $wpdb->query($wpdb->prepare( "UPDATE {$wpdb->prefix}bdfg_discount_rules SET status = 'active', updated_at = %s WHERE rule_id IN (" . implode(',', $rule_ids) . ")", current_time('mysql') )); if ($updated !== false) { wp_send_json_success(array( 'message' => sprintf( __('%d rules enabled successfully', 'bdfg-dynamic-pricing'), $updated ) )); } else { wp_send_json_error(__('Error enabling rules', 'bdfg-dynamic-pricing')); } } /** * 处理批量禁用规则 */ public function handle_bulk_disable_rules() { check_ajax_referer('bdfg_bulk_action', 'nonce'); if (!current_user_can('manage_woocommerce')) { wp_send_json_error(__('Permission denied', 'bdfg-dynamic-pricing')); } $rule_ids = isset($_POST['rule_ids']) ? array_map('intval', $_POST['rule_ids']) : array(); if (empty($rule_ids)) { wp_send_json_error(__('No rules selected', 'bdfg-dynamic-pricing')); } global $wpdb; $updated = $wpdb->query($wpdb->prepare( "UPDATE {$wpdb->prefix}bdfg_discount_rules SET status = 'inactive', updated_at = %s WHERE rule_id IN (" . implode(',', $rule_ids) . ")", current_time('mysql') )); if ($updated !== false) { wp_send_json_success(array( 'message' => sprintf( __('%d rules disabled successfully', 'bdfg-dynamic-pricing'), $updated ) )); } else { wp_send_json_error(__('Error disabling rules', 'bdfg-dynamic-pricing')); } } /** * 执行每日维护任务 */ public function perform_daily_maintenance() { // 清理过期规则 $this->cleanup_expired_rules(); // 更新规则统计 $this->update_rules_statistics(); // 优化数据表 $this->optimize_tables(); do_action('bdfg_after_daily_maintenance'); } /** * 清理过期规则 */ private function cleanup_expired_rules() { global $wpdb; $wpdb->query($wpdb->prepare( "UPDATE {$wpdb->prefix}bdfg_discount_rules SET status = 'expired', updated_at = %s WHERE end_date < %s AND status = 'active'", current_time('mysql'), current_time('mysql') )); } /** * 更新规则统计 */ private function update_rules_statistics() { global $wpdb; $rules = $wpdb->get_results( "SELECT rule_id FROM {$wpdb->prefix}bdfg_discount_rules WHERE status = 'active'" ); foreach ($rules as $rule) { $stats = $this->calculate_rule_statistics($rule->rule_id); $this->update_rule_meta($rule->rule_id, 'statistics', $stats); } } /** * 优化数据表 */ private function optimize_tables() { global $wpdb; $tables = array( $wpdb->prefix . 'bdfg_discount_rules', $wpdb->prefix . 'bdfg_statistics', $wpdb->prefix . 'bdfg_activity_log' ); foreach ($tables as $table) { $wpdb->query("OPTIMIZE TABLE $table"); } } }
includes/class-bdfg-marketing-notification-extension.php
<?php /** * BDFG Dynamic Pricing - Marketing & Notifications Extension * * 提供营销功能和客户通知系统 * * @package BDFG_Dynamic_Pricing * @subpackage Marketing * @version 2.3.0 * @since 2.0.0 * @author BeiDuoFengOu * @last_modified 2024-10-16 */ defined('ABSPATH') || exit; class BDFG_Marketing_Notification_Extension { /** * 父插件实例 * * @var BDFG_Dynamic_Pricing */ private $plugin; /** * 营销设置 * * @var array */ private $settings; /** * 通知队列 * * @var array */ private $notification_queue = array(); /** * 营销统计缓存 * * @var array */ private $stats_cache = array(); /** * 构造函数 * * @param BDFG_Dynamic_Pricing $plugin */ public function __construct($plugin) { $this->plugin = $plugin; $this->settings = get_option('bdfg_marketing_settings', array()); $this->init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 前端显示 add_action('wp_enqueue_scripts', array($this, 'enqueue_marketing_assets')); add_action('woocommerce_before_single_product', array($this, 'display_countdown_timer')); add_action('woocommerce_before_add_to_cart_form', array($this, 'display_stock_countdown')); add_filter('woocommerce_get_price_html', array($this, 'add_social_share_discount_notice'), 10, 2); // AJAX处理 add_action('wp_ajax_bdfg_subscribe_discount', array($this, 'handle_subscription_discount')); add_action('wp_ajax_nopriv_bdfg_subscribe_discount', array($this, 'handle_subscription_discount')); add_action('wp_ajax_bdfg_record_share', array($this, 'handle_social_share')); add_action('wp_ajax_nopriv_bdfg_record_share', array($this, 'handle_social_share')); // 通知系统 add_action('init', array($this, 'schedule_notification_events')); add_action('bdfg_process_notifications', array($this, 'process_notification_queue')); add_action('bdfg_daily_cleanup', array($this, 'cleanup_old_notifications')); // 管理界面 if (is_admin()) { add_action('admin_menu', array($this, 'add_marketing_menu')); add_action('admin_init', array($this, 'register_marketing_settings')); } } /** * 加载营销相关资源 */ public function enqueue_marketing_assets() { if (!$this->should_load_assets()) { return; } wp_enqueue_style( 'bdfg-marketing', BDFG_PLUGIN_URL . 'assets/css/marketing.css', array(), BDFG_VERSION ); wp_enqueue_script( 'bdfg-marketing', BDFG_PLUGIN_URL . 'assets/js/marketing.js', array('jquery'), BDFG_VERSION, true ); wp_localize_script('bdfg-marketing', 'bdfgMarketing', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('bdfg-marketing-nonce'), 'i18n' => $this->get_js_translations() )); } /** * 显示倒计时计时器 */ public function display_countdown_timer() { if (!$this->is_countdown_enabled()) { return; } global $product; if (!$product) { return; } $discount_rules = $this->get_active_discount_rules($product->get_id()); if (empty($discount_rules)) { return; } foreach ($discount_rules as $rule) { if (!empty($rule->end_date) && strtotime($rule->end_date) > current_time('timestamp')) { $this->render_countdown_timer($rule); break; // 只显示第一个有效的倒计时 } } } /** * 渲染倒计时计时器 * * @param object $rule */ private function render_countdown_timer($rule) { $template = $this->get_template('countdown-timer.php'); if ($template) { include $template; } else { // 备用内联模板 ?> <div class="bdfg-countdown-timer" data-end="<?php echo esc_attr($rule->end_date); ?>" data-discount="<?php echo esc_attr($rule->discount_amount); ?>" data-type="<?php echo esc_attr($rule->discount_type); ?>"> <div class="timer-title"> <?php esc_html_e('Limited Time Offer!', 'bdfg-dynamic-pricing'); ?> </div> <div class="timer-blocks"></div> </div> <?php } } /** * 显示库存倒计时 */ public function display_stock_countdown() { if (!$this->is_stock_countdown_enabled()) { return; } global $product; if (!$product || !$product->managing_stock()) { return; } $stock = $product->get_stock_quantity(); $threshold = $this->get_stock_threshold(); if ($stock <= $threshold) { $this->render_stock_countdown($stock, $threshold); } } /** * 处理订阅折扣 */ public function handle_subscription_discount() { check_ajax_referer('bdfg-marketing-nonce', 'nonce'); $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : ''; if (!is_email($email)) { wp_send_json_error(array( 'message' => __('Invalid email address.', 'bdfg-dynamic-pricing') )); } // 检查是否已订阅 if ($this->is_email_subscribed($email)) { wp_send_json_error(array( 'message' => __('This email is already subscribed.', 'bdfg-dynamic-pricing') )); } // 生成优惠券 $coupon_code = $this->generate_subscription_coupon($email); if (!$coupon_code) { wp_send_json_error(array( 'message' => __('Error generating coupon.', 'bdfg-dynamic-pricing') )); } // 保存订阅者信息 $this->save_subscriber($email, $coupon_code); // 发送欢迎邮件 $this->send_welcome_email($email, $coupon_code); wp_send_json_success(array( 'message' => __('Thank you for subscribing! Check your email for your discount code.', 'bdfg-dynamic-pricing'), 'coupon_code' => $coupon_code )); } /** * 处理社交分享 */ public function handle_social_share() { check_ajax_referer('bdfg-marketing-nonce', 'nonce'); $product_id = isset($_POST['product_id']) ? absint($_POST['product_id']) : 0; $network = isset($_POST['network']) ? sanitize_text_field($_POST['network']) : ''; if (!$product_id || !$network) { wp_send_json_error(__('Invalid request.', 'bdfg-dynamic-pricing')); } // 记录分享 $this->record_social_share($product_id, $network); // 获取分享折扣 $discount = $this->get_share_discount($product_id); wp_send_json_success(array( 'message' => sprintf( __('Thanks for sharing! Use code %s for %s off.', 'bdfg-dynamic-pricing'), $discount['code'], $discount['amount'] ), 'discount' => $discount )); } /** * 生成订阅优惠券 * * @param string $email * @return string|bool */ private function generate_subscription_coupon($email) { $coupon_code = 'BDFG_' . strtoupper(substr(md5($email . time()), 0, 8)); $coupon = array( 'post_title' => $coupon_code, 'post_content' => '', 'post_status' => 'publish', 'post_author' => 1, 'post_type' => 'shop_coupon' ); $coupon_id = wp_insert_post($coupon); if (!$coupon_id) { return false; } // 设置优惠券元数据 update_post_meta($coupon_id, 'discount_type', 'percent'); update_post_meta($coupon_id, 'coupon_amount', $this->get_subscription_discount_amount()); update_post_meta($coupon_id, 'individual_use', 'yes'); update_post_meta($coupon_id, 'usage_limit', 1); update_post_meta($coupon_id, 'expiry_date', date('Y-m-d', strtotime('+30 days'))); update_post_meta($coupon_id, 'email', $email); return $coupon_code; } /** * 发送欢迎邮件 * * @param string $email * @param string $coupon_code */ private function send_welcome_email($email, $coupon_code) { $template = $this->get_email_template('welcome.php', array( 'coupon_code' => $coupon_code, 'expiry_date' => date('Y-m-d', strtotime('+30 days')) )); $subject = sprintf( __('Welcome to %s - Here\'s Your Discount Code!', 'bdfg-dynamic-pricing'), get_bloginfo('name') ); $headers = array('Content-Type: text/html; charset=UTF-8'); wp_mail($email, $subject, $template, $headers); } /** * 保存订阅者信息 * * @param string $email * @param string $coupon_code */ private function save_subscriber($email, $coupon_code) { global $wpdb; $wpdb->insert( $wpdb->prefix . 'bdfg_subscribers', array( 'email' => $email, 'coupon_code' => $coupon_code, 'subscribed_date' => current_time('mysql'), 'status' => 'active' ), array('%s', '%s', '%s', '%s') ); } /** * 获取JavaScript翻译 * * @return array */ private function get_js_translations() { return array( 'days' => __('Days', 'bdfg-dynamic-pricing'), 'hours' => __('Hours', 'bdfg-dynamic-pricing'), 'minutes' => __('Minutes', 'bdfg-dynamic-pricing'), 'seconds' => __('Seconds', 'bdfg-dynamic-pricing'), 'share_discount' => __('Share to get %s off!', 'bdfg-dynamic-pricing'), 'subscribe_success' => __('Thank you for subscribing!', 'bdfg-dynamic-pricing'), 'error_occurred' => __('An error occurred. Please try again.', 'bdfg-dynamic-pricing') ); } /** * 检查是否应该加载营销资源 * * @return bool */ private function should_load_assets() { return is_product() || is_shop() || is_product_category() || is_cart() || is_checkout(); } /** * 获取模板文件路径 * * @param string $template * @return string */ private function get_template($template) { $template_path = locate_template('bdfg/' . $template); if (!$template_path) { $template_path = BDFG_PLUGIN_DIR . 'templates/' . $template; } return file_exists($template_path) ? $template_path : false; } /** * 清理旧通知 */ public function cleanup_old_notifications() { global $wpdb; $wpdb->query($wpdb->prepare( "DELETE FROM {$wpdb->prefix}bdfg_notifications WHERE created_at < DATE_SUB(%s, INTERVAL 30 DAY)", current_time('mysql') )); } }
includes/class-bdfg-autoloader.php
相关文章: WooCommerce 产品比较工具
<?php /** * BDFG Dynamic Pricing - Autoloader * * 自动加载插件类文件 * * @package BDFG_Dynamic_Pricing * @since 2.0.0 */ defined('ABSPATH') || exit; class BDFG_Autoloader { /** * 类映射缓存 * * @var array */ private static $class_map = array(); /** * 注册自动加载器 */ public static function register() { spl_autoload_register(array(__CLASS__, 'autoload')); } /** * 自动加载类文件 * * @param string $class 完整的类名 */ public static function autoload($class) { if (0 !== strpos($class, 'BDFG_')) { return; } $file = self::get_file_name_from_class($class); // 检查缓存 if (isset(self::$class_map[$class])) { $file = self::$class_map[$class]; if (file_exists($file)) { require_once $file; return; } } // 常见的类文件位置 $locations = array( BDFG_PLUGIN_DIR . 'includes/', BDFG_PLUGIN_DIR . 'includes/admin/', BDFG_PLUGIN_DIR . 'includes/marketing/', BDFG_PLUGIN_DIR . 'includes/integrations/' ); foreach ($locations as $location) { if (file_exists($location . $file)) { self::$class_map[$class] = $location . $file; require_once $location . $file; return; } } } /** * 从类名生成文件名 * * @param string $class 类名 * @return string */ private static function get_file_name_from_class($class) { return 'class-' . str_replace('_', '-', strtolower($class)) . '.php'; } } BDFG_Autoloader::register();
includes/class-bdfg-installer.php
<?php /** * BDFG Dynamic Pricing - Installer * * 处理插件的安装和更新 * * @package BDFG_Dynamic_Pricing * @since 2.0.0 */ defined('ABSPATH') || exit; class BDFG_Installer { /** * 数据库版本选项名 */ const DB_VERSION_OPTION = 'bdfg_db_version'; /** * 安装插件 */ public static function install() { if (!is_blog_installed()) { return; } // 检查权限 if (!current_user_can('activate_plugins')) { return; } // 获取当前数据库版本 $current_db_version = get_option(self::DB_VERSION_OPTION, '0.0.0'); // 创建必要的数据表 self::create_tables(); // 安装默认数据 self::install_default_data(); // 添加定时任务 self::schedule_tasks(); // 更新数据库版本 update_option(self::DB_VERSION_OPTION, BDFG_VERSION); // 清理缓存 wp_cache_flush(); } /** * 创建数据表 */ private static function create_tables() { global $wpdb; $wpdb->hide_errors(); require_once ABSPATH . 'wp-admin/includes/upgrade.php'; // 折扣规则表 $sql = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}bdfg_discount_rules ( rule_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, rule_name VARCHAR(255) NOT NULL, rule_type VARCHAR(50) NOT NULL, discount_type VARCHAR(50) NOT NULL, discount_amount DECIMAL(10,2) NOT NULL, start_date DATETIME NULL, end_date DATETIME NULL, conditions LONGTEXT NULL, priority INT UNSIGNED DEFAULT 10, status VARCHAR(20) DEFAULT 'active', created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY (rule_id), KEY rule_status (status), KEY rule_dates (start_date, end_date) ) {$wpdb->get_charset_collate()};"; // 统计数据表 $sql .= "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}bdfg_statistics ( stat_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, rule_id BIGINT UNSIGNED NOT NULL, product_id BIGINT UNSIGNED NOT NULL, order_id BIGINT UNSIGNED NOT NULL, discount_amount DECIMAL(10,2) NOT NULL, customer_id BIGINT UNSIGNED NULL, applied_date DATETIME NOT NULL, PRIMARY KEY (stat_id), KEY rule_id (rule_id), KEY product_id (product_id), KEY order_id (order_id) ) {$wpdb->get_charset_collate()};"; // 订阅者表 $sql .= "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}bdfg_subscribers ( subscriber_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, email VARCHAR(255) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'active', subscribed_date DATETIME NOT NULL, preferences TEXT NULL, PRIMARY KEY (subscriber_id), UNIQUE KEY email (email) ) {$wpdb->get_charset_collate()};"; dbDelta($sql); } /** * 安装默认数据 */ private static function install_default_data() { // 添加默认设置 $default_settings = array( 'general' => array( 'enable_dynamic_pricing' => 'yes', 'price_display_format' => 'both_prices', 'sale_badge_text' => __('Sale!', 'bdfg-dynamic-pricing'), ), 'marketing' => array( 'enable_marketing_features' => 'yes', 'countdown_timer' => 'yes', 'stock_countdown' => 'yes', 'social_share_discount' => 'yes', ), 'advanced' => array( 'cache_duration' => 3600, 'debug_mode' => 'no', 'clean_on_uninstall' => 'no', ), ); update_option('bdfg_settings', $default_settings); // 添加默认折扣规则 $default_rule = array( 'rule_name' => __('Welcome Discount', 'bdfg-dynamic-pricing'), 'rule_type' => 'cart', 'discount_type' => 'percentage', 'discount_amount' => 10.00, 'status' => 'active', 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql'), ); self::add_default_rule($default_rule); } /** * 添加默认规则 * * @param array $rule */ private static function add_default_rule($rule) { global $wpdb; $wpdb->insert( $wpdb->prefix . 'bdfg_discount_rules', $rule, array( '%s', '%s', '%s', '%f', '%s', '%s', '%s' ) ); } /** * 设置定时任务 */ private static function schedule_tasks() { if (!wp_next_scheduled('bdfg_daily_maintenance')) { wp_schedule_event(time(), 'daily', 'bdfg_daily_maintenance'); } if (!wp_next_scheduled('bdfg_cleanup_old_statistics')) { wp_schedule_event(time(), 'weekly', 'bdfg_cleanup_old_statistics'); } } /** * 更新插件 */ public static function update() { $current_version = get_option(self::DB_VERSION_OPTION, '0.0.0'); if (version_compare($current_version, '2.0.0', '<')) { self::update_to_2_0_0(); } if (version_compare($current_version, '2.1.0', '<')) { self::update_to_2_1_0(); } // 更新数据库版本 update_option(self::DB_VERSION_OPTION, BDFG_VERSION); } /** * 更新到2.0.0版本 */ private static function update_to_2_0_0() { global $wpdb; // 添加新的数据库字段 $wpdb->query("ALTER TABLE {$wpdb->prefix}bdfg_discount_rules ADD COLUMN conditions LONGTEXT NULL AFTER discount_amount"); } /** * 更新到2.1.0版本 */ private static function update_to_2_1_0() { global $wpdb; // 添加优先级字段 $wpdb->query("ALTER TABLE {$wpdb->prefix}bdfg_discount_rules ADD COLUMN priority INT UNSIGNED DEFAULT 10 AFTER conditions"); } }
includes/admin/class-bdfg-admin.php
相关文章: WordPress 地图定位插件
<?php /** * BDFG Dynamic Pricing - Admin * * 处理后台管理界面 * * @package BDFG_Dynamic_Pricing * @subpackage Admin * @since 2.0.0 */ defined('ABSPATH') || exit; class BDFG_Admin { /** * 父插件实例 * * @var BDFG_Dynamic_Pricing */ private $plugin; /** * 当前活动的选项卡 * * @var string */ private $active_tab = ''; /** * 构造函数 * * @param BDFG_Dynamic_Pricing $plugin */ public function __construct($plugin) { $this->plugin = $plugin; // 添加菜单 add_action('admin_menu', array($this, 'add_admin_menu')); // 注册设置 add_action('admin_init', array($this, 'register_settings')); // 添加插件操作链接 add_filter('plugin_action_links_' . BDFG_PLUGIN_BASENAME, array($this, 'add_plugin_action_links')); // 加载管理界面资源 add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets')); } /** * 添加管理菜单 */ public function add_admin_menu() { add_menu_page( __('BDFG Dynamic Pricing', 'bdfg-dynamic-pricing'), __('Dynamic Pricing', 'bdfg-dynamic-pricing'), 'manage_woocommerce', 'bdfg-dynamic-pricing', array($this, 'render_admin_page'), 'dashicons-tag', 58 ); add_submenu_page( 'bdfg-dynamic-pricing', __('Settings', 'bdfg-dynamic-pricing'), __('Settings', 'bdfg-dynamic-pricing'), 'manage_woocommerce', 'bdfg-settings', array($this, 'render_settings_page') ); add_submenu_page( 'bdfg-dynamic-pricing', __('Pricing Rules', 'bdfg-dynamic-pricing'), __('Pricing Rules', 'bdfg-dynamic-pricing'), 'manage_woocommerce', 'bdfg-pricing-rules', array($this, 'render_pricing_rules_page') ); } /** * 注册插件设置 */ public function register_settings() { register_setting( 'bdfg_settings', 'bdfg_settings', array($this, 'validate_settings') ); // 常规设置 add_settings_section( 'bdfg_general_settings', __('General Settings', 'bdfg-dynamic-pricing'), array($this, 'render_general_settings_section'), 'bdfg-settings' ); // 营销设置 add_settings_section( 'bdfg_marketing_settings', __('Marketing Settings', 'bdfg-dynamic-pricing'), array($this, 'render_marketing_settings_section'), 'bdfg-settings' ); // 高级设置 add_settings_section( 'bdfg_advanced_settings', __('Advanced Settings', 'bdfg-dynamic-pricing'), array($this, 'render_advanced_settings_section'), 'bdfg-settings' ); } /** * 加载管理界面资源 */ public function enqueue_admin_assets($hook) { if (!$this->is_plugin_page($hook)) { return; } wp_enqueue_style( 'bdfg-admin-style', BDFG_PLUGIN_URL . 'assets/css/admin.css', array(), BDFG_VERSION ); wp_enqueue_script( 'bdfg-admin-script', BDFG_PLUGIN_URL . 'assets/js/admin.js', array('jquery', 'jquery-ui-datepicker', 'wp-util'), BDFG_VERSION, true ); wp_localize_script('bdfg-admin-script', 'bdfgAdmin', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('bdfg-admin-nonce'), 'i18n' => $this->get_admin_translations() )); } /** * 获取管理界面翻译 * * @return array */ private function get_admin_translations() { return array( 'confirm_delete' => __('Are you sure you want to delete this rule?', 'bdfg-dynamic-pricing'), 'changes_saved' => __('Changes saved successfully.', 'bdfg-dynamic-pricing'), 'error_saving' => __('Error saving changes.', 'bdfg-dynamic-pricing'), 'loading' => __('Loading...', 'bdfg-dynamic-pricing'), 'no_rules' => __('No pricing rules found.', 'bdfg-dynamic-pricing'), ); } /** * 检查是否在插件页面 * * @param string $hook * @return bool */ private function is_plugin_page($hook) { $plugin_pages = array( 'toplevel_page_bdfg-dynamic-pricing', 'dynamic-pricing_page_bdfg-settings', 'dynamic-pricing_page_bdfg-pricing-rules' ); return in_array($hook, $plugin_pages); } /** * 渲染管理主页 */ public function render_admin_page() { $this->active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'dashboard'; ?> <div class="wrap bdfg-admin"> <h1> <?php echo esc_html__('BDFG Dynamic Pricing', 'bdfg-dynamic-pricing'); ?> <a href="<?php echo esc_url(admin_url('admin.php?page=bdfg-pricing-rules&action=new')); ?>" class="page-title-action"> <?php echo esc_html__('Add New Rule', 'bdfg-dynamic-pricing'); ?> </a> </h1> <?php $this->render_tabs(); ?> <div class="bdfg-admin-content"> <?php switch ($this->active_tab) { case 'dashboard': $this->render_dashboard(); break; case 'reports': $this->render_reports(); break; default: do_action('bdfg_admin_tab_content_' . $this->active_tab); break; } ?> </div> </div> <?php } /** * 渲染管理标签页 */ private function render_tabs() { $tabs = array( 'dashboard' => __('Dashboard', 'bdfg-dynamic-pricing'), 'reports' => __('Reports', 'bdfg-dynamic-pricing'), ); $tabs = apply_filters('bdfg_admin_tabs', $tabs); ?> <h2 class="nav-tab-wrapper"> <?php foreach ($tabs as $tab => $label) { $active_class = ($this->active_tab === $tab) ? 'nav-tab-active' : ''; $url = add_query_arg('tab', $tab); ?> <a href="<?php echo esc_url($url); ?>" class="nav-tab <?php echo esc_attr($active_class); ?>"> <?php echo esc_html($label); ?> </a> <?php } ?> </h2> <?php } /** * 渲染仪表盘 */ private function render_dashboard() { $active_rules = $this->get_active_rules_count(); $total_savings = $this->get_total_savings_this_month(); $popular_rules = $this->get_popular_rules(); ?> <div class="bdfg-dashboard-widgets"> <div class="bdfg-widget"> <h3><?php esc_html_e('Active Rules', 'bdfg-dynamic-pricing'); ?></h3> <div class="bdfg-widget-content"> <span class="bdfg-big-number"><?php echo esc_html($active_rules); ?></span> </div> </div> <div class="bdfg-widget"> <h3><?php esc_html_e('Total Savings This Month', 'bdfg-dynamic-pricing'); ?></h3> <div class="bdfg-widget-content"> <span class="bdfg-big-number"><?php echo wc_price($total_savings); ?></span> </div> </div> <div class="bdfg-widget bdfg-widget-full"> <h3><?php esc_html_e('Popular Rules', 'bdfg-dynamic-pricing'); ?></h3> <div class="bdfg-widget-content"> <?php if ($popular_rules) : ?> <table class="widefat"> <thead> <tr> <th><?php esc_html_e('Rule', 'bdfg-dynamic-pricing'); ?></th> <th><?php esc_html_e('Uses', 'bdfg-dynamic-pricing'); ?></th> <th><?php esc_html_e('Total Savings', 'bdfg-dynamic-pricing'); ?></th> </tr> </thead> <tbody> <?php foreach ($popular_rules as $rule) : ?> <tr> <td><?php echo esc_html($rule->rule_name); ?></td> <td><?php echo esc_html($rule->uses); ?></td> <td><?php echo wc_price($rule->total_savings); ?></td> </tr> <?php endforeach; ?> </tbody> </table> <?php else : ?> <p><?php esc_html_e('No data available yet.', 'bdfg-dynamic-pricing'); ?></p> <?php endif; ?> </div> </div> </div> <?php } /** * 获取活动规则数量 * * @return int */ private function get_active_rules_count() { global $wpdb; return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}bdfg_discount_rules WHERE status = 'active'" ); } /** * 获取本月总节省金额 * * @return float */ private function get_total_savings_this_month() { global $wpdb; $first_day = date('Y-m-01 00:00:00'); $last_day = date('Y-m-t 23:59:59'); return (float) $wpdb->get_var($wpdb->prepare( "SELECT SUM(discount_amount) FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date BETWEEN %s AND %s", $first_day, $last_day )); } /** * 获取最受欢迎的规则 * * @return array */ private function get_popular_rules() { global $wpdb; return $wpdb->get_results( "SELECT r.rule_name, COUNT(s.stat_id) as uses, SUM(s.discount_amount) as total_savings FROM {$wpdb->prefix}bdfg_discount_rules r LEFT JOIN {$wpdb->prefix}bdfg_statistics s ON r.rule_id = s.rule_id GROUP BY r.rule_id ORDER BY uses DESC LIMIT 5" ); } }
assets/css/marketing.css
/* BDFG Dynamic Pricing Marketing Styles */ .bdfg-countdown-timer { background: #f7f7f7; padding: 15px; border-radius: 4px; margin-bottom: 20px; text-align: center; border: 1px solid #e5e5e5; } .bdfg-countdown-timer .timer-block { display: inline-block; margin: 0 10px; text-align: center; min-width: 60px; } .bdfg-countdown-timer .timer-number { font-size: 24px; font-weight: bold; color: #e94444; display: block; } .bdfg-countdown-timer .timer-label { font-size: 12px; color: #666; text-transform: uppercase; } .bdfg-stock-countdown { margin: 15px 0; padding: 10px; background: #fff8e5; border: 1px solid #ffe5b2; border-radius: 3px; } .bdfg-stock-countdown .stock-count { color: #d63638; font-weight: bold; } .bdfg-stock-countdown .progress-bar { height: 10px; background: #f0f0f0; border-radius: 5px; margin-top: 8px; overflow: hidden; } .bdfg-stock-countdown .progress { height: 100%; background: #4caf50; border-radius: 5px; transition: width 0.3s ease; } .bdfg-social-share { margin: 20px 0; padding: 15px; background: #e9f7ff; border: 1px solid #b3e0ff; border-radius: 4px; text-align: center; } .bdfg-social-share .share-buttons { margin-top: 10px; } .bdfg-social-share .share-button { display: inline-block; padding: 8px 15px; margin: 0 5px; border-radius: 3px; color: #fff; text-decoration: none; font-size: 14px; } .bdfg-social-share .share-facebook { background: #3b5998; } .bdfg-social-share .share-twitter { background: #1da1f2; } .bdfg-notification { position: fixed; bottom: 20px; right: 20px; padding: 15px 20px; background: #fff; box-shadow: 0 2px 10px rgba(0,0,0,0.1); border-left: 4px solid #4caf50; border-radius: 3px; z-index: 9999; animation: slideIn 0.3s ease; } @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* 响应式设计 */ @media screen and (max-width: 768px) { .bdfg-countdown-timer .timer-block { margin: 5px; min-width: 50px; } .bdfg-countdown-timer .timer-number { font-size: 20px; } .bdfg-social-share .share-button { display: block; margin: 5px 0; } }
assets/js/marketing.js
相关文章: WooCommerce 客户分析报告插件
/** * BDFG Dynamic Pricing Marketing Scripts * * @package BDFG_Dynamic_Pricing */ (function($) { 'use strict'; var BDFG_Marketing = { /** * 初始化 */ init: function() { this.initCountdownTimers(); this.initStockCountdown(); this.initSocialShare(); this.initSubscriptionForm(); }, /** * 初始化倒计时计时器 */ initCountdownTimers: function() { $('.bdfg-countdown-timer').each(function() { var $timer = $(this); var endDate = new Date($timer.data('end')).getTime(); var updateTimer = function() { var now = new Date().getTime(); var distance = endDate - now; if (distance < 0) { clearInterval(interval); $timer.html(bdfgMarketing.i18n.expired); return; } var days = Math.floor(distance / (1000 * 60 * 60 * 24)); var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); var seconds = Math.floor((distance % (1000 * 60)) / 1000); $timer.html( '<div class="timer-block">' + '<span class="timer-number">' + days + '</span>' + '<span class="timer-label">' + bdfgMarketing.i18n.days + '</span>' + '</div>' + '<div class="timer-block">' + '<span class="timer-number">' + hours + '</span>' + '<span class="timer-label">' + bdfgMarketing.i18n.hours + '</span>' + '</div>' + '<div class="timer-block">' + '<span class="timer-number">' + minutes + '</span>' + '<span class="timer-label">' + bdfgMarketing.i18n.minutes + '</span>' + '</div>' + '<div class="timer-block">' + '<span class="timer-number">' + seconds + '</span>' + '<span class="timer-label">' + bdfgMarketing.i18n.seconds + '</span>' + '</div>' ); }; updateTimer(); var interval = setInterval(updateTimer, 1000); }); }, /** * 初始化库存倒计时 */ initStockCountdown: function() { $('.bdfg-stock-countdown').each(function() { var $container = $(this); var stock = parseInt($container.data('stock'), 10); var threshold = parseInt($container.data('threshold'), 10); var percentage = Math.min((stock / threshold) * 100, 100); $container.find('.progress').css('width', percentage + '%'); }); }, /** * 初始化社交分享 */ initSocialShare: function() { $('.bdfg-share-button').on('click', function(e) { e.preventDefault(); var url = $(this).data('share-url'); var network = $(this).data('network'); var width = 600; var height = 400; var left = (screen.width/2)-(width/2); var top = (screen.height/2)-(height/2); window.open(url, network + '_share', 'toolbar=no, location=no, directories=no, status=no, menubar=no, ' + 'scrollbars=no, resizable=no, copyhistory=no, width=' + width + ', height=' + height + ', top=' + top + ', left=' + left ); // 记录分享 $.post(bdfgMarketing.ajax_url, { action: 'bdfg_record_share',nonce: bdfgMarketing.nonce, network: network, product_id: $(this).data('product-id') }, function(response) { if (response.success) { BDFG_Marketing.showNotification(response.data.message); } }); }); }, /** * 初始化订阅表单 */ initSubscriptionForm: function() { $('#bdfg-subscription-form').on('submit', function(e) { e.preventDefault(); var $form = $(this); var $submit = $form.find('button[type="submit"]'); var originalText = $submit.text(); $submit.prop('disabled', true).text(bdfgMarketing.i18n.processing); $.post(bdfgMarketing.ajax_url, { action: 'bdfg_subscribe_discount', nonce: bdfgMarketing.nonce, email: $form.find('input[name="email"]').val() }, function(response) { if (response.success) { BDFG_Marketing.showNotification(response.data.message); $form.find('.bdfg-coupon-code').text(response.data.coupon_code).show(); $form[0].reset(); } else { BDFG_Marketing.showNotification(response.data.message, 'error'); } $submit.prop('disabled', false).text(originalText); }); }); }, /** * 显示通知 * * @param {string} message 消息内容 * @param {string} type 通知类型 (success|error) */ showNotification: function(message, type) { type = type || 'success'; var $notification = $('<div/>', { 'class': 'bdfg-notification bdfg-notification-' + type, 'text': message }); $('body').append($notification); setTimeout(function() { $notification.fadeOut(300, function() { $(this).remove(); }); }, 3000); } }; // DOM 加载完成后初始化 $(function() { BDFG_Marketing.init(); }); })(jQuery);
assets/css/admin.css
/* BDFG Dynamic Pricing Admin Styles */ .bdfg-admin { margin: 20px 0; } .bdfg-admin .bdfg-header { background: #fff; padding: 20px; margin-bottom: 20px; border: 1px solid #e5e5e5; border-radius: 3px; display: flex; align-items: center; justify-content: space-between; } .bdfg-admin .bdfg-logo { max-width: 200px; height: auto; } .bdfg-dashboard-widgets { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px; } .bdfg-widget { background: #fff; border: 1px solid #e5e5e5; border-radius: 3px; padding: 20px; } .bdfg-widget-full { grid-column: 1 / -1; } .bdfg-widget h3 { margin: 0 0 15px; padding-bottom: 10px; border-bottom: 1px solid #eee; color: #23282d; } .bdfg-big-number { font-size: 36px; font-weight: bold; color: #2271b1; } .bdfg-rules-table { width: 100%; border-spacing: 0; } .bdfg-rules-table th { text-align: left; padding: 10px; background: #f8f9fa; border-bottom: 2px solid #e5e5e5; } .bdfg-rules-table td { padding: 12px 10px; border-bottom: 1px solid #e5e5e5; } .bdfg-rules-table tr:hover { background: #f8f9fa; } .bdfg-status-badge { display: inline-block; padding: 3px 8px; border-radius: 3px; font-size: 12px; font-weight: 500; } .bdfg-status-active { background: #edf7ed; color: #2e7d32; } .bdfg-status-inactive { background: #fef6f6; color: #d32f2f; } .bdfg-form-row { margin-bottom: 20px; } .bdfg-form-row label { display: block; margin-bottom: 5px; font-weight: 500; } .bdfg-form-row input[type="text"], .bdfg-form-row input[type="number"], .bdfg-form-row select, .bdfg-form-row textarea { width: 100%; max-width: 400px; } .bdfg-help-tip { color: #666; font-size: 13px; font-style: italic; margin-top: 5px; } /* 响应式设计 */ @media screen and (max-width: 782px) { .bdfg-dashboard-widgets { grid-template-columns: 1fr; } .bdfg-rules-table { display: block; overflow-x: auto; } }
templates/emails/welcome.php
<?php /** * 订阅欢迎邮件模板 * * @package BDFG_Dynamic_Pricing * @version 2.3.0 */ defined('ABSPATH') || exit; ?> <!DOCTYPE html> <html lang="<?php echo get_locale(); ?>"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php echo get_bloginfo('name'); ?></title> </head> <body style="background-color: #f7f7f7; margin: 0; padding: 0; font-family: Arial, sans-serif;"> <table width="100%" cellpadding="0" cellspacing="0" style="max-width: 600px; margin: 0 auto; background-color: #ffffff;"> <tr> <td style="padding: 40px 30px; text-align: center;"> <img src="<?php echo BDFG_PLUGIN_URL; ?>assets/images/logo.png" alt="<?php echo get_bloginfo('name'); ?>" style="max-width: 200px;"> </td> </tr> <tr> <td style="padding: 0 30px 30px;"> <h1 style="color: #333333; font-size: 24px; margin-bottom: 20px;"> <?php esc_html_e('Welcome to our community!', 'bdfg-dynamic-pricing'); ?> </h1> <p style="color: #666666; font-size: 16px; line-height: 1.5;"> <?php esc_html_e('Thank you for subscribing to our newsletter. As a welcome gift, here\'s your exclusive discount code:', 'bdfg-dynamic-pricing'); ?> </p> <div style="background-color: #f5f5f5; padding: 20px; text-align: center; margin: 20px 0;"> <span style="font-size: 24px; font-weight: bold; color: #e94444;"> <?php echo esc_html($coupon_code); ?> </span> </div> <p style="color: #666666; font-size: 16px; line-height: 1.5;"> <?php esc_html_e('Use this code during checkout to get 10% off your first order. This code will expire in 30 days.', 'bdfg-dynamic-pricing'); ?> </p> <div style="text-align: center; margin-top: 30px;"> <a href="<?php echo esc_url(wc_get_page_permalink('shop')); ?>" style="display: inline-block; padding: 15px 25px; background-color: #2271b1; color: #ffffff; text-decoration: none; border-radius: 3px;"> <?php esc_html_e('Start Shopping', 'bdfg-dynamic-pricing'); ?> </a> </div> </td> </tr> <tr> <td style="background-color: #f7f7f7; padding: 20px 30px; text-align: center; color: #666666; font-size: 14px;"> <p> <?php echo sprintf( esc_html__('Follow us on %1$s and %2$s for more updates and special offers!', 'bdfg-dynamic-pricing'), '<a href="https://facebook.com/beiduofengou" style="color: #2271b1; text-decoration: none;">Facebook</a>', '<a href="https://twitter.com/beiduofengou" style="color: #2271b1; text-decoration: none;">Twitter</a>' ); ?> </p> <p style="margin-top: 10px;"> © <?php echo date('Y'); ?> <?php echo get_bloginfo('name'); ?>. <?php esc_html_e('All rights reserved.', 'bdfg-dynamic-pricing'); ?> </p> </td> </tr> </table> </body> </html>
includes/api/class-bdfg-api.php
<?php /** * BDFG Dynamic Pricing - API * * 处理REST API请求和外部集成 * * @package BDFG_Dynamic_Pricing * @subpackage API * @since 2.3.0 * @author BeiDuoFengOu */ defined('ABSPATH') || exit; class BDFG_API { /** * API版本 */ const VERSION = 'v1'; /** * API命名空间 */ const NAMESPACE = 'bdfg/v1'; /** * 构造函数 */ public function __construct() { add_action('rest_api_init', array($this, 'register_routes')); } /** * 注册API路由 */ public function register_routes() { register_rest_route(self::NAMESPACE, '/rules', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array($this, 'get_rules'), 'permission_callback' => array($this, 'check_permission'), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array($this, 'create_rule'), 'permission_callback' => array($this, 'check_permission'), 'args' => $this->get_rule_schema(), ), )); register_rest_route(self::NAMESPACE, '/rules/(?P<id>\d+)', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array($this, 'get_rule'), 'permission_callback' => array($this, 'check_permission'), ), array( 'methods' => WP_REST_Server::EDITABLE, 'callback' => array($this, 'update_rule'), 'permission_callback' => array($this, 'check_permission'), 'args' => $this->get_rule_schema(), ), array( 'methods' => WP_REST_Server::DELETABLE, 'callback' => array($this, 'delete_rule'), 'permission_callback' => array($this, 'check_permission'), ), )); register_rest_route(self::NAMESPACE, '/statistics', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => array($this, 'get_statistics'), 'permission_callback' => array($this, 'check_permission'), ), )); } /** * 检查API权限 * * @param WP_REST_Request $request * @return bool|WP_Error */ public function check_permission($request) { if (!current_user_can('manage_woocommerce')) { return new WP_Error( 'bdfg_rest_forbidden', __('Sorry, you are not allowed to access this endpoint.', 'bdfg-dynamic-pricing'), array('status' => rest_authorization_required_code()) ); } return true; } /** * 获取所有规则 * * @param WP_REST_Request $request * @return WP_REST_Response */ public function get_rules($request) { global $wpdb; $page = $request->get_param('page') ?: 1; $per_page = $request->get_param('per_page') ?: 10; $offset = ($page - 1) * $per_page; $rules = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bdfg_discount_rules ORDER BY priority ASC LIMIT %d OFFSET %d", $per_page, $offset )); $total = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}bdfg_discount_rules"); $response = new WP_REST_Response($rules); $response->header('X-WP-Total', $total); $response->header('X-WP-TotalPages', ceil($total / $per_page)); return $response; } /** * 获取单个规则 * * @param WP_REST_Request $request * @return WP_REST_Response|WP_Error */ public function get_rule($request) { global $wpdb; $rule_id = $request->get_param('id'); $rule = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}bdfg_discount_rules WHERE rule_id = %d", $rule_id )); if (!$rule) { return new WP_Error( 'bdfg_rule_not_found', __('Rule not found.', 'bdfg-dynamic-pricing'), array('status' => 404) ); } return new WP_REST_Response($rule); } /** * 创建新规则 * * @param WP_REST_Request $request * @return WP_REST_Response|WP_Error */ public function create_rule($request) { global $wpdb; $data = $this->prepare_rule_for_database($request); $result = $wpdb->insert( $wpdb->prefix . 'bdfg_discount_rules', $data, array('%s', '%s', '%s', '%f', '%s', '%s', '%s', '%d') ); if (!$result) { return new WP_Error( 'bdfg_db_error', __('Could not create rule.', 'bdfg-dynamic-pricing'), array('status' => 500) ); } $rule_id = $wpdb->insert_id; $rule = $this->get_rule(new WP_REST_Request('GET', array('id' => $rule_id))); return new WP_REST_Response($rule, 201); } /** * 更新规则 * * @param WP_REST_Request $request * @return WP_REST_Response|WP_Error */ public function update_rule($request) { global $wpdb; $rule_id = $request->get_param('id'); $data = $this->prepare_rule_for_database($request); $result = $wpdb->update( $wpdb->prefix . 'bdfg_discount_rules', $data, array('rule_id' => $rule_id), array('%s', '%s', '%s', '%f', '%s', '%s', '%s', '%d'), array('%d') ); if ($result === false) { return new WP_Error( 'bdfg_db_error', __('Could not update rule.', 'bdfg-dynamic-pricing'), array('status' => 500) ); } $rule = $this->get_rule($request); return new WP_REST_Response($rule); } /** * 删除规则 * * @param WP_REST_Request $request * @return WP_REST_Response|WP_Error */ public function delete_rule($request) { global $wpdb; $rule_id = $request->get_param('id'); $result = $wpdb->delete( $wpdb->prefix . 'bdfg_discount_rules', array('rule_id' => $rule_id), array('%d') ); if (!$result) { return new WP_Error( 'bdfg_db_error', __('Could not delete rule.', 'bdfg-dynamic-pricing'), array('status' => 500) ); } return new WP_REST_Response(null, 204); } /** * 获取统计数据 * * @param WP_REST_Request $request * @return WP_REST_Response */ public function get_statistics($request) { global $wpdb; $start_date = $request->get_param('start_date') ?: date('Y-m-d', strtotime('-30 days')); $end_date = $request->get_param('end_date') ?: date('Y-m-d'); $stats = $wpdb->get_results($wpdb->prepare( "SELECT DATE(applied_date) as date, COUNT(DISTINCT order_id) as order_count, SUM(discount_amount) as total_discount, AVG(discount_amount) as avg_discount FROM {$wpdb->prefix}bdfg_statistics WHERE applied_date BETWEEN %s AND %s GROUP BY DATE(applied_date) ORDER BY date DESC", $start_date, $end_date )); return new WP_REST_Response($stats); } /** * 获取规则模式 * * @return array */ private function get_rule_schema() { return array( 'rule_name' => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', ), 'rule_type' => array( 'required' => true, 'type' => 'string', 'enum' => array('product', 'cart', 'category'), ), 'discount_type' => array( 'required' => true, 'type' => 'string', 'enum' => array('percentage', 'fixed', 'bogo'), ), 'discount_amount' => array( 'required' => true, 'type' => 'number', ), 'start_date' => array( 'type' => 'string', 'format' => 'date-time', ), 'end_date' => array( 'type' => 'string', 'format' => 'date-time', ), 'conditions' => array( 'type' => 'object', ), 'priority' => array( 'type' => 'integer', 'default' => 10, ), ); } /** * 准备规则数据用于数据库操作 * * @param WP_REST_Request $request * @return array */ private function prepare_rule_for_database($request) { return array( 'rule_name' => $request->get_param('rule_name'), 'rule_type' => $request->get_param('rule_type'), 'discount_type' => $request->get_param('discount_type'), 'discount_amount' => $request->get_param('discount_amount'), 'start_date' => $request->get_param('start_date'), 'end_date' => $request->get_param('end_date'), 'conditions' => json_encode($request->get_param('conditions')), 'priority' => $request->get_param('priority'), 'updated_at' => current_time('mysql'), ); } }
includes/integrations/class-bdfg-woocommerce.php
<?php /** * BDFG Dynamic Pricing - WooCommerce Integration * * 处理与WooCommerce的集成 * * @package BDFG_Dynamic_Pricing * @subpackage Integrations * @since 2.3.0 * @author BeiDuoFengOu */ defined('ABSPATH') || exit; class BDFG_WooCommerce { /** * 父插件实例 * * @var BDFG_Dynamic_Pricing */ private $plugin; /** * 构造函数 * * @param BDFG_Dynamic_Pricing $plugin */ public function __construct($plugin) { $this->plugin = $plugin; $this->init_hooks(); } /** * 初始化钩子 */ private function init_hooks() { // 产品价格过滤器 add_filter('woocommerce_product_get_price', array($this, 'filter_product_price'), 10, 2); add_filter('woocommerce_product_get_regular_price', array($this, 'filter_product_regular_price'), 10, 2); add_filter('woocommerce_product_variation_get_price', array($this, 'filter_product_price'), 10, 2); // 购物车相关 add_action('woocommerce_before_calculate_totals', array($this, 'calculate_cart_discounts')); add_action('woocommerce_cart_item_price', array($this, 'show_cart_item_discount'), 10, 3); // 订单相关 add_action('woocommerce_checkout_order_processed', array($this, 'save_order_discounts'), 10, 3); add_action('woocommerce_order_status_completed', array($this, 'record_completed_order_stats')); // 管理界面 if (is_admin()) { add_action('woocommerce_product_options_pricing', array($this, 'add_product_pricing_fields')); add_action('woocommerce_process_product_meta', array($this, 'save_product_pricing_fields')); } } /** * 过滤产品价格 * * @param string $price * @param WC_Product $product * @return string */ public function filter_product_price($price, $product) { if (!$this->should_apply_pricing($product)) { return $price; } $discounted_price = $this->calculate_product_discount($price, $product); // 记录价格变化 $this->log_price_change($product->get_id(), $price, $discounted_price); return $discounted_price; } /** * 计算产品折扣 * * @param float $price * @param WC_Product $product * @return float */ private function calculate_product_discount($price, $product) { $rules = $this->get_applicable_rules($product); $final_price = $price; foreach ($rules as $rule) { switch ($rule['discount_type']) { case 'percentage': $discount = ($price * $rule['discount_amount']) / 100; $final_price = $price - $discount; break; case 'fixed': $final_price = $price - $rule['discount_amount']; break; case 'bogo': // BOGO逻辑在购物车中处理 break; default: $final_price = apply_filters('bdfg_custom_discount_calculation', $final_price, $price, $rule,$product ); break; } } return max(0, $final_price); } /** * 计算购物车折扣 * * @param WC_Cart $cart */ public function calculate_cart_discounts($cart) { if (!$cart || $cart->is_empty()) { return; } $cart_rules = $this->get_applicable_cart_rules(); foreach ($cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; $original_price = $product->get_price(); // 应用产品级别的折扣 $discounted_price = $this->calculate_product_discount($original_price, $product); // 应用购物车级别的折扣 foreach ($cart_rules as $rule) { $discounted_price = $this->apply_cart_rule($discounted_price, $rule, $cart_item); } $cart_item['data']->set_price($discounted_price); } // 处理BOGO优惠 $this->process_bogo_discounts($cart); } /** * 显示购物车项目折扣 * * @param string $price_html * @param array $cart_item * @param string $cart_item_key * @return string */ public function show_cart_item_discount($price_html, $cart_item, $cart_item_key) { $product = $cart_item['data']; $original_price = $product->get_regular_price(); $current_price = $product->get_price(); if ($original_price > $current_price) { $price_html = sprintf( '<del>%s</del> <ins>%s</ins>', wc_price($original_price), wc_price($current_price) ); } return $price_html; } /** * 保存订单折扣信息 * * @param int $order_id * @param array $posted_data * @param WC_Order $order */ public function save_order_discounts($order_id, $posted_data, $order) { $discounts = array(); foreach ($order->get_items() as $item) { $product = $item->get_product(); $original_price = $product->get_regular_price(); $discounted_price = $item->get_total() / $item->get_quantity(); if ($original_price > $discounted_price) { $discounts[] = array( 'product_id' => $product->get_id(), 'order_id' => $order_id, 'discount_amount' => $original_price - $discounted_price, 'rule_id' => $this->get_applied_rule_id($product->get_id()), 'applied_date' => current_time('mysql') ); } } if (!empty($discounts)) { $this->save_discount_records($discounts); } } /** * 记录已完成订单的统计数据 * * @param int $order_id */ public function record_completed_order_stats($order_id) { global $wpdb; $order = wc_get_order($order_id); if (!$order) { return; } $stats = array( 'order_id' => $order_id, 'total_discount' => $order->get_total_discount(), 'items_count' => $order->get_item_count(), 'customer_id' => $order->get_customer_id(), 'completed_date' => current_time('mysql') ); $wpdb->insert( $wpdb->prefix . 'bdfg_order_statistics', $stats, array('%d', '%f', '%d', '%d', '%s') ); } /** * 添加产品定价字段 */ public function add_product_pricing_fields() { global $product_object; echo '<div class="options_group pricing bdfg-pricing-options">'; woocommerce_wp_select(array( 'id' => '_bdfg_pricing_rule', 'label' => __('BDFG Pricing Rule', 'bdfg-dynamic-pricing'), 'options' => $this->get_pricing_rules_options(), 'desc_tip' => true, 'description' => __('Select a dynamic pricing rule to apply to this product.', 'bdfg-dynamic-pricing') )); woocommerce_wp_text_input(array( 'id' => '_bdfg_min_quantity', 'label' => __('Minimum Quantity', 'bdfg-dynamic-pricing'), 'type' => 'number', 'custom_attributes' => array( 'step' => '1', 'min' => '0' ), 'desc_tip' => true, 'description' => __('Minimum quantity required for the pricing rule to apply.', 'bdfg-dynamic-pricing') )); echo '</div>'; } /** * 保存产品定价字段 * * @param int $post_id */ public function save_product_pricing_fields($post_id) { $rule_id = isset($_POST['_bdfg_pricing_rule']) ? absint($_POST['_bdfg_pricing_rule']) : ''; $min_quantity = isset($_POST['_bdfg_min_quantity']) ? absint($_POST['_bdfg_min_quantity']) : ''; update_post_meta($post_id, '_bdfg_pricing_rule', $rule_id); update_post_meta($post_id, '_bdfg_min_quantity', $min_quantity); } /** * 获取定价规则选项 * * @return array */ private function get_pricing_rules_options() { global $wpdb; $rules = $wpdb->get_results( "SELECT rule_id, rule_name FROM {$wpdb->prefix}bdfg_discount_rules WHERE status = 'active' ORDER BY priority ASC" ); $options = array('' => __('Select a rule', 'bdfg-dynamic-pricing')); foreach ($rules as $rule) { $options[$rule->rule_id] = $rule->rule_name; } return $options; } /** * 保存折扣记录 * * @param array $discounts */ private function save_discount_records($discounts) { global $wpdb; foreach ($discounts as $discount) { $wpdb->insert( $wpdb->prefix . 'bdfg_statistics', $discount, array('%d', '%d', '%f', '%d', '%s') ); } } /** * 处理BOGO折扣 * * @param WC_Cart $cart */ private function process_bogo_discounts($cart) { $bogo_rules = $this->get_bogo_rules(); foreach ($bogo_rules as $rule) { $qualifying_items = $this->get_qualifying_items($cart, $rule); if (!empty($qualifying_items)) { $this->apply_bogo_discount($cart, $qualifying_items, $rule); } } } /** * 记录价格变化 * * @param int $product_id * @param float $old_price * @param float $new_price */ private function log_price_change($product_id, $old_price, $new_price) { if (!$this->is_logging_enabled()) { return; } global $wpdb; $wpdb->insert( $wpdb->prefix . 'bdfg_price_history', array( 'product_id' => $product_id, 'old_price' => $old_price, 'new_price' => $new_price, 'change_date' => current_time('mysql') ), array('%d', '%f', '%f', '%s') ); } /** * 检查是否启用了日志记录 * * @return bool */ private function is_logging_enabled() { $settings = get_option('bdfg_settings'); return isset($settings['general']['enable_logging']) && $settings['general']['enable_logging'] === 'yes'; } }
templates/discount-badge.php
<?php /** * 折扣标签模板 * * @package BDFG_Dynamic_Pricing * @version 2.3.0 */ defined('ABSPATH') || exit; ?> <div class="bdfg-discount-badge <?php echo esc_attr($badge_class); ?>"> <?php if ($discount_type === 'percentage'): ?> <span class="discount-amount"> <?php echo sprintf( esc_html__('Save %s%%', 'bdfg-dynamic-pricing'), number_format($discount_amount, 0) ); ?> </span> <?php else: ?> <span class="discount-amount"> <?php echo sprintf( esc_html__('Save %s', 'bdfg-dynamic-pricing'), wc_price($discount_amount) ); ?> </span> <?php endif; ?> <?php if (!empty($end_date)): ?> <span class="discount-timer" data-end="<?php echo esc_attr($end_date); ?>"> <?php esc_html_e('Ends in:', 'bdfg-dynamic-pricing'); ?> <span class="timer-content"></span> </span> <?php endif; ?> </div>
includes/class-bdfg-cache-manager.php
<?php /** * BDFG Dynamic Pricing - Cache Manager * * 处理缓存和性能优化 * * @package BDFG_Dynamic_Pricing * @since 2.3.0 * @author BeiDuoFengOu */ defined('ABSPATH') || exit; class BDFG_Cache_Manager { /** * 缓存组 */ const CACHE_GROUP = 'bdfg_dynamic_pricing'; /** * 缓存生命周期(秒) */ private $cache_ttl; /** * 构造函数 */ public function __construct() { $settings = get_option('bdfg_settings'); $this->cache_ttl = isset($settings['advanced']['cache_duration']) ? (int) $settings['advanced']['cache_duration'] : 3600; add_action('save_post_product', array($this, 'clear_product_cache'), 10, 2); add_action('woocommerce_update_product', array($this, 'clear_product_cache'), 10, 2); add_action('bdfg_rule_updated', array($this, 'clear_all_cache')); } /** * 获取缓存的数据 * * @param string $key * @return mixed */ public function get($key) { return wp_cache_get($key, self::CACHE_GROUP); } /** * 设置缓存数据 * * @param string $key * @param mixed $data * @return bool */ public function set($key, $data) { return wp_cache_set($key, $data, self::CACHE_GROUP, $this->cache_ttl); } /** * 清除特定产品的缓存 * * @param int $product_id * @param WP_Post $post */ public function clear_product_cache($product_id, $post) { wp_cache_delete('product_' . $product_id, self::CACHE_GROUP); wp_cache_delete('price_' . $product_id, self::CACHE_GROUP); wp_cache_delete('rules_' . $product_id, self::CACHE_GROUP); } /** * 清除所有缓存 */ public function clear_all_cache() { wp_cache_flush(); } /** * 生成缓存键 * * @param string $prefix * @param mixed $identifier * @return string */ public function generate_key($prefix, $identifier) { return sprintf('%s_%s', $prefix, md5(serialize($identifier))); } }