PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.21
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.21
1.4.21 1.4.20 1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 All 184 releases
← All changes | functions/order.php +111 -1 1.4.19 → 1.4.21 View file →
@@ -56,9 +56,9 @@
56 56 */
57 57 $existing = $order->get_meta( 'disco_campaign', false );
58 58
59 59 if ( ! empty( $existing ) ) {
60 - WC()->session->__unset( 'disco_campaign' );
60 + disco_finalise_campaign_usage( $order );
61 61
62 62 return;
63 63 }
64 64
@@ -85,8 +85,118 @@
85 85 }
86 86
87 87 add_action( 'woocommerce_thankyou', 'disco_add_order_meta', PHP_INT_MAX );
88 88 add_action( 'woocommerce_payment_complete', 'disco_add_order_meta', PHP_INT_MAX );
89 +}
90 +
91 +if ( ! function_exists( 'disco_finalise_campaign_usage' ) ) {
92 +
93 + /**
94 + * Settle the caches and session for an order that already carries its meta.
95 + *
96 + * Normally the meta was written by disco_add_campaign_order_meta() as the
97 + * order was created. The usage caches have to be dropped here rather than
98 + * there: at creation the order is not persisted yet, so a flush would
99 + * immediately repopulate the old count from the database.
100 + *
101 + * @param \WC_Order $order Order object.
102 + * @return void
103 + */
104 + function disco_finalise_campaign_usage( $order ) {
105 + foreach ( disco_campaign_ids_on_order( $order ) as $campaign_id ) {
106 + \Disco\App\Features\UserLimit::flush_cache( $campaign_id );
107 + }
108 +
109 + if ( WC()->session ) {
110 + WC()->session->__unset( 'disco_campaign' );
111 + }
112 +
113 + if ( ! function_exists( 'disco_clear_price_cache' ) ) {
114 + return;
115 + }
116 +
117 + disco_clear_price_cache();
118 + }
119 +
120 +}
121 +
122 +if ( ! function_exists( 'disco_campaign_ids_on_order' ) ) {
123 +
124 + /**
125 + * Campaign IDs already recorded on an order.
126 + *
127 + * @param \WC_Order $order Order object.
128 + * @return array<int, int>
129 + */
130 + function disco_campaign_ids_on_order( $order ): array {
131 + if ( ! $order instanceof WC_Order ) {
132 + return array();
133 + }
134 +
135 + $meta = $order->get_meta( 'disco_campaign', false );
136 +
137 + if ( empty( $meta ) ) {
138 + return array();
139 + }
140 +
141 + return array_map( 'intval', wp_list_pluck( $meta, 'value' ) );
142 + }
143 +
144 +}
145 +
146 +if ( ! function_exists( 'disco_add_campaign_order_meta' ) ) {
147 +
148 + /**
149 + * Record the applied campaigns while the order is being created.
150 + *
151 + * The campaign IDs are staged in the WC session as the cart is priced, and
152 + * were previously read back on woocommerce_thankyou / payment_complete. Those
153 + * run in a later request, which is not always the same session: an off site
154 + * gateway can return the customer on a fresh one, and a payment webhook has
155 + * no customer session at all. The handover then found nothing and returned
156 + * silently, leaving a discounted order with no campaign recorded, so its
157 + * usage limit never counted it and Analytics never saw it.
158 + *
159 + * Reading the session here instead keeps both halves in the request that
160 + * priced the cart. The later hooks stay in place as a fallback for anything
161 + * that reaches them without meta, and to drop the usage caches once the order
162 + * actually exists.
163 + *
164 + * @param \WC_Order $order The order being created.
165 + * @return void
166 + */
167 + function disco_add_campaign_order_meta( $order ) {
168 + if ( ! $order instanceof WC_Order || ! WC()->session ) {
169 + return;
170 + }
171 +
172 + $campaigns = WC()->session->get( 'disco_campaign' );
173 +
174 + if ( empty( $campaigns ) || ! is_array( $campaigns ) ) {
175 + return;
176 + }
177 +
178 + $existing = disco_campaign_ids_on_order( $order );
179 +
180 + foreach ( $campaigns as $campaign_id ) {
181 + $campaign_id = (int) $campaign_id;
182 +
183 + if ( in_array( $campaign_id, $existing, true ) ) {
184 + continue;
185 + }
186 +
187 + $order->add_meta_data( 'disco_campaign', $campaign_id, false );
188 +
189 + $existing[] = $campaign_id;
190 + }
191 + }
192 +
193 + // Classic (shortcode) checkout: order is saved by WC after this action.
194 + add_action( 'woocommerce_checkout_create_order', 'disco_add_campaign_order_meta', 10 );
195 +
196 + // Block / Store API checkout: WC_Checkout::create_order() does not run, so
197 + // the action above never fires.
198 + add_action( 'woocommerce_store_api_checkout_update_order_meta', 'disco_add_campaign_order_meta', 10 );
89 199 }
90 200
91 201 if ( ! function_exists( 'disco_flush_campaign_usage_cache_on_status_change' ) ) {
92 202