PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.1
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.1
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 1.3.51 1.3.50 1.3.49 1.3.48 1.3.47 1.3.46 All 178 releases
disco / functions / order.php

order.php in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.1, at functions/order.php

159 lines 4.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Disco
4 *
5 * @package Disco
6 * @author Ohidul Islam <wahid0003@gmail.com>
7 * @link http://domain.tld
8 * @license GPL 2.0+
9 * @copyright 2022 WebAppick
10 */
11
12 // Ensure the file is not accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 if ( ! function_exists( 'disco_add_order_meta' ) ) {
18
19 /**
20 * Get a campaign id from WC session and set into post meta after place order.
21 * Unset WC session after update post-meta.
22 *
23 * @param int $order_id Order ID.
24 * @return void
25 */
26 function disco_add_order_meta( $order_id ) {
27 // Validate session exists
28 if ( ! WC()->session ) {
29 return;
30 }
31
32 $campaigns = WC()->session->get( 'disco_campaign' );
33
34 if ( empty( $campaigns ) || ! is_array( $campaigns ) ) {
35 return;
36 }
37
38 $order = wc_get_order( $order_id );
39
40 // Validate order exists
41 if ( ! $order instanceof WC_Order ) {
42 return;
43 }
44
45 /**
46 * Add each campaign ID as separate meta entry.
47 * Using unique=false allows multiple campaign IDs per order.
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 foreach ( $campaigns as $campaign_id ) {
66 $order->add_meta_data( 'disco_campaign', (int) $campaign_id, false );
67 }
68
69 // Save once after all meta is added (more efficient)
70 $order->save();
71
72 WC()->session->__unset( 'disco_campaign' );
73
74 // Clear price cache so user limits are re-evaluated
75 if ( !function_exists( 'disco_clear_price_cache' ) ) {
76 return;
77 }
78
79 disco_clear_price_cache();
80 }
81
82 add_action( 'woocommerce_thankyou', 'disco_add_order_meta', PHP_INT_MAX );
83 add_action( 'woocommerce_payment_complete', 'disco_add_order_meta', PHP_INT_MAX );
84 }
85
86 if ( ! function_exists( 'disco_reset_campaign_session' ) ) {
87
88 /**
89 * Clear the disco_campaign session before cart totals are recalculated.
90 *
91 * This prevents stale campaign IDs (from previously discounted products
92 * that were later removed from the cart) from being saved to order meta.
93 * The session is rebuilt fresh each time checkout prices are recalculated.
94 *
95 * @return void
96 */
97 function disco_reset_campaign_session() {
98 if ( ! is_checkout() ) {
99 return;
100 }
101
102 if ( ! WC()->session ) {
103 return;
104 }
105
106 WC()->session->__unset( 'disco_campaign' );
107 }
108
109 add_action( 'woocommerce_before_calculate_totals', 'disco_reset_campaign_session', 0 );
110 }
111
112 if ( ! function_exists( 'disco_add_free_shipping_order_meta' ) ) {
113
114 /**
115 * Persist free-shipping campaign IDs to the order meta during checkout.
116 *
117 * Free shipping is applied through the woocommerce_package_rates filter,
118 * whose results WooCommerce caches per package. Because of that cache, the
119 * filter is not guaranteed to run on the final order-placement recalculation,
120 * so the campaign ID cannot be reliably staged in the WC session like the
121 * product and cart intents are. Instead we evaluate the Shipping intents
122 * fresh here, where the order object and cart are both available, and write
123 * the campaign IDs straight to the order.
124 *
125 * @param \WC_Order $order The order being created.
126 * @return void
127 */
128 function disco_add_free_shipping_order_meta( $order ) {
129 if ( ! $order instanceof WC_Order ) {
130 return;
131 }
132
133 $campaign_ids = ( new \Disco\App\Disco )->get_applied_free_shipping_campaign_ids();
134
135 if ( empty( $campaign_ids ) ) {
136 return;
137 }
138
139 // Avoid duplicating IDs already staged from product/cart intents.
140 $existing = array_map( 'intval', $order->get_meta( 'disco_campaign', false ) ? wp_list_pluck( $order->get_meta( 'disco_campaign', false ), 'value' ) : array() );
141
142 foreach ( $campaign_ids as $campaign_id ) {
143 if ( in_array( (int) $campaign_id, $existing, true ) ) {
144 continue;
145 }
146
147 $order->add_meta_data( 'disco_campaign', (int) $campaign_id, false );
148 }
149 }
150
151 // Classic (shortcode) checkout: order is saved by WC after this action.
152 add_action( 'woocommerce_checkout_create_order', 'disco_add_free_shipping_order_meta', 20 );
153
154 // Block / Store API checkout: WC_Checkout::create_order() does not run, so
155 // the action above never fires. This Store API hook also passes the WC_Order
156 // (as its first arg) before the order is persisted.
157 add_action( 'woocommerce_store_api_checkout_update_order_meta', 'disco_add_free_shipping_order_meta', 20 );
158 }
159