| @@ -45,24 +45,8 @@ | ||
| 45 | 45 | /** |
| 46 | 46 | * Add each campaign ID as separate meta entry. |
| 47 | 47 | * Using unique=false allows multiple campaign IDs per order. |
| 48 | 48 | */ |
| 49 | - /** | |
| 50 | - * Guard against double execution. | |
| 51 | - * | |
| 52 | - * This callback fires on both woocommerce_thankyou and | |
| 53 | - * woocommerce_payment_complete. Depending on the gateway and page | |
| 54 | - * reloads either can run first, so skip if campaign meta is already | |
| 55 | - * stored to avoid duplicate disco_campaign entries. | |
| 56 | - */ | |
| 57 | - $existing = $order->get_meta( 'disco_campaign', false ); | |
| 58 | - | |
| 59 | - if ( ! empty( $existing ) ) { | |
| 60 | - WC()->session->__unset( 'disco_campaign' ); | |
| 61 | - | |
| 62 | - return; | |
| 63 | - } | |
| 64 | - | |
| 65 | 49 | foreach ( $campaigns as $campaign_id ) { |
| 66 | 50 | $order->add_meta_data( 'disco_campaign', (int) $campaign_id, false ); |
| 67 | 51 | } |
| 68 | 52 | |
| @@ -70,13 +54,8 @@ | ||
| 70 | 54 | $order->save(); |
| 71 | 55 | |
| 72 | 56 | WC()->session->__unset( 'disco_campaign' ); |
| 73 | 57 | |
| 74 | - // Drop the cached usage counts for the campaigns this order just used. | |
| 75 | - foreach ( $campaigns as $campaign_id ) { | |
| 76 | - \Disco\App\Features\UserLimit::flush_cache( (int) $campaign_id ); | |
| 77 | - } | |
| 78 | - | |
| 79 | 58 | // Clear price cache so user limits are re-evaluated |
| 80 | 59 | if ( !function_exists( 'disco_clear_price_cache' ) ) { |
| 81 | 60 | return; |
| 82 | 61 | } |
| @@ -87,83 +66,8 @@ | ||
| 87 | 66 | add_action( 'woocommerce_thankyou', 'disco_add_order_meta', PHP_INT_MAX ); |
| 88 | 67 | add_action( 'woocommerce_payment_complete', 'disco_add_order_meta', PHP_INT_MAX ); |
| 89 | 68 | } |
| 90 | 69 | |
| 91 | -if ( ! function_exists( 'disco_flush_campaign_usage_cache_on_status_change' ) ) { | |
| 92 | - | |
| 93 | - /** | |
| 94 | - * Invalidate cached campaign usage counts when an order changes status. | |
| 95 | - * | |
| 96 | - * The usage count only counts orders in processing / on-hold / completed, so | |
| 97 | - * any status transition can change it. Flushing here keeps the cached count | |
| 98 | - * correct without querying on every cart or fragment-refresh request. | |
| 99 | - * | |
| 100 | - * @param int $order_id Order ID. | |
| 101 | - * @return void | |
| 102 | - */ | |
| 103 | - function disco_flush_campaign_usage_cache_on_status_change( $order_id ) { | |
| 104 | - $order = wc_get_order( $order_id ); | |
| 105 | - | |
| 106 | - if ( ! $order instanceof WC_Order ) { | |
| 107 | - return; | |
| 108 | - } | |
| 109 | - | |
| 110 | - $meta = $order->get_meta( 'disco_campaign', false ); | |
| 111 | - | |
| 112 | - if ( empty( $meta ) || ! is_array( $meta ) ) { | |
| 113 | - return; | |
| 114 | - } | |
| 115 | - | |
| 116 | - foreach ( wp_list_pluck( $meta, 'value' ) as $campaign_id ) { | |
| 117 | - \Disco\App\Features\UserLimit::flush_cache( (int) $campaign_id ); | |
| 118 | - } | |
| 119 | - } | |
| 120 | - | |
| 121 | - add_action( 'woocommerce_order_status_changed', 'disco_flush_campaign_usage_cache_on_status_change', 10, 1 ); | |
| 122 | - add_action( 'woocommerce_trash_order', 'disco_flush_campaign_usage_cache_on_status_change', 10, 1 ); | |
| 123 | - add_action( 'woocommerce_untrash_order', 'disco_flush_campaign_usage_cache_on_status_change', 10, 1 ); | |
| 124 | - add_action( 'woocommerce_before_delete_order', 'disco_flush_campaign_usage_cache_on_status_change', 10, 1 ); | |
| 125 | - add_action( 'woocommerce_delete_order', 'disco_flush_campaign_usage_cache_on_status_change', 10, 1 ); | |
| 126 | -} | |
| 127 | - | |
| 128 | -if ( ! function_exists( 'disco_flush_campaign_usage_cache_on_meta_write' ) ) { | |
| 129 | - | |
| 130 | - /** | |
| 131 | - * Invalidate cached campaign usage counts when disco_campaign meta is written | |
| 132 | - * outside of this plugin. | |
| 133 | - * | |
| 134 | - * Imports, migrations and third-party code write order meta directly rather | |
| 135 | - * than going through disco_add_order_meta(), so without this the cached count | |
| 136 | - * would stay stale until its TTL expired. | |
| 137 | - * | |
| 138 | - * @param int|array $meta_id Meta ID (array on delete). | |
| 139 | - * @param int $object_id Order ID. | |
| 140 | - * @param string $meta_key Meta key. | |
| 141 | - * @param mixed $meta_value Meta value. | |
| 142 | - * @return void | |
| 143 | - */ | |
| 144 | - // $meta_id and $object_id are unused but required: the meta hooks pass their | |
| 145 | - // arguments positionally, so $meta_key and $meta_value cannot be reached | |
| 146 | - // without declaring them. | |
| 147 | - function disco_flush_campaign_usage_cache_on_meta_write( $meta_id, $object_id, $meta_key, $meta_value ) { //phpcs:ignore | |
| 148 | - if ( 'disco_campaign' !== $meta_key ) { | |
| 149 | - return; | |
| 150 | - } | |
| 151 | - | |
| 152 | - \Disco\App\Features\UserLimit::flush_cache( (int) $meta_value ); | |
| 153 | - } | |
| 154 | - | |
| 155 | - // Legacy (post table) orders. | |
| 156 | - add_action( 'added_post_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 157 | - add_action( 'updated_post_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 158 | - add_action( 'deleted_post_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 159 | - | |
| 160 | - // HPOS orders. | |
| 161 | - add_action( 'added_wc_order_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 162 | - add_action( 'updated_wc_order_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 163 | - add_action( 'deleted_wc_order_meta', 'disco_flush_campaign_usage_cache_on_meta_write', 10, 4 ); | |
| 164 | -} | |
| 165 | - | |
| 166 | 70 | if ( ! function_exists( 'disco_reset_campaign_session' ) ) { |
| 167 | 71 | |
| 168 | 72 | /** |
| 169 | 73 | * Clear the disco_campaign session before cart totals are recalculated. |
| @@ -186,53 +90,5 @@ | ||
| 186 | 90 | WC()->session->__unset( 'disco_campaign' ); |
| 187 | 91 | } |
| 188 | 92 | |
| 189 | 93 | add_action( 'woocommerce_before_calculate_totals', 'disco_reset_campaign_session', 0 ); |
| 190 | -} | |
| 191 | - | |
| 192 | -if ( ! function_exists( 'disco_add_free_shipping_order_meta' ) ) { | |
| 193 | - | |
| 194 | - /** | |
| 195 | - * Persist free-shipping campaign IDs to the order meta during checkout. | |
| 196 | - * | |
| 197 | - * Free shipping is applied through the woocommerce_package_rates filter, | |
| 198 | - * whose results WooCommerce caches per package. Because of that cache, the | |
| 199 | - * filter is not guaranteed to run on the final order-placement recalculation, | |
| 200 | - * so the campaign ID cannot be reliably staged in the WC session like the | |
| 201 | - * product and cart intents are. Instead we evaluate the Shipping intents | |
| 202 | - * fresh here, where the order object and cart are both available, and write | |
| 203 | - * the campaign IDs straight to the order. | |
| 204 | - * | |
| 205 | - * @param \WC_Order $order The order being created. | |
| 206 | - * @return void | |
| 207 | - */ | |
| 208 | - function disco_add_free_shipping_order_meta( $order ) { | |
| 209 | - if ( ! $order instanceof WC_Order ) { | |
| 210 | - return; | |
| 211 | - } | |
| 212 | - | |
| 213 | - $campaign_ids = ( new \Disco\App\Disco )->get_applied_free_shipping_campaign_ids(); | |
| 214 | - | |
| 215 | - if ( empty( $campaign_ids ) ) { | |
| 216 | - return; | |
| 217 | - } | |
| 218 | - | |
| 219 | - // Avoid duplicating IDs already staged from product/cart intents. | |
| 220 | - $existing = array_map( 'intval', $order->get_meta( 'disco_campaign', false ) ? wp_list_pluck( $order->get_meta( 'disco_campaign', false ), 'value' ) : array() ); | |
| 221 | - | |
| 222 | - foreach ( $campaign_ids as $campaign_id ) { | |
| 223 | - if ( in_array( (int) $campaign_id, $existing, true ) ) { | |
| 224 | - continue; | |
| 225 | - } | |
| 226 | - | |
| 227 | - $order->add_meta_data( 'disco_campaign', (int) $campaign_id, false ); | |
| 228 | - } | |
| 229 | - } | |
| 230 | - | |
| 231 | - // Classic (shortcode) checkout: order is saved by WC after this action. | |
| 232 | - add_action( 'woocommerce_checkout_create_order', 'disco_add_free_shipping_order_meta', 20 ); | |
| 233 | - | |
| 234 | - // Block / Store API checkout: WC_Checkout::create_order() does not run, so | |
| 235 | - // the action above never fires. This Store API hook also passes the WC_Order | |
| 236 | - // (as its first arg) before the order is persisted. | |
| 237 | - add_action( 'woocommerce_store_api_checkout_update_order_meta', 'disco_add_free_shipping_order_meta', 20 ); | |
| 238 | 94 | } |