| 1 |
<?php |
| 2 |
|
| 3 |
class WooMailerLiteOrderController extends WooMailerLiteController |
| 4 |
{ |
| 5 |
|
| 6 |
public function handleOrderStatusChanged($orderId) |
| 7 |
{ |
| 8 |
try { |
| 9 |
|
| 10 |
if (WooMailerLiteCache::get('order_sent:'.$orderId)) { |
| 11 |
return true; |
| 12 |
} |
| 13 |
$order = wc_get_order($orderId); |
| 14 |
if (!$order->get_billing_email()) { |
| 15 |
return true; |
| 16 |
} |
| 17 |
|
| 18 |
$this->persistLanguageToOrder($order); |
| 19 |
|
| 20 |
if (WooMailerLiteSession::getMLCartHash()) { |
| 21 |
$order->add_meta_data('_woo_ml_cart_hash', WooMailerLiteSession::getMLCartHash()); |
| 22 |
} |
| 23 |
$customer = WooMailerLiteCustomer::selectAll(false)->where('email', $order->get_billing_email())->first(); |
| 24 |
if (!$customer) { |
| 25 |
$customer = WooMailerLiteCustomer::selectAll(false) |
| 26 |
->getFromOrder() |
| 27 |
->where("email", $order->get_billing_email()) |
| 28 |
->whereIn("status", WooMailerLiteOptions::allSupportedOrderStatuses()) |
| 29 |
->first(); |
| 30 |
} |
| 31 |
// Query live order stats directly to avoid stale wc_order_stats reads when |
| 32 |
// multiple orders are placed in quick succession for the same email. |
| 33 |
$liveOrders = wc_get_orders([ |
| 34 |
'billing_email' => $order->get_billing_email(), |
| 35 |
'status' => WooMailerLiteOptions::COMPLETE_ORDER_STATUSES, |
| 36 |
'limit' => -1, |
| 37 |
]); |
| 38 |
$liveOrdersCount = count($liveOrders); |
| 39 |
$liveTotalSpent = (float) array_sum(array_map(fn($o) => $o->get_total(), $liveOrders)); |
| 40 |
|
| 41 |
$cart = WooMailerLiteCart::where('email', $order->get_billing_email())->first(); |
| 42 |
if (!$cart) { |
| 43 |
$cart = WooMailerLiteCart::where('hash', WooMailerLiteSession::getMLCartHash()) |
| 44 |
->withoutPrefix(function($query) use ($order) { |
| 45 |
$query->orWhere('hash', $order->get_meta('_woo_ml_cart_hash')); |
| 46 |
})->first(); |
| 47 |
if ($cart instanceof WooMailerLiteCart) { |
| 48 |
$cart->update([ |
| 49 |
'email' => $order->get_billing_email(), |
| 50 |
]); |
| 51 |
} |
| 52 |
} |
| 53 |
if (!$cart && !$customer) { |
| 54 |
return true; |
| 55 |
} |
| 56 |
|
| 57 |
if ((isset($cart->subscribe) && $cart->subscribe) || WooMailerLiteOptions::get("settings.checkoutHidden")) { |
| 58 |
$order->add_meta_data('_woo_ml_subscribe', true); |
| 59 |
} |
| 60 |
|
| 61 |
$syncFields = WooMailerLiteOptions::get('syncFields', []); |
| 62 |
if (empty($syncFields)) { |
| 63 |
$syncFields = [ |
| 64 |
'name', |
| 65 |
'email', |
| 66 |
'company', |
| 67 |
'city', |
| 68 |
'zip', |
| 69 |
'state', |
| 70 |
'country', |
| 71 |
'phone' |
| 72 |
]; |
| 73 |
WooMailerLiteOptions::update('syncFields', $syncFields); |
| 74 |
} |
| 75 |
$filteredCustomerData = array_filter($customer ? $customer->toArray() : [], function($value) { |
| 76 |
return !is_null($value) && trim($value) !== ''; |
| 77 |
}); |
| 78 |
|
| 79 |
$syncFields[] = 'last_name'; |
| 80 |
if (!in_array('name', $syncFields)) { |
| 81 |
$syncFields[] = 'name'; |
| 82 |
} |
| 83 |
|
| 84 |
$customerFields = array_intersect_key($filteredCustomerData, array_flip($syncFields)); |
| 85 |
if (WooMailerLiteOptions::get('settings.languageField')) { |
| 86 |
$customerFields['subscriber_language'] = $order->get_meta('_woo_ml_language'); |
| 87 |
} |
| 88 |
|
| 89 |
$subscribe = false; |
| 90 |
$email = $customer->email ?? $order->get_billing_email(); |
| 91 |
$subscribeCacheKey = 'woo_ml_subscribe_checkbox:'.$email; |
| 92 |
if ($cart && isset($cart->subscribe)) { |
| 93 |
$subscribe = $cart->subscribe; |
| 94 |
} |
| 95 |
|
| 96 |
if (WooMailerLiteOptions::get("settings.checkoutHidden") || $order->get_meta('_woo_ml_subscribe')) { |
| 97 |
$subscribe = true; |
| 98 |
} |
| 99 |
|
| 100 |
if (WooMailerLiteCache::get($subscribeCacheKey) === null) { |
| 101 |
WooMailerLiteCache::set($subscribeCacheKey, $subscribe, 20); |
| 102 |
} |
| 103 |
|
| 104 |
if (WooMailerLiteCache::get($subscribeCacheKey) === true) { |
| 105 |
$subscribe = true; |
| 106 |
} |
| 107 |
|
| 108 |
$orderCustomer = [ |
| 109 |
'email' => $customer->email ?? $order->get_billing_email(), |
| 110 |
'create_subscriber' => $subscribe, |
| 111 |
'accepts_marketing' => $subscribe, |
| 112 |
'subscriber_fields' => $customerFields, |
| 113 |
'total_spent' => $liveTotalSpent, |
| 114 |
'orders_count' => $liveOrdersCount, |
| 115 |
'last_order_id' => $customer->last_order_id ?? null, |
| 116 |
'last_order' => $customer->last_order ?? null |
| 117 |
]; |
| 118 |
$items = []; |
| 119 |
|
| 120 |
foreach ($order->get_items() as $item) { |
| 121 |
if ($item->get_product_id() !== 0) { |
| 122 |
$items[] = [ |
| 123 |
'product_resource_id' => (string)$item->get_product_id(), |
| 124 |
'ecommerce_product_variant_id' => (string) $item->get_variation_id(), |
| 125 |
'variant' => $item->get_name(), |
| 126 |
'quantity' => $item->get_quantity(), |
| 127 |
'price' => (float)$item->get_product()->get_price() |
| 128 |
]; |
| 129 |
} |
| 130 |
} |
| 131 |
$cartData = [ |
| 132 |
'items' => $items |
| 133 |
]; |
| 134 |
|
| 135 |
if ($this->apiClient()->isClassic()) { |
| 136 |
$orderData['order'] = $order->get_data(); |
| 137 |
$orderData['checkout_id'] = $cart->data['checkout_id'] ?? null; |
| 138 |
$orderData['order_url'] = home_url() . "/wp-admin/post.php?post=" . $orderId . "&action=edit"; |
| 139 |
$customerFields['woo_total_spent'] = $liveTotalSpent; |
| 140 |
$customerFields['woo_orders_count'] = $liveOrdersCount; |
| 141 |
$customerFields['woo_last_order_id'] = $customer->last_order_id ?? null; |
| 142 |
$customerFields['woo_last_order'] = $customer->last_order ?? nulL; |
| 143 |
$data = [ |
| 144 |
'email' => $customer->email, |
| 145 |
'checked_sub_to_mailist' => (bool)$subscribe ?? (bool)$cart->subscribe, |
| 146 |
'checkout_id' => $cart->data['checkout_id'] ?? null, |
| 147 |
'order_id' => $orderId, |
| 148 |
'payment_method' => $order->get_payment_method(), |
| 149 |
'fields' => $customerFields, |
| 150 |
'shop_url' => home_url(), |
| 151 |
'order_url' => home_url() . "/wp-admin/post.php?post=" . $orderId . "&action=edit", |
| 152 |
'checkout_data' => WooMailerLiteCheckoutDataService::getCheckoutData($order->get_billing_email()) |
| 153 |
]; |
| 154 |
$this->apiClient()->sendOrderProcessing($data); |
| 155 |
if (WooMailerLiteOptions::isCompleteOrderStatus($order->get_status()) && $order->get_items()) { |
| 156 |
$order_items = $order->get_items(); |
| 157 |
foreach ($order_items as $key => $value) { |
| 158 |
$item_data = $value->get_data(); |
| 159 |
$orderData['order']['line_items'][$key] = $item_data; |
| 160 |
$orderData['order']['line_items'][$key]['ignored_product'] = in_array($item_data['product_id'], |
| 161 |
array_map('strval', array_keys(WooMailerLiteOptions::get('ignored_products', [])))) ? 1 : 0; |
| 162 |
} |
| 163 |
$orderData['order']['status'] = 'completed'; |
| 164 |
WooMailerLiteCache::set('order_sent:'.$orderId, true, 20); |
| 165 |
$response = $this->apiClient()->syncOrder(home_url(), $orderData); |
| 166 |
$this->apiClient()->sendSubscriberData($data); |
| 167 |
} |
| 168 |
|
| 169 |
} else { |
| 170 |
$date = null; |
| 171 |
if ($order->get_date_created()) { |
| 172 |
$date = $order->get_date_created()->format('Y-m-d H:i:s'); |
| 173 |
} |
| 174 |
|
| 175 |
$stage = WooMailerLiteOptions::isCompleteOrderStatus($order->get_status()) ? null : 'checkout'; |
| 176 |
$response = $this->apiClient()->syncOrder( |
| 177 |
WooMailerLiteOptions::get('shopId'), |
| 178 |
$orderId, |
| 179 |
$orderCustomer, |
| 180 |
$cartData, |
| 181 |
$order->get_status(), |
| 182 |
$order->get_total(), |
| 183 |
$date, |
| 184 |
$stage |
| 185 |
); |
| 186 |
} |
| 187 |
|
| 188 |
if (isset($response) && $response->success) { |
| 189 |
$order->add_meta_data('_woo_ml_order_data_submitted', true); |
| 190 |
if (!empty($cart) && $cart instanceof WooMailerLiteCart) { |
| 191 |
if ($this->apiClient()->isRewrite()) { |
| 192 |
$this->apiClient()->deleteOrder($cart->data['checkout_id']); |
| 193 |
} |
| 194 |
if (WooMailerLiteOptions::isCompleteOrderStatus($order->get_status())) { |
| 195 |
$cart->delete(); |
| 196 |
} |
| 197 |
} |
| 198 |
|
| 199 |
$createdAt = null; |
| 200 |
$updatedAt = null; |
| 201 |
|
| 202 |
if ($this->apiClient()->isClassic()) { |
| 203 |
$response = $this->apiClient()->searchSubscriber($customer->email); |
| 204 |
|
| 205 |
// For classic response, we have accesss to the date_created and date_updated fields |
| 206 |
if ($response->success) { |
| 207 |
$createdAt = $response->data->date_created; |
| 208 |
$updatedAt = $response->data->date_updated; |
| 209 |
} |
| 210 |
} |
| 211 |
|
| 212 |
// For rewrite response, we have accesss to the subscriber object |
| 213 |
if (isset($response->data->customer->subscriber)) { |
| 214 |
$createdAt = $response->data->customer->subscriber->created_at; |
| 215 |
$updatedAt = $response->data->customer->subscriber->updated_at; |
| 216 |
} |
| 217 |
|
| 218 |
// We will only set the order meta when we have these dates |
| 219 |
if ($createdAt && $updatedAt) { |
| 220 |
$createdAt = strtotime($createdAt); |
| 221 |
$updatedAt = strtotime($updatedAt); |
| 222 |
|
| 223 |
// If the created and updated timestamps are within 60 seconds, the subscriber was just created |
| 224 |
if (abs($createdAt - $updatedAt) < 60) { |
| 225 |
$order->add_meta_data('_woo_ml_subscribed', true); |
| 226 |
} else { |
| 227 |
$order->add_meta_data('_woo_ml_already_subscribed', true); |
| 228 |
$order->add_meta_data('_woo_ml_subscriber_updated', true); |
| 229 |
} |
| 230 |
} |
| 231 |
|
| 232 |
$order->add_meta_data('_woo_ml_order_tracked', true); |
| 233 |
} |
| 234 |
$order->save(); |
| 235 |
} catch(\Throwable $e) { |
| 236 |
WooMailerLiteLog()->error('handleOrderStatusChanged', [ |
| 237 |
'error' => $e->getMessage(), |
| 238 |
'trace' => $e->getTraceAsString(), |
| 239 |
'orderId' => $orderId |
| 240 |
]); |
| 241 |
|
| 242 |
return true; |
| 243 |
} |
| 244 |
} |
| 245 |
|
| 246 |
private function persistLanguageToOrder($order): void |
| 247 |
{ |
| 248 |
$key = '_woo_ml_language'; |
| 249 |
if (isset(WC()->session)) { |
| 250 |
$language = WC()->session->get($key); |
| 251 |
if ($language && !$order->get_meta($key)) { |
| 252 |
$order->add_meta_data($key, $language); |
| 253 |
$order->save(); |
| 254 |
} |
| 255 |
} |
| 256 |
} |
| 257 |
} |
| 258 |
|