Initial commit

This commit is contained in:
gustavooth
2026-07-23 22:56:30 -03:00
commit 22a1006598
1816 changed files with 410742 additions and 0 deletions
@@ -0,0 +1,752 @@
<?php
namespace FluentCrm\App\Modules\AbandonCart\Drivers\FluentCart;
use FluentCart\Api\StoreSettings;
use FluentCart\App\Helpers\AddressHelper;
use FluentCart\App\Models\Cart;
use FluentCrm\App\Modules\AbandonCart\AbandonCartModel;
use FluentCrm\App\Modules\AbandonCart\AbCartHelper;
use FluentCrm\App\Models\FunnelSubscriber;
use FluentCrm\App\Models\Subscriber;
use FluentCrm\Framework\Support\Arr;
class FluentCartTrackingInit
{
public function register()
{
// Funnel Automations
(new FluentCartAutomationTrigger())->register();
// Checkout Frontend - inject tracking script
add_action('fluent_cart/after_checkout_page', [$this, 'addAbandonScript']);
// AJAX handler for GDPR opt-out
add_action('wp_ajax_fc_ab_fct_cart_skip', [$this, 'handleAjaxOptOut']);
add_action('wp_ajax_nopriv_fc_ab_fct_cart_skip', [$this, 'handleAjaxOptOut']);
// Sync abandoned cart when FluentCart saves checkout data
add_filter('fluent_cart/checkout/after_patch_checkout_data_fragments', function ($fragments, $data) {
$this->maybeSyncCart(Arr::get($data, 'cart'));
return $fragments;
}, 99, 2);
// Sync abandoned cart when cart amounts change (item add/remove, coupon)
add_action('fluent_cart/checkout/cart_amount_updated', function ($data) {
$this->maybeSyncCart(Arr::get($data, 'cart'));
}, 99);
// Sync abandoned cart on form data change (alternative save path)
add_action('fluent_cart/checkout/form_data_changed', function ($data) {
$this->maybeSyncCart(Arr::get($data, 'cart'));
}, 99);
// Cart recovery URL handler
// URL: example.com/?fluentcrm=1&route=general&handler=fc_cart_fluent_cart&fc_ab_hash=xyz
add_action('fluent_crm/handle_frontend_for_fc_cart_fluent_cart', function ($data) {
add_action('template_redirect', function () use ($data) {
$this->maybeRestoreCart($data);
}, 1);
});
// Order lifecycle - link cart to order when created
add_action('fluent_cart/order_created', [$this, 'handleOrderCreated'], 1);
// Order paid - mark cart as recovered
add_action('fluent_cart/order_paid', [$this, 'handleOrderPaid'], 1);
// Order status changes
add_action('fluent_cart/order_status_changed', [$this, 'handleOrderStatusChanged'], 10);
// Push contextual smart codes for this provider
add_filter('fluent_crm_funnel_context_smart_codes', [$this, 'pushContextCodes'], 1, 2);
// Parse the context codes
add_filter('fluent_crm/smartcode_group_callback_ab_cart_fluent_cart', [$this, 'parseSmartCodes'], 10, 4);
}
public function addAbandonScript()
{
if (!AbCartHelper::willCartTrack()) {
return;
}
if (isset($_COOKIE['fc_ab_cart_skip_track']) && $_COOKIE['fc_ab_cart_skip_track'] == 'yes') {
return;
}
wp_enqueue_script(
'fluent_crm-abandon-cart-fct',
FLUENTCRM_PLUGIN_URL . 'app/Modules/AbandonCart/Drivers/FluentCart/assets/fc-cart-abandon-fluent-cart.js',
[],
FLUENTCRM_PLUGIN_VERSION,
true
);
wp_localize_script('fluent_crm-abandon-cart-fct', 'fc_ab_fct_cart', [
'nonce' => wp_create_nonce('fc_ab_fct_cart_nonce'),
'__gdpr_message' => AbCartHelper::getGDPRMessage(),
]);
}
public function handleAjaxOptOut()
{
$nonce = Arr::get($_REQUEST, '_nonce');
if (!wp_verify_nonce($nonce, 'fc_ab_fct_cart_nonce')) {
wp_send_json([
'message' => __('Security check failed. Invalid nonce.', 'fluent-crm')
], 403);
}
$record = $this->getCurrentRecord();
if ($record) {
$record->optOut();
}
$cookieDays = (int)apply_filters('fluent_crm/ab_cart_opt_out_cookie_validity', 7);
setcookie('fc_ab_cart_skip_track', 'yes', time() + (86400 * $cookieDays), COOKIEPATH, COOKIE_DOMAIN);
wp_send_json([
'message' => __('You have opted out from cart tracking', 'fluent-crm')
]);
}
public function maybeSyncCart($fctCart)
{
if (!$fctCart || !AbCartHelper::willCartTrack()) {
return;
}
if (!$fctCart->email || empty($fctCart->cart_data)) {
return;
}
$billingEmail = $fctCart->email;
if (isset($_COOKIE['fc_ab_cart_skip_track']) && $_COOKIE['fc_ab_cart_skip_track'] == 'yes') {
$record = $this->getCurrentRecord($billingEmail, $fctCart->cart_hash);
if ($record && $record->status !== 'opt_out') {
$record->status = 'opt_out';
$record->save();
}
return;
}
$checkoutData = $fctCart->checkout_data ?: [];
// Calculate totals for the table columns (FluentCart stores amounts in cents).
// $subtotal is the items' price BEFORE any discount.
$subtotal = $fctCart->getItemsSubtotal();
// Coupon and per-item manual discounts are stored on each cart item as
// discount_total (manual_discount + coupon_discount). The old code only read
// custom_checkout_data.discount_total, which is empty for normal frontend
// coupons, so the coupon was never reflected in the cart total. Sum the per-item
// discounts plus any checkout-level (manual/upgrade/prorate) discounts.
$itemsDiscountTotal = array_sum(array_map(function ($item) {
return (int)Arr::get($item, 'discount_total', 0);
}, $fctCart->cart_data ?: []));
$discountTotal = $itemsDiscountTotal
+ (int)Arr::get($checkoutData, 'manual_discount.amount', 0)
+ (int)Arr::get($checkoutData, 'upgrade_discount.amount', 0)
+ (int)Arr::get($checkoutData, 'prorate_credit.amount', 0);
$shippingTotal = (int)$fctCart->getShippingTotal();
$taxTotal = (int)Arr::get($checkoutData, 'tax_data.tax_total', 0);
// Use FluentCart's authoritative total so the displayed Cart Total matches the
// checkout exactly (coupons, fees, shipping and tax all included).
$total = (int)$fctCart->getEstimatedTotal();
if ($total <= 0) {
$record = $this->getCurrentRecord($billingEmail);
if ($record) {
$record->delete();
setcookie('fc_ab_fct_cart_token', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN);
}
return;
}
$currency = '';
if (class_exists('\FluentCart\Api\CurrencySettings')) {
$currency = \FluentCart\Api\CurrencySettings::get('currency') ?: 'USD';
}
$contact = FluentCrmApi('contacts')->getContact($billingEmail);
$fullName = $fctCart->full_name ?? trim($fctCart->first_name . ' ' . $fctCart->last_name);
if (!$fullName && $contact) {
$fullName = trim($contact->first_name . ' ' . $contact->last_name);
}
// Build a per-coupon breakdown (code + discounted value) for the cart details view.
// FluentCart stores the applied codes on $fctCart->coupons and the amount each code
// saved (in cents) on checkout_data.__per_coupon_discounts, keyed by code.
$perCouponDiscounts = Arr::get($checkoutData, '__per_coupon_discounts', []);
$couponDetails = [];
foreach (($fctCart->coupons ?: []) as $couponCode) {
$couponAmount = (int)Arr::get($perCouponDiscounts, $couponCode, 0);
$couponDetails[] = [
'code' => $couponCode,
'discount' => number_format($couponAmount / 100, 2, '.', ''),
];
}
// Snapshot the FluentCart data as-is for easy restore
$data = [
'cart_hash' => $fctCart->cart_hash,
'full_name' => $fullName,
'email' => $billingEmail,
'provider' => 'fluent_cart',
'user_id' => $fctCart->user_id,
'contact_id' => $contact ? $contact->id : null,
'order_id' => $fctCart->order_id,
'subtotal' => number_format($subtotal / 100, 2, '.', ''),
'shipping' => number_format($shippingTotal / 100, 2, '.', ''),
'discounts' => number_format($discountTotal / 100, 2, '.', ''),
'tax' => number_format($taxTotal / 100, 2, '.', ''),
'fees' => 0,
'total' => number_format($total / 100, 2, '.', ''),
'currency' => $currency,
'cart' => [
'cart_data' => $fctCart->cart_data ?: [],
'checkout_data' => $checkoutData,
'coupons' => $fctCart->coupons ?: [],
'coupons_detail' => $couponDetails,
'utm_data' => $fctCart->utm_data ?: [],
'cart_group' => $fctCart->cart_group,
'customer_data' => $this->buildCustomerData($checkoutData),
],
];
$record = $this->getCurrentRecord($billingEmail, $fctCart->cart_hash);
if (!$record) {
$data['status'] = 'draft';
$record = AbandonCartModel::create($data);
} else {
$record->fill($data);
$record->save();
}
$cookieDays = (int)apply_filters('fluent_crm/ab_cart_cookie_validity', 30);
setcookie('fc_ab_fct_cart_token', $record->checkout_key, time() + (86400 * $cookieDays), COOKIEPATH, COOKIE_DOMAIN);
}
private function buildCustomerData($checkoutData)
{
$formData = Arr::get($checkoutData, 'form_data', []);
return [
'billingAddress' => [
'first_name' => Arr::get($formData, 'billing_first_name', ''),
'last_name' => Arr::get($formData, 'billing_last_name', ''),
'address_1' => Arr::get($formData, 'billing_address_1', ''),
'address_2' => Arr::get($formData, 'billing_address_2', ''),
'postcode' => Arr::get($formData, 'billing_postcode', ''),
'city' => Arr::get($formData, 'billing_city', ''),
'state' => Arr::get($formData, 'billing_state', ''),
'country' => Arr::get($formData, 'billing_country', ''),
'phone' => Arr::get($formData, 'billing_phone', ''),
],
];
}
private function getCurrentRecord($billingEmail = null, $cartHash = null)
{
if ($cartHash) {
// Try to find by cart hash first if available
$record = AbandonCartModel::where('cart_hash', $cartHash)
->where('provider', 'fluent_cart')
->whereIn('status', ['pending', 'opt_out', 'draft', 'processing'])
->first();
if ($record) {
return $record;
}
}
// First try from the cookie
$existingToken = Arr::get($_COOKIE, 'fc_ab_fct_cart_token');
if ($existingToken) {
$record = AbandonCartModel::where('checkout_key', $existingToken)
->where('provider', 'fluent_cart')
->whereIn('status', ['pending', 'opt_out', 'draft', 'processing'])
->first();
if ($record) {
return $record;
}
}
// Try with billing email
if ($billingEmail) {
$record = AbandonCartModel::where('email', $billingEmail)
->where('provider', 'fluent_cart')
->whereIn('status', ['pending', 'opt_out', 'draft', 'processing'])
->first();
if ($record) {
return $record;
}
}
// If user logged in, try with user id
$userId = get_current_user_id();
if ($userId) {
$record = AbandonCartModel::where('user_id', $userId)
->where('provider', 'fluent_cart')
->whereIn('status', ['pending', 'opt_out', 'draft', 'processing'])
->first();
if ($record) {
return $record;
}
}
return null;
}
public function handleOrderCreated($eventData)
{
$order = Arr::get($eventData, 'order');
if (!$order) {
return;
}
$token = sanitize_text_field(Arr::get($_COOKIE, 'fc_ab_fct_cart_token', ''));
if (!$token) {
return;
}
$abCart = AbCartHelper::getAbCartByDataProps([
'checkout_key' => $token
], ['processing', 'draft']);
if (!$abCart || $abCart->provider !== 'fluent_cart') {
return;
}
$abCart->order_id = $order->id;
$abCart->save();
}
public function handleOrderPaid($eventData)
{
$order = Arr::get($eventData, 'order');
$customer = Arr::get($eventData, 'customer');
if (!$order || !$customer) {
return;
}
$abCart = AbandonCartModel::query()->where('order_id', $order->id)->where('provider', 'fluent_cart')->first();
if (!$abCart) {
$this->cancelAutomationsByCustomer($customer);
return;
}
$this->markCartAsRecovered($abCart, $order);
}
public function handleOrderStatusChanged($eventData)
{
$order = Arr::get($eventData, 'order');
$newStatus = Arr::get($eventData, 'new_status');
if (!$order || !$newStatus) {
return;
}
$abCartId = $order->getMeta('_fc_ab_cart_id');
if (!$abCartId) {
return;
}
$abCart = AbandonCartModel::find($abCartId);
if (!$abCart || $abCart->provider !== 'fluent_cart') {
return;
}
$driver = new FluentCartDriver();
if ($driver->isWinOrderStatus($newStatus)) {
if ($abCart->status !== 'recovered') {
$this->markCartAsRecovered($abCart, $order);
}
return;
}
$lostStatuses = ['failed', 'canceled'];
if (in_array($newStatus, $lostStatuses, true)) {
$this->handleCartLost($abCart, $order);
}
}
private function markCartAsRecovered($abCart, $order)
{
$deletableStatuses = ['draft', 'opt_out', 'pending'];
if (in_array($abCart->status, $deletableStatuses, true)) {
$abCart->deleteCart();
$this->deleteOtherCarts($abCart, $order);
return;
}
$recoverableStatuses = ['processing', 'lost', 'cancelled'];
if (!in_array($abCart->status, $recoverableStatuses, true)) {
return;
}
$settings = AbCartHelper::getSettings();
$subscriber = $abCart->subscriber;
if ($subscriber) {
if ($attachLists = Arr::get($settings, 'lists_on_cart_abandoned', [])) {
$subscriber->detachLists($attachLists);
}
if ($attachTags = Arr::get($settings, 'tags_on_cart_abandoned', [])) {
$subscriber->detachTags($attachTags);
}
}
$orderTotal = $order->total_amount ?? 0;
$oldStatus = $abCart->status;
$abCart->status = 'recovered';
$abCart->order_id = $order->id;
$abCart->total = $orderTotal / 100;
$abCart->recovered_at = current_time('mysql');
$abCart->save();
do_action('fluent_crm/ab_cart_fluent_cart_recovered', $abCart, $order, $oldStatus);
$this->deleteOtherCarts($abCart, $order);
$this->handleCartRecoveredAutomations($abCart);
}
private function handleCartLost($abCart, $order)
{
if ($abCart->status == 'lost') {
return;
}
$oldStatus = $abCart->status;
$abCart->status = 'lost';
$abCart->save();
do_action('fluent_crm/ab_cart_fluent_cart_lost', $abCart, $order, $oldStatus);
if ($abCart->automation_id) {
$subscriber = $abCart->subscriber;
if ($subscriber) {
$settings = AbCartHelper::getSettings();
if ($attachLists = Arr::get($settings, 'lists_on_cart_lost', [])) {
$subscriber->attachLists($attachLists);
}
if ($attachTags = Arr::get($settings, 'tags_on_cart_lost', [])) {
$subscriber->attachTags($attachTags);
}
FunnelSubscriber::where('subscriber_id', $subscriber->id)
->where('source_ref_id', $abCart->id)
->whereHas('funnel', function ($q) {
$q->where('trigger_name', 'fc_ab_cart_simulation_fluent_cart');
})
->where('funnel_id', $abCart->automation_id)
->update([
'status' => 'cancelled',
'notes' => __('Automatically cancelled because the cart has been lost', 'fluent-crm')
]);
}
}
}
private function handleCartRecoveredAutomations($abCart)
{
if (!$abCart->automation_id) {
return;
}
$contact = $abCart->subscriber;
if (!$contact) {
return;
}
$this->cancelAutomations($contact);
}
private function cancelAutomations($subscriber)
{
FunnelSubscriber::where('subscriber_id', $subscriber->id)
->whereHas('funnel', function ($q) {
$q->where('trigger_name', 'fc_ab_cart_simulation_fluent_cart');
})
->whereIn('status', ['active', 'pending', 'paused'])
->update([
'status' => 'cancelled',
'notes' => __('Automatically cancelled because a cart has been recovered', 'fluent-crm')
]);
}
private function cancelAutomationsByCustomer($customer)
{
$subscriberIds = Subscriber::select(['id'])
->where('email', $customer->email)
->when($customer->user_id, function ($q) use ($customer) {
return $q->orWhere('user_id', $customer->user_id);
})
->pluck('id')
->toArray();
if (!$subscriberIds) {
return;
}
FunnelSubscriber::whereIn('subscriber_id', $subscriberIds)
->whereHas('funnel', function ($q) {
$q->where('trigger_name', 'fc_ab_cart_simulation_fluent_cart');
})
->whereIn('status', ['active', 'pending', 'paused'])
->update([
'status' => 'cancelled',
'notes' => __('Automatically cancelled because a cart has been recovered', 'fluent-crm')
]);
}
private function deleteOtherCarts($abCart, $order)
{
$customerEmail = $abCart->email;
$customerId = 0;
if (method_exists($order, 'getAttribute')) {
$customerId = $order->customer_id ?? 0;
}
$query = AbandonCartModel::where('provider', 'fluent_cart')
->where('id', '!=', $abCart->id)
->whereIn('status', ['processing', 'draft']);
$query->where(function ($q) use ($customerEmail, $customerId) {
$q->where('email', $customerEmail);
if ($customerId) {
// Look up user_id from the FluentCart customer
$userId = fluentCrmDb()->table('fct_customers')
->where('id', $customerId)
->value('user_id');
if ($userId) {
$q->orWhere('user_id', $userId);
}
}
});
$otherCarts = $query->get();
foreach ($otherCarts as $cart) {
$cart->deleteCart();
}
}
public function maybeRestoreCart($data)
{
$cartHash = sanitize_text_field(Arr::get($data, 'fc_ab_hash', ''));
$abandonCart = null;
if ($cartHash) {
$abandonCart = AbandonCartModel::where('checkout_key', $cartHash)->first();
}
if (!$abandonCart || $abandonCart->status != 'processing' || $abandonCart->provider != 'fluent_cart') {
do_action('fluent_crm/ab_cart_restore_failed', $abandonCart);
$checkoutUrl = home_url();
if (class_exists('\FluentCart\Api\StoreSettings')) {
$checkoutUrl = (new \FluentCart\Api\StoreSettings())->getCheckoutPage() ?: $checkoutUrl;
}
wp_redirect($checkoutUrl);
exit();
}
// Set tracking cookie
$cookieDays = (int)apply_filters('fluent_crm/ab_cart_cookie_validity', 30);
setcookie('fc_ab_fct_cart_token', $abandonCart->checkout_key, time() + (86400 * $cookieDays), COOKIEPATH, COOKIE_DOMAIN);
$abandonCart->click_counts = $abandonCart->click_counts + 1;
$abandonCart->save();
// Restore the FluentCart cart from our snapshot
$snapshot = $abandonCart->cart;
$fctCartHash = $abandonCart->cart_hash;
if ($fctCartHash) {
$fctCart = \FluentCart\App\Models\Cart::where('cart_hash', $fctCartHash)->first();
if ($fctCart) {
// just redirect to checkout if the cart still exists in FluentCart
$checkoutUrl = add_query_arg([
'fct_cart_hash' => $fctCart->cart_hash,
], (new StoreSettings())->getCheckoutPage());
wp_redirect($checkoutUrl);
exit();
}
}
$newCart = new Cart();
$newCart->cart_hash = $abandonCart->cart_hash ?: Cart::generateCartHash();
// Write the snapshot back directly
$newCart->cart_data = Arr::get($snapshot, 'cart_data', []);
$newCart->checkout_data = Arr::get($snapshot, 'checkout_data', []);
$newCart->coupons = Arr::get($snapshot, 'coupons', []);
$newCart->email = $abandonCart->email;
$newCart->utm_data = Arr::get($snapshot, 'utm_data', []);
$newCart->cart_group = 'instant';
$newCart->ip_address = AddressHelper::getIpAddress();
$newCart->user_agent = AddressHelper::getUserAgent();
$fullName = $abandonCart->full_name;
if ($fullName) {
// Try to split full name into first and last name for better compatibility
$nameParts = explode(' ', $fullName, 2);
$newCart->first_name = $nameParts[0];
$newCart->last_name = isset($nameParts[1]) ? $nameParts[1] : '';
}
$newCart->save();
\FluentCart\Api\Cookie\Cookie::setCartHash($newCart->cart_hash);
$abandonCart->cart_hash = $newCart->cart_hash;
$abandonCart->save();
wp_redirect(add_query_arg(['fct_cart_hash' => $newCart->cart_hash], (new \FluentCart\Api\StoreSettings())->getCheckoutPage()));
exit();
}
public function pushContextCodes($codes, $context)
{
if ($context != 'fc_ab_cart_simulation_fluent_cart') {
return $codes;
}
$smartCodes = [
'key' => 'ab_cart_fluent_cart',
'title' => 'Abandoned Cart - FluentCart',
'shortcodes' => [
'{{ab_cart_fluent_cart.billing_email}}' => __('Cart Billing Email', 'fluent-crm'),
'{{ab_cart_fluent_cart.cart_items_table}}' => __('Cart Items', 'fluent-crm'),
'##ab_cart_fluent_cart.recovery_url##' => __('Cart Recovery URL', 'fluent-crm'),
'{{ab_cart_fluent_cart.cart_total}}' => __('Cart Total', 'fluent-crm'),
'{{ab_cart_fluent_cart.subtotal}}' => __('Cart Subtotal (only products)', 'fluent-crm'),
'{{ab_cart_fluent_cart.shipping_total}}' => __('Cart Shipping Total', 'fluent-crm'),
'{{ab_cart_fluent_cart.discount_total}}' => __('Cart Discount Total', 'fluent-crm'),
'{{ab_cart_fluent_cart.coupon_codes}}' => __('Applied Coupon Codes', 'fluent-crm'),
'{{ab_cart_fluent_cart.tax_total}}' => __('Cart Tax Total', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_full_name}}' => __('Billing Full Name', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_address}}' => __('Billing Address', 'fluent-crm'),
'{{ab_cart_fluent_cart.shipping_address}}' => __('Shipping Address', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_city}}' => __('Billing City', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_state}}' => __('Billing State', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_postcode}}' => __('Billing Postcode', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_country}}' => __('Billing Country', 'fluent-crm'),
'{{ab_cart_fluent_cart.billing_phone}}' => __('Billing Phone', 'fluent-crm'),
]
];
$codes[] = $smartCodes;
return $codes;
}
public function parseSmartCodes($code, $valueKey, $defaultValue, $subscriber)
{
$abCart = null;
if ($subscriber->funnel_subscriber_id) {
$funnelSub = FunnelSubscriber::find($subscriber->funnel_subscriber_id);
if ($funnelSub) {
$abCart = AbandonCartModel::find($funnelSub->source_ref_id);
}
}
if (!$abCart) {
$abCart = AbandonCartModel::where('email', $subscriber->email)
->where('provider', 'fluent_cart')
->whereIn('status', ['processing', 'opt_out', 'lost'])
->orderBy('id', 'DESC')
->first();
}
if (!$abCart && defined('FLUENTCRM_PREVIEWING_EMAIL')) {
$abCart = AbandonCartModel::where('provider', 'fluent_cart')
->orderBy('id', 'DESC')
->first();
}
if (!$abCart) {
if (defined('FLUENTCRM_PREVIEWING_EMAIL')) {
return __('Dynamic Text will be available on real email', 'fluent-crm');
}
return $defaultValue;
}
$formatPrice = function ($amount) use ($abCart) {
$driver = new FluentCartDriver();
return $driver->formatPrice($amount, $abCart->currency);
};
switch ($valueKey) {
case 'billing_email':
return $abCart->email;
case 'cart_total':
return $formatPrice($abCart->total);
case 'subtotal':
return $formatPrice($abCart->subtotal);
case 'shipping_total':
return $abCart->shipping ? $formatPrice($abCart->shipping) : $defaultValue;
case 'discount_total':
return ($abCart->discounts > 0) ? $formatPrice($abCart->discounts) : $defaultValue;
case 'coupon_codes':
$couponCodes = Arr::get($abCart->cart, 'coupons', []);
return $couponCodes ? implode(', ', $couponCodes) : $defaultValue;
case 'tax_total':
return $abCart->tax ? $formatPrice($abCart->tax) : $defaultValue;
case 'billing_full_name':
return $abCart->full_name ?: $defaultValue;
case 'billing_address':
case 'shipping_address':
$prefix = ($valueKey === 'shipping_address') ? 'shipping_' : 'billing_';
$formData = Arr::get($abCart->cart, 'checkout_data.form_data', []);
return implode(', ', array_filter([
Arr::get($formData, $prefix . 'address_1'),
Arr::get($formData, $prefix . 'address_2'),
Arr::get($formData, $prefix . 'city'),
Arr::get($formData, $prefix . 'state'),
Arr::get($formData, $prefix . 'postcode'),
])) ?: $defaultValue;
case 'billing_city':
case 'billing_state':
case 'billing_postcode':
case 'billing_country':
case 'billing_phone':
return Arr::get($abCart->cart, 'checkout_data.form_data.' . $valueKey, $defaultValue);
case 'recovery_url':
return add_query_arg([
'fluentcrm' => 1,
'route' => 'general',
'handler' => 'fc_cart_fluent_cart',
'fc_ab_hash' => $abCart->checkout_key
], home_url());
case 'cart_items_table':
return $abCart->getCartItemsHtml();
default:
return apply_filters('fluent_crm/ab_cart_smart_code_default_value', $defaultValue, $valueKey, $abCart);
}
}
}