| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- <?php
- /**
- * Plugin Name: WC Completed-Order Email Throttle
- * Description: Posílá zákaznické e-maily o dokončení objednávky přes rate-limitovanou frontu (Action Scheduler), aby hromadná změna stavu nezahltila wp_mail / nepřekročila limit hostingu.
- * Version: 1.0.0
- * Requires Plugins: woocommerce
- *
- * Umístění: wp-content/mu-plugins/wc-mail-throttle.php (mu-plugin = vždy aktivní)
- * nebo jako běžný plugin do wp-content/plugins/.
- */
- defined( 'ABSPATH' ) || exit;
- if ( ! class_exists( 'WC_Mail_Throttle' ) ) :
- class WC_Mail_Throttle {
- const HOOK = 'wcmt_send_completed_email';
- const GROUP = 'wcmt';
- const SLOT_OPT = 'wcmt_next_slot';
- /**
- * Odstup mezi jednotlivými e-maily v sekundách.
- * 12 s = max. 5 e-mailů / min. Uprav podle limitu svého hostingu.
- */
- public static function interval() {
- return (int) apply_filters( 'wcmt_interval_seconds', 12 );
- }
- public static function init() {
- // 1) Odpojí standardní (synchronní) odeslání e-mailu o dokončení objednávky.
- add_action( 'woocommerce_email', array( __CLASS__, 'detach_default' ), 99 );
- // 2) Místo něj zařadí objednávku do fronty se staggered časem.
- add_action( 'woocommerce_order_status_completed_notification', array( __CLASS__, 'enqueue' ), 10 );
- // 3) Worker fronty – v naplánovaný čas e-mail skutečně odešle.
- add_action( self::HOOK, array( __CLASS__, 'process' ) );
- }
- /** Sundá výchozí trigger z mailer objektu, aby se neposlal hned v rámci requestu. */
- public static function detach_default( $wc_emails ) {
- if ( isset( $wc_emails->emails['WC_Email_Customer_Completed_Order'] ) ) {
- remove_action(
- 'woocommerce_order_status_completed_notification',
- array( $wc_emails->emails['WC_Email_Customer_Completed_Order'], 'trigger' )
- );
- }
- }
- /** Zařadí objednávku do fronty; každý další e-mail dostane pozdější slot. */
- public static function enqueue( $order_id ) {
- $order_id = (int) $order_id;
- // Fallback, kdyby Action Scheduler nebyl k dispozici – pošli hned.
- if ( ! function_exists( 'as_schedule_single_action' ) ) {
- self::process( $order_id );
- return;
- }
- $now = time();
- $next = (int) get_option( self::SLOT_OPT, 0 );
- // Slot = buď „teď", nebo navazuje na poslední naplánovaný (self-healing přes max()).
- $slot = max( $now, $next );
- update_option( self::SLOT_OPT, $slot + self::interval(), false ); // autoload = false
- as_schedule_single_action( $slot, self::HOOK, array( $order_id ), self::GROUP );
- }
- /** Worker: znovu spustí standardní WooCommerce e-mail pro danou objednávku. */
- public static function process( $order_id = 0 ) {
- $order_id = (int) $order_id;
- if ( ! $order_id ) {
- return;
- }
- $emails = WC()->mailer()->get_emails();
- if ( isset( $emails['WC_Email_Customer_Completed_Order'] ) ) {
- $emails['WC_Email_Customer_Completed_Order']->trigger( $order_id );
- }
- }
- }
- add_action( 'init', array( 'WC_Mail_Throttle', 'init' ) );
- endif;
|