~/icsd.ir — bash
SYSTEM_ONLINE

🪝 فصل ۷: Hooks و Filters پیشرفته در ووکامرس

ووکامرس بیش از ۴۰۰ هوک اکشن و فیلتر دارد. در این فصل، حرفه‌ای‌ترین و کاربردی‌ترین آنها را برای سفارشی‌سازی فروشگاه یاد می‌گیرید.

🛒 هوک‌های سبد خرید

بررسی قبل از افزودن به سبد

// محدودیت تعداد محصول در سبد
add_filter('woocommerce_add_to_cart_validation', function($passed, $product_id, $quantity) {
    // محدودیت ۵ عدد از یک محصول
    foreach (WC()->cart->get_cart() as $item) {
        if ($item['product_id'] == $product_id) {
            if (($item['quantity'] + $quantity) > 5) {
                wc_add_notice('حداکثر ۵ عدد از این محصول می‌توانید بخرید', 'error');
                return false;
            }
        }
    }
    return $passed;
}, 10, 3);

محدودیت ترکیب محصولات

// نمی‌توان محصولات از دو دسته خاص را با هم خرید
add_filter('woocommerce_add_to_cart_validation', function($passed, $product_id) {
    $cats = wp_get_post_terms($product_id, 'product_cat', ['fields' => 'slugs']);
    
    if (!in_array('digital', $cats)) return $passed;
    
    // اگر در سبد محصول فیزیکی هست، اجازه نده
    foreach (WC()->cart->get_cart() as $item) {
        $existing_cats = wp_get_post_terms($item['product_id'], 'product_cat', ['fields' => 'slugs']);
        if (in_array('physical', $existing_cats)) {
            wc_add_notice('محصول دیجیتال و فیزیکی را نمی‌توان همزمان سفارش داد', 'error');
            return false;
        }
    }
    
    return $passed;
}, 10, 2);

افزودن خودکار هدیه

// خرید بالای ۵۰۰ هزار = یک محصول هدیه رایگان
add_action('woocommerce_before_calculate_totals', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    
    $gift_id = 123; // ID محصول هدیه
    $threshold = 500000;
    $has_gift = false;
    $cart_total = 0;
    
    // محاسبه و چک
    foreach ($cart->get_cart() as $key => $item) {
        if ($item['product_id'] != $gift_id) {
            $cart_total += $item['line_total'];
        } else {
            $has_gift = $key;
        }
    }
    
    // اضافه/حذف خودکار
    if ($cart_total >= $threshold && !$has_gift) {
        WC()->cart->add_to_cart($gift_id, 1, 0, [], ['_is_gift' => true]);
    } elseif ($cart_total < $threshold && $has_gift) {
        WC()->cart->remove_cart_item($has_gift);
    }
});

// محصول هدیه را رایگان کن
add_action('woocommerce_before_calculate_totals', function($cart) {
    foreach ($cart->get_cart() as $item) {
        if (!empty($item['_is_gift'])) {
            $item['data']->set_price(0);
        }
    }
}, 20);

💳 هوک‌های صفحه پرداخت

اضافه کردن فیلد سفارشی

// فیلد "تاریخ تحویل دلخواه"
add_action('woocommerce_after_order_notes', function($checkout) {
    woocommerce_form_field('delivery_date', [
        'type'     => 'date',
        'class'    => ['form-row-wide'],
        'label'    => 'تاریخ تحویل دلخواه',
        'required' => false,
    ], $checkout->get_value('delivery_date'));
});

// validation
add_action('woocommerce_checkout_process', function() {
    if (!empty($_POST['delivery_date'])) {
        $date = strtotime($_POST['delivery_date']);
        if ($date < strtotime('+2 days')) {
            wc_add_notice('تاریخ تحویل باید حداقل ۲ روز بعد باشد', 'error');
        }
    }
});

// ذخیره
add_action('woocommerce_checkout_update_order_meta', function($order_id) {
    if (!empty($_POST['delivery_date'])) {
        $order = wc_get_order($order_id);
        $order->update_meta_data('_delivery_date', sanitize_text_field($_POST['delivery_date']));
        $order->save();
    }
});

// نمایش در پنل ادمین
add_action('woocommerce_admin_order_data_after_billing_address', function($order) {
    $date = $order->get_meta('_delivery_date');
    if ($date) {
        echo '

تاریخ تحویل دلخواه: ' . esc_html($date) . '

'; } });

فیلد شرطی – فقط برای دسته‌های خاص

add_action('woocommerce_after_order_notes', function($checkout) {
    // اگر در سبد، محصول از دسته «فرش» هست
    $has_carpet = false;
    foreach (WC()->cart->get_cart() as $item) {
        $cats = wp_get_post_terms($item['product_id'], 'product_cat', ['fields' => 'slugs']);
        if (in_array('carpet', $cats)) {
            $has_carpet = true;
            break;
        }
    }
    
    if ($has_carpet) {
        woocommerce_form_field('floor_size', [
            'type'  => 'text',
            'label' => 'متراژ کف اتاق (برای راهنمایی نصب)',
        ]);
    }
});

تغییر متن دکمه پرداخت

add_filter('woocommerce_order_button_text', function($text) {
    return 'پرداخت امن و ثبت سفارش';
});

📦 چرخه عمر سفارش

اکشن‌های مهم وضعیت سفارش

هوک زمان اجرا
woocommerce_new_order هنگام ثبت سفارش جدید
woocommerce_order_status_pending_to_processing پرداخت موفق
woocommerce_order_status_processing_to_completed تکمیل سفارش
woocommerce_order_status_changed هر تغییر وضعیت
woocommerce_order_refunded استرداد

ارسال SMS هنگام تغییر وضعیت

add_action('woocommerce_order_status_changed', function($order_id, $old_status, $new_status, $order) {
    $phone = $order->get_billing_phone();
    if (!$phone) return;
    
    $messages = [
        'processing' => 'سفارش %s شما در حال پردازش است.',
        'completed'  => 'سفارش %s ارسال شد. کد رهگیری در پنل کاربری.',
        'cancelled'  => 'سفارش %s لغو شد.',
        'refunded'   => 'مبلغ سفارش %s به حساب شما بازگشت.',
    ];
    
    if (!isset($messages[$new_status])) return;
    
    $message = sprintf($messages[$new_status], $order->get_order_number());
    
    // ارسال با کاوه‌نگار
    wp_remote_post('https://api.kavenegar.com/v1/.../sms/send.json', [
        'body' => ['receptor' => $phone, 'message' => $message],
        'timeout' => 5,
    ]);
}, 10, 4);

تغییر وضعیت خودکار بعد از زمان مشخص

// سفارش‌های processing بعد از ۷ روز خودکار completed شوند
add_action('init', function() {
    if (!wp_next_scheduled('icsd_auto_complete_orders')) {
        wp_schedule_event(time(), 'daily', 'icsd_auto_complete_orders');
    }
});

add_action('icsd_auto_complete_orders', function() {
    $orders = wc_get_orders([
        'status'       => 'processing',
        'date_created' => '<' . (time() - (7 * DAY_IN_SECONDS)),
        'limit'        => 100,
    ]);
    
    foreach ($orders as $order) {
        $order->update_status('completed', 'تکمیل خودکار پس از ۷ روز');
    }
});

📦 هوک‌های صفحه محصول

تب جدید در صفحه محصول

add_filter('woocommerce_product_tabs', function($tabs) {
    $tabs['warranty'] = [
        'title'    => 'گارانتی و خدمات پس از فروش',
        'priority' => 30,
        'callback' => function() {
            global $product;
            $warranty = $product->get_meta('_warranty_period');
            ?>
            

اطلاعات گارانتی

مدت گارانتی:

پشتیبانی: ۰۲۱-۱۲۳۴۵۶۷۸

  • تعویض ۷ روزه
  • گارانتی اصالت کالا
  • خدمات پس از فروش رایگان

نشان «موجود» / «ناموجود» سفارشی

add_filter('woocommerce_get_availability', function($availability, $product) {
    if ($product->is_in_stock()) {
        $stock = $product->get_stock_quantity();
        if ($stock !== null && $stock < 5) {
            $availability['availability'] = 'فقط ' . $stock . ' عدد در انبار!';
            $availability['class'] = 'low-stock';
        } else {
            $availability['availability'] = '✓ موجود در انبار';
        }
    } else {
        $availability['availability'] = 'به زودی موجود می‌شود - اطلاع‌رسانی کنید';
    }
    return $availability;
}, 10, 2);

تخفیف ویژه برای کاربر VIP

add_filter('woocommerce_product_get_price', function($price, $product) {
    if (!is_user_logged_in()) return $price;
    
    $user = wp_get_current_user();
    if (in_array('vip_customer', (array) $user->roles)) {
        return floatval($price) * 0.9; // ۱۰٪ تخفیف
    }
    
    return $price;
}, 10, 2);

📧 سفارشی‌سازی ایمیل‌ها

اضافه کردن متن سفارشی به ایمیل‌ها

add_action('woocommerce_email_after_order_table', function($order, $sent_to_admin, $plain_text, $email) {
    if ($sent_to_admin || $email->id !== 'customer_processing_order') return;
    
    echo '
'; echo '

📞 پشتیبانی ۲۴ ساعته

'; echo '

تماس: ۰۲۱-۱۲۳۴۵۶۷۸

'; echo '

تلگرام: @icsd_support

'; echo '
'; }, 10, 4);

تغییر موضوع ایمیل

add_filter('woocommerce_email_subject_customer_processing_order', function($subject, $order) {
    return sprintf('🎉 سفارش #%s دریافت شد - %s', $order->get_order_number(), get_bloginfo('name'));
}, 10, 2);

ساخت ایمیل کاملاً جدید

add_filter('woocommerce_email_classes', function($emails) {
    require_once __DIR__ . '/includes/class-wc-email-shipped.php';
    $emails['WC_Email_Shipped'] = new WC_Email_Shipped();
    return $emails;
});

// در فایل کلاس:
class WC_Email_Shipped extends WC_Email {
    public function __construct() {
        $this->id          = 'wc_email_shipped';
        $this->title       = 'سفارش ارسال شد';
        $this->description = 'به مشتری اطلاع می‌دهد که سفارش پست شد';
        $this->customer_email = true;
        $this->template_html  = 'emails/customer-shipped.php';
        $this->template_plain = 'emails/plain/customer-shipped.php';
        $this->placeholders = [
            '{order_number}' => '',
            '{tracking_code}' => '',
        ];
        
        add_action('icsd_order_shipped_notification', [$this, 'trigger'], 10, 2);
        parent::__construct();
    }
    
    public function trigger($order_id, $tracking_code) {
        $this->object = wc_get_order($order_id);
        $this->placeholders['{order_number}'] = $this->object->get_order_number();
        $this->placeholders['{tracking_code}'] = $tracking_code;
        $this->recipient = $this->object->get_billing_email();
        
        $this->send($this->recipient, $this->get_subject(), $this->get_content(),
                    $this->get_headers(), $this->get_attachments());
    }
    
    public function get_default_subject() {
        return '🚚 سفارش {order_number} ارسال شد';
    }
}

// تریگر کن
do_action('icsd_order_shipped_notification', $order_id, $tracking_code);

💸 کارمزد و تخفیف پویا

اضافه کردن کارمزد بسته‌بندی

add_action('woocommerce_cart_calculate_fees', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    
    // اگر بسته‌بندی هدیه انتخاب شده
    if (!empty($_POST['gift_wrap'])) {
        $cart->add_fee('بسته‌بندی هدیه', 25000, true);
    }
    
    // کارمزد پرداخت در محل
    $payment_method = WC()->session->get('chosen_payment_method');
    if ($payment_method === 'cod') {
        $cart->add_fee('کارمزد پرداخت در محل', 15000, false);
    }
});

تخفیف خودکار با کد

// تخفیف ۱۰٪ خودکار برای اولین خرید
add_action('woocommerce_before_calculate_totals', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    if (!is_user_logged_in()) return;
    
    $user_id = get_current_user_id();
    $orders_count = wc_get_customer_order_count($user_id);
    
    if ($orders_count == 0 && !$cart->has_discount('first_purchase')) {
        $cart->apply_coupon('first_purchase');
    }
});

function wc_get_customer_order_count($user_id) {
    return count(wc_get_orders(['customer_id' => $user_id, 'limit' => -1]));
}

تخفیف بر اساس تعداد

// خرید ۳ تا = ۵٪، ۵ تا = ۱۰٪، ۱۰ تا = ۱۵٪
add_action('woocommerce_before_calculate_totals', function($cart) {
    if (is_admin() && !defined('DOING_AJAX')) return;
    
    foreach ($cart->get_cart() as $item) {
        $qty = $item['quantity'];
        $original = floatval($item['data']->get_regular_price());
        
        $discount = 0;
        if ($qty >= 10) $discount = 0.15;
        elseif ($qty >= 5) $discount = 0.10;
        elseif ($qty >= 3) $discount = 0.05;
        
        if ($discount > 0) {
            $item['data']->set_price($original * (1 - $discount));
        }
    }
});

📊 مدیریت موجودی

کاهش موجودی هنگام ساخت سفارش (نه فقط پرداخت)

// رزرو موجودی به محض ثبت سفارش
add_action('woocommerce_checkout_order_processed', function($order_id) {
    $order = wc_get_order($order_id);
    foreach ($order->get_items() as $item) {
        $product = $item->get_product();
        if ($product && $product->managing_stock()) {
            $product->set_stock_quantity($product->get_stock_quantity() - $item->get_quantity());
            $product->save();
        }
    }
});

اطلاع‌رسانی موجودی به ادمین

add_action('woocommerce_low_stock', function($product) {
    $email = get_option('admin_email');
    $message = sprintf(
        'محصول "%s" کم‌موجود شد (تعداد: %d)',
        $product->get_name(),
        $product->get_stock_quantity()
    );
    wp_mail($email, 'هشدار کم‌موجودی', $message);
});

add_action('woocommerce_no_stock', function($product) {
    // اطلاع به مدیر و فروشنده
    do_action('icsd_send_telegram', '⚠️ محصول ' . $product->get_name() . ' ناموجود شد');
});

قابلیت «وقتی موجود شد، اطلاعم بده»

// در محصولات ناموجود، فرم ثبت ایمیل
add_action('woocommerce_single_product_summary', function() {
    global $product;
    if ($product->is_in_stock()) return;
    ?>
    

وقتی موجود شد، اطلاعم بده:

is_in_stock()) return; $subscribers = get_post_meta($product->get_id(), '_back_in_stock_subscribers', true) ?: []; foreach ($subscribers as $email) { wp_mail($email, 'محصول مورد علاقه‌تان موجود شد!', $product->get_name() . ' الان موجود است: ' . $product->get_permalink()); } delete_post_meta($product->get_id(), '_back_in_stock_subscribers'); });

🔍 دیباگ هوک‌ها

پیدا کردن هوک‌های فعال

// نمایش تمام هوک‌های اجرا شده
add_action('all', function($tag) {
    if (strpos($tag, 'woocommerce') !== false) {
        error_log('WC Hook fired: ' . $tag);
    }
});

افزونه Query Monitor

افزونه Query Monitor را نصب کنید — تب «Hooks & Actions» تمام هوک‌های اجرا شده در صفحه فعلی را با priority و callback نشان می‌دهد.

پیدا کردن هوک کنار یک خروجی

// در فایل قالب، قبل از خروجی:
echo '';
do_action('woocommerce_before_main_content');
echo '';

✅ مرجع کامل: همه هوک‌های ووکامرس در سایت رسمی فهرست شده‌اند: https://woocommerce.github.io/code-reference/hooks/hooks.html

📝 خلاصه فصل

  • هوک‌های قدرتمند سبد خرید برای محدودیت و هدیه
  • اضافه کردن فیلد سفارشی به checkout
  • چرخه عمر سفارش و SMS خودکار
  • سفارشی‌سازی صفحه محصول و ایمیل‌ها
  • کارمزد پویا، تخفیف خودکار و رزرو موجودی
  • ابزارهای دیباگ هوک‌ها

نمایش سایت

رنگ سایت
حالت نمایش
اندازهٔ متن
خوانایی

این تنظیمات فقط روی مرورگر شما ذخیره می‌شود.