Files
medicalalert-web-reloaded/wp/wp-content/themes/medicalalert/helpers/WooHelper.php
2024-12-02 13:02:50 -05:00

1358 lines
47 KiB
PHP

<?php
/**
* WooCommerce Support
*/
add_action('after_setup_theme', function () {
add_theme_support('woocommerce');
add_theme_support('wc-product-gallery-zoom');
add_theme_support('wc-product-gallery-lightbox');
add_theme_support('wc-product-gallery-slider');
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0);
/* Disable all payment gateways at checkout */
add_filter('woocommerce_cart_needs_payment', '__return_false');
// Disable different woocommerce notifications
add_filter('woocommerce_cart_item_removed_notice_type', '__return_false');
add_filter('wc_add_to_cart_message_html', '__return_false');
// when a new item gets added to the cart, empty the cart of previous items
// and purge add ons
add_filter('woocommerce_add_to_cart_validation', function ($passed, $product_id, $quantity) {
if (!WC()->cart->is_empty()) {
WC()->cart->empty_cart();
}
$_SESSION["addOns"] = [];
$_SESSION["one-time"] = [];
return $passed;
}, 20, 3);
add_filter('woocommerce_checkout_fields', function ($fields) {
// $fields['order']['order_comments']['placeholder'] = 'My new placeholder';
return $fields;
});
});
// WooCommerce Fee Stuff
// first, wordpress doesn't use sessions, so let's enable those
add_action('init', function () {
if (!session_id()) {
session_start();
}
});
// and clean up sessions on logout
add_action('wp_logout', function () {
session_destroy();
});
// $_SESSION values are set on the cart page
/**
* Allow only one coupon per order in WooCommerce.
*/
add_filter('woocommerce_apply_individual_use_coupon', 'only_one_coupon_allowed', 10, 2);
function only_one_coupon_allowed($apply, $coupon) {
// Check if a coupon is already applied
if (WC()->cart->has_discount()) {
// Remove other applied coupons except the current one
WC()->cart->empty_discounts();
WC()->cart->apply_coupon($coupon->get_code());
return false; // Do not apply the new coupon
}
return $apply;
}
add_filter('woocommerce_add_error', 'customize_coupon_error_message', 10, 1);
function customize_coupon_error_message($error) {
// Check if the error message is related to a coupon already applied
if (strpos($error, 'Coupon code already applied!') !== false) {
return '';
}
return $error;
}
function get_current_shipping_comment() {
// Get the chosen shipping methods from the cart
$chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
if (empty($chosen_shipping_methods)) {
return null; // No shipping methods selected
}
// Loop through chosen shipping methods to find their settings
foreach ($chosen_shipping_methods as $chosen_method) {
$method_parts = explode(':', $chosen_method); // Split method ID and instance ID
$shipping_method_id = $method_parts[0];
$instance_id = isset($method_parts[1]) ? $method_parts[1] : '';
// Build the option name for the instance-specific settings
$option_name = 'woocommerce_' . $shipping_method_id . '_' . $instance_id . '_settings';
$instance_settings = get_option($option_name);
// Check if `shipping_comment` exists
if (!empty($instance_settings) && isset($instance_settings['shipping_comment'])) {
return $instance_settings['shipping_comment']; // Return the first found Salesforce ID
}
}
return null; // No `shipping_comment` found
}
/**
* Generates a cart summary with accurate total calculation and full details
*
* @param bool $showCheckoutButton Whether to show the checkout button
* @return string Rendered cart summary
*/
function generateCartSummary($showCheckoutButton = true) {
global $product;
// Ensure WooCommerce calculates all totals
WC()->cart->calculate_totals();
$cartItem = getFirstCartItem();
$parentName = $cartItem['data']->get_parent_data()['title'];
$product = getProductDetails($cartItem["product_id"]);
$ratePlan = getRatePlan();
$rateMultiplier = ($ratePlan === 'Annually') ? 12 : (($ratePlan === 'Semi-Annually') ? 6 : 1);
// Base product pricing
$basePrice = $cartItem['data']->get_regular_price();
$isSmartwatch = ($parentName === "Smartwatch");
// Setup fee setup
$setupFeeName = $isSmartwatch ? "Device Fee" : "Setup Fee";
$setupFee = $isSmartwatch ? 159.00 : 99.95;
$isAarpMember = WC()->session->get('aarp_discount') === true;
$activationDiscount = 0;
if ($isAarpMember && !$isSmartwatch) {
$discountedMonthlyRate = round($base_price * 0.85, 2);
$setupFee = 99.95;
$activationDiscount = 50.00;
} else {
$discountedMonthlyRate = $base_price;
}
// Apply AARP discount if eligible
$discountedMonthlyRate = $isAarpMember ? round($basePrice * 0.85, 2) : $basePrice;
$variable_price = round($discountedMonthlyRate * $rateMultiplier, 2);
// Setup Fee & Activation Discount
//$setupFee = 99.95;
$activationDiscount = ($isAarpMember && $parentName !== 'Smartwatch') ? 50.00 : 0;
// Professional Install Check and Cost
$professionalInstallLabel = $_SESSION['one-time']['Professional Install']['label'] ?? '';
$professionalInstallCost = $_SESSION['one-time']['Professional Install']['price'] ?? 0;
// Add-ons and their total price calculation
$totalAddonPrice = 0;
$adjustedAddons = [];
$addonLabels = [];
if (isset($_SESSION['addOns']) && is_array($_SESSION['addOns'])) {
foreach ($_SESSION['addOns'] as $addOn) {
$addOnLabel = $addOn['label'];
$addOnPrice = ($addOnLabel === 'Key Lockbox' && $ratePlan === 'Annually') ? 0 : $addOn['price'] * $rateMultiplier;
if (!in_array($addOnLabel, $addonLabels)) {
$adjustedAddons[] = ['name' => $addOnLabel, 'price' => $addOnPrice];
$addonLabels[] = $addOnLabel;
$totalAddonPrice += $addOnPrice;
}
}
}
// Determine if free shipping applies
$defaultShippingCost = 29.95;
$freeShippingApplied = $isAarpMember || ($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually') || $professionalInstallCost > 0;
$finalShippingCost = $freeShippingApplied ? 0 : $defaultShippingCost;
// Calculate total cart value
$totalCart = round($variable_price + $setupFee + $professionalInstallCost + $totalAddonPrice + $finalShippingCost - $activationDiscount, 2);
// Retrieve applied coupons
$couponSummary = [];
$couponDescription = [];
foreach (WC()->cart->get_applied_coupons() as $coupon_code) {
$coupon = new WC_Coupon($coupon_code);
$couponSummary[] = $coupon_code;
$couponDescription[] = $coupon->get_description();
}
$chosen_method = WC()->session->get('chosen_shipping_methods')[0] ?? '';
error_log('Chosen Method: ' . $chosen_method);
$shipping_comment = get_current_shipping_comment();
if ($shipping_comment) {
error_log('Current shipping comment (Salesforce ID): ' . $shipping_comment);
} else {
error_log('No shipping comment found for the currently applied shipping method.');
}
// Render with original structure and components
return site()->render("cart_summary", array_merge($product, [
"variation" => $ratePlan,
'variable_price' => $variable_price,
'addonPrice' => $totalAddonPrice,
'adjustedAddons' => $adjustedAddons,
'fallDetectionLabel' => getAddonLabel('Fall Detection'),
'fallDetectionPrice' => getAddonPrice('Fall Detection') * $rateMultiplier,
'protectionPlan' => getAddonLabel('Protection Plan'),
'protectionPlanprice' => getAddonPrice('Protection Plan') * $rateMultiplier,
'keyLockboxlabel' => getAddonLabel('Key Lockbox'),
'keylockboxprice' => ($ratePlan === 'Annually') ? 0 : getAddonPrice('Key Lockbox') * $rateMultiplier,
'one-time' => $professionalInstallLabel,
'pro-one-time' => $professionalInstallCost,
'setupFeeName' => $setupFeeName,
'activationFeeAmount' => $setupFee,
'activationDiscount' => $activationDiscount > 0 ? -$activationDiscount : null,
'defaultShipping' => $defaultShippingCost,
'freeShipping' => $freeShippingApplied ? $defaultShippingCost : null,
'totalDue' => $totalCart,
'couponList' => implode(', ', $couponSummary),
'couponDescription' => implode('<br>', array_filter($couponDescription)),
'showCheckoutButton' => $showCheckoutButton,
]));
}
/**
* Add custom fees to WooCommerce order based on cart items and conditions.
*
* @param WC_Order $order WooCommerce order object.
* @param array $data Additional data for the order.
*/
function add_custom_meta_to_order($order, $data) {
$existingFees = array_map(function ($fee) {
return sanitize_title($fee->get_name());
}, $order->get_items('fee'));
$cartItem = getFirstCartItem();
if (!$cartItem) return;
$parentName = $cartItem['data']->get_parent_data()['title'];
$isSmartwatch = ($parentName === "Smartwatch");
// Determine fee name and amount
$feeName = $isSmartwatch ? "Device Fee" : "Setup Fee";
$feeAmount = $isSmartwatch ? 159.00 : 99.95;
// Add Device/Setup Fee
if (!in_array(sanitize_title($feeName), $existingFees)) {
$feeItem = new WC_Order_Item_Fee();
$feeItem->set_name($feeName);
$feeItem->set_total($feeAmount);
$order->add_item($feeItem);
}
// Professional Install Fee
$proInstall = $_SESSION["one-time"]["Professional Install"] ?? null;
if ($proInstall && !in_array(sanitize_title("Professional Install"), $existingFees)) {
$installFeeItem = new WC_Order_Item_Fee();
$installFeeItem->set_name("Professional Install");
$installFeeItem->set_total(99.00); // Specific fee amount
$order->add_item($installFeeItem);
}
// Recalculate order totals after adding fees
$order->calculate_totals();
}
add_action('woocommerce_checkout_create_order', 'add_custom_meta_to_order', 20, 2);
/**
* Retrieves the default title and cost for the "Shipping" flat rate method from WooCommerce settings.
*
* @return array|null Array containing 'title' and 'cost' if found, or null if not found.
*/
function get_default_shipping_info() {
$zones = WC_Shipping_Zones::get_zones();
$shipping_info = [
'title' => null,
'cost' => null,
];
// Iterate over each zone to find the 'flat_rate' method titled 'Shipping'
foreach ($zones as $zone) {
foreach ($zone['shipping_methods'] as $method) {
if ($method->id === 'flat_rate' && $method->title === 'Shipping') {
$shipping_info['title'] = $method->title;
// Try to retrieve the cost directly from the method's instance options
if (method_exists($method, 'get_instance_option')) {
$cost = $method->get_instance_option('cost');
if (!empty($cost)) {
$shipping_info['cost'] = $cost;
error_log("Shipping Method Title: {$shipping_info['title']}");
error_log("Shipping Method Default Cost: {$shipping_info['cost']}");
}
}
// Fallback if cost retrieval fails
$shipping_info['cost'] = 'N/A';
error_log("Shipping Method Cost not found using get_instance_option; using fallback 'N/A'.");
return $shipping_info;
}
}
}
return null;
}
/**
* Calculate the variable price based on the rate plan
*
* @param float $basePrice The base price of the product
* @param string|null $ratePlan The rate plan (e.g., "Monthly", "Semi-Annually", "Annually")
* @return float The adjusted price based on the rate plan
*/
function calculateVariablePrice($basePrice, $ratePlan) {
if (!is_numeric($basePrice)) {
return 0; // Prevent non-numeric value issues
}
switch ($ratePlan) {
case 'Annually':
return $basePrice * 12; // Annual plan = monthly price * 12
case 'Semi-Annually':
return $basePrice * 6; // Semi-annual plan = monthly price * 6
case 'Monthly':
default:
return $basePrice; // Monthly plan = base price
}
}
/**
* Get the first item in the cart
*/
function getFirstCartItem() {
foreach (WC()->cart->get_cart() as $item) {
return $item;
}
}
/**
* Retrieve product details based on ID
*/
function getProductDetails($productId) {
// Ensure regular price is fetched correctly
return site()->getPost($productId, [
"title",
"thumbnail",
"acf.activation_fee",
"acf.fee_type",
"meta._regular_price", // This field might not be necessary anymore
"shipCoupon",
"shipCouponName",
"defaultShipping",
"shippingName",
"couponList",
"couponTotal",
"activationFeeName",
"activationFeeAmount",
"defaultshippingTitle",
"defaultshippingCost",
]);
}
/**
* Calculate the monthly costs of the cart
*/
function calculateMonthlyCosts($cartContents) {
$total = 0;
foreach ($cartContents as $item) {
$total += $item['data']->get_regular_price();
}
return $total;
}
/**
* Retrieve the rate plan from the cart item's variation attributes
*
* @return string|null The rate plan, or null if not found
*/
function getRatePlan() {
$cart = WC()->cart;
foreach ($cart->get_cart() as $cart_item) {
if (isset($cart_item['variation']['attribute_rate-plan'])) {
return $cart_item['variation']['attribute_rate-plan'];
}
}
return null; // Return null if no rate plan is found
}
/**
* Retrieve applied coupons and their details
*/
function getAppliedCoupons() {
$appliedCoupons = WC()->cart->get_applied_coupons();
$couponDetails = [
'coupon_title' => '',
'coupon_amount' => 0,
'couponSummary' => '',
'coupon_description' => ''
];
foreach ($appliedCoupons as $couponCode) {
$coupon = new WC_Coupon($couponCode);
$couponDetails['coupon_title'] = $coupon->get_code();
$couponDetails['coupon_amount'] += $coupon->get_amount();
$couponDetails['coupon_description'] = $coupon->get_description();
}
return $couponDetails;
}
/**
* Calculate the total cart value based on product, monthly costs, and applied coupons
*/
function calculateTotalCart($basePrice, $activationFee, $finalShippingCost, $ratePlan) {
// Define multipliers based on the rate plan
$rateMultiplier = 1;
if ($ratePlan === "Annually") {
$rateMultiplier = 12;
} elseif ($ratePlan === "Semi-Annually") {
$rateMultiplier = 6;
}
// Calculate the variable price adjusted for the rate plan
$variablePrice = $basePrice * $rateMultiplier;
//error_log("Adjusted Variable Price for Rate Plan ($ratePlan): " . $variablePrice);
// Calculate the total cart value
$totalCart = $variablePrice + $activationFee + $finalShippingCost;
//error_log("Total Cart Before Calculation: " . $totalCart);
// Apply additional discounts or fees if necessary
// ...
//error_log("Total Cart After Calculation: " . $totalCart);
return $totalCart;
}
/**
* Get the label for a specific add-on
*/
function getAddonLabel($label) {
return $_SESSION["addOns"][$label]["label"];
}
/**
* Get the price for a specific add-on
*/
function getAddonPrice($label) {
return $_SESSION["addOns"][$label]["price"];
}
/**
* Calculate the total price for all add-ons
*/
function calculateAddonPrices() {
// Check if addOns is set and is an array
if (!isset($_SESSION["addOns"]) || !is_array($_SESSION["addOns"])) {
//error_log("Warning: \$_SESSION['addOns'] is not set or is not an array.");
return 0; // Return default price if addOns is missing or invalid
}
// Calculate total price from add-ons
$addonPrices = 0;
foreach ($_SESSION["addOns"] as $addOn) {
// Ensure each addOn has a price
if (isset($addOn["price"])) {
$addonPrices += $addOn["price"];
} else {
//error_log("Warning: Add-on missing 'price' key.");
}
}
return $addonPrices;
}
/**
* Retrieve the selected shipping type
*/
function getShippingType() {
$shippingMethodId = WC()->session->get('chosen_shipping_methods')[0];
return get_title_shipping_method_from_method_id($shippingMethodId);
}
/**
* Get the cost of shipping, providing free shipping for annual or semi-annual plans
*
* @param string|null $ratePlan The selected rate plan
* @return float Shipping cost
*/
function getShippingCost($ratePlan = null) {
// Check for Professional Install add-on in the session or cart
$proInstallSelected = isset($_SESSION["one-time"]["Professional Install"]);
// Apply free shipping for annual and semi-annual rate plans or if Professional Install is selected
if ($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually' || $proInstallSelected) {
WC()->session->set('chosen_shipping_methods', ['free_shipping']);
return 0.00;
}
$packages = WC()->shipping->get_packages();
// Check if we have shipping packages
if (!empty($packages)) {
// Get the chosen shipping method ID
$chosen_method = WC()->session->get('chosen_shipping_methods')[0] ?? '';
// Get the first package (there might be multiple in some setups)
$package = $packages[0];
// Check if the shipping method exists in the package rates
if (isset($package['rates'][$chosen_method])) {
return $package['rates'][$chosen_method]->cost;
}
}
// Fallback shipping price if none is found
return 29.95;
}
/**
* Get the discount applied through shipping coupons
*/
function getShippingDiscount() {
return WC()->cart->get_coupon_discount_totals()['shipping'] ?? 0;
}
/**
* Get the free shipping name, if any
*/
function getFreeShippingName() {
foreach (WC()->cart->get_applied_coupons() as $couponCode) {
$coupon = new WC_Coupon($couponCode);
if ($coupon->get_free_shipping()) {
return "Free Shipping";
}
}
return "";
}
/**
* Get the cost of professional install
*/
function getProfessionalInstallCost() {
return $_SESSION["one-time"]["Professional Install"]["price"] ?? 99.00;
}
function get_title_shipping_method_from_method_id( $method_rate_id = '' ){
if( ! empty( $method_rate_id ) ){
$method_key_id = str_replace( ':', '_', $method_rate_id );
$option_name = 'woocommerce_'.$method_key_id.'_settings';
return get_option( $option_name, true )['title'];
} else {
return false;
}
}
function add_administration_fees() {
WC()->cart->add_fee( 'Processing Fee', 2.5 );
}
/**
* custom woocommerce order fields
*/
$additionalWooFields = [
"subscriber_first_name" => [
"type" => "text",
"label" => "",
"placeholder" => "First Name",
"required" => true,
],
"subscriber_last_name" => [
"type" => "text",
"label" => "",
"placeholder" => "Last Name",
"required" => true,
],
"subscriber_address_1" => [
"type" => "text",
"label" => "",
"placeholder" => "Address 1",
"required" => true,
],
"subscriber_address_2" => [
"type" => "text",
"label" => "",
"placeholder" => "Address 2 (Apt, Suite, etc.)",
],
"subscriber_zip" => [
"type" => "text",
"label" => "",
"placeholder" => "Zip Code",
"required" => true,
],
"subscriber_city" => [
"type" => "text",
"label" => "",
"placeholder" => "City",
"required" => true,
],
"subscriber_state" => [
"type" => "text",
"label" => "",
"placeholder" => "State",
"required" => true,
],
"subscriber_email" => [
"type" => "text",
"label" => "",
"placeholder" => "Email Address",
],
"subscriber_phone" => [
"type" => "text",
"label" => "",
"placeholder" => "Phone Number",
],
"caregiver_relation" => [
"type" => "select",
"label" => "Relation",
"options" => [
"Brother" => "Brother",
"Daughter" => "Daughter",
"Father" => "Father",
"Friend" => "Friend",
"Granddaughter" => "Granddaughter",
"Grandson" => "Grandson",
"In-law" => "In-law",
"Mother" => "Mother",
"Neighbor" => "Neighbor",
"Relative" => "Relative",
"Sister" => "Sister",
"Son" => "Son",
"Spouse" => "Spouse",
"Other" => "Other",
],
"required" => true,
],
"caregiver_first_name" => [
"type" => "text",
"label" => "",
"placeholder" => "First Name",
"required" => true,
],
"caregiver_last_name" => [
"type" => "text",
"label" => "",
"placeholder" => "Last Name",
"required" => true,
],
"caregiver_email" => [
"type" => "text",
"label" => "",
"placeholder" => "Email Address",
],
"caregiver_phone" => [
"type" => "text",
"label" => "",
"placeholder" => "Phone Number",
],
"card_number" => [
"type" => "number",
"label" => "Credit Card",
"required" => true,
],
"ccv" => [
"type" => "number",
"label" => "CCV",
"required" => true,
],
"expiration_month" => [
"type" => "number",
"label" => "Expiration Month",
"required" => true,
"attrs" => ["min" => 1, "max" => 12, "step" => 1]
],
"expiration_year" => [
"type" => "number",
"label" => "Expiration Year",
"required" => true,
"attrs" => ["min" => 2022, "max" => 2032, "step" => 1]
],
"SESSpromoid" => [
"type" => "hidden",
"label" => "Promotion ID",
],
"SESSpromotion_description" => [
"type" => "hidden",
"label" => "Promotion Description",
],
"SESScoupon_code" => [
"type" => "hidden",
"label" => "Coupon Code",
],
];
add_action('woocommerce_before_checkout_billing_form', function ($checkout) use ($additionalWooFields) {
$dto = [];
foreach ($additionalWooFields as $key => $field) {
ob_start();
$customAttributes = ["v-model" => $key];
if ($field["attrs"]) {
$customAttributes = array_merge($customAttributes, $field["attrs"]);
}
woocommerce_form_field($key, [
'type' => $field["type"],
'class' => $field["classes"] ?? ['my-field-class orm-row-wide'],
'input_class' => $field["input_classes"] ?? [],
'label_class' => $field["label_classes"] ?? [],
'label' => $field["label"] ?? $key,
'required' => $field["placeholder"] ?? false,
'placeholder' => $field["placeholder"] ?? "",
'options' => $field["options"] ?? [],
'custom_attributes' => $customAttributes,
], $checkout->get_value($key));
$fieldHTML = ob_get_contents();
ob_end_clean();
$dto[$key] = $fieldHTML;
}
echo site()->render("checkout-step-1", $dto);
});
function showCardFields()
{
global $additionalWooFields;
$dto = [];
foreach ($additionalWooFields as $key => $field) {
if (!in_array($key, ["card_number", "ccv", "expiration_month", "expiration_year"])) {
continue;
}
ob_start();
$customAttributes = ["v-model" => $key];
if ($field["attrs"]) {
$customAttributes = array_merge($customAttributes, $field["attrs"]);
}
woocommerce_form_field($key, [
'type' => $field["type"],
'class' => $field["classes"] ?? ['my-field-class orm-row-wide'],
'input_class' => $field["input_classes"] ?? [],
'label_class' => $field["label_classes"] ?? [],
'label' => $field["label"] ?? $key,
'required' => $field["placeholder"] ?? false,
'placeholder' => $field["placeholder"] ?? "",
'options' => $field["options"] ?? [],
'custom_attributes' => $customAttributes,
], null);
$fieldHTML = ob_get_contents();
ob_end_clean();
$dto[$key] = $fieldHTML;
}
echo site()->render("card-fields", $dto);
}
add_action('woocommerce_checkout_update_order_meta', function ($orderID) use ($additionalWooFields) {
foreach ($additionalWooFields as $key => $field) {
if (isset($_POST[$key])) {
$value = esc_attr($_POST[$key]);
if ($key === "card_number") {
$parts = str_split($value);
$output = "";
for ($i = 0; $i < count($parts); $i++) {
if ($i < count($parts) - 4) {
$output .= "*";
} else {
$output .= $parts[$i];
}
}
$value = $output;
}
update_post_meta($orderID, $key, $value);
}
}
});
add_action('woocommerce_admin_order_data_after_shipping_address', function ($order) use ($additionalWooFields) {
$dto = [
"subscriber-data" => [],
"caregiver-data" => [],
];
foreach ($additionalWooFields as $key => $field) {
$meta = get_post_meta($order->get_id(), $key, true);
$dataType = (substr($key, 0, 10) === "subscriber") ? "subscriber-data" : "caregiver-data";
$dto[$dataType][] = [
"label" => $field["label"] ? $field["label"] : $field["placeholder"],
"value" => $meta ?: "",
];
}
echo site()->render("order_details_in_admin", $dto);
});
add_filter( 'woocommerce_order_shipping_to_display_shipped_via', '__return_false' );
/**
* Update order emails to include all the extra stuff
*/
add_filter('woocommerce_email_order_meta_fields', function ($fields, $sent_to_admin, $order) use ($additionalWooFields) {
foreach ($additionalWooFields as $key => $value) {
$fields[$key] = [
'label' => strlen($value["label"]) ? $value["label"] : $value["placeholder"],
'value' => get_post_meta($order->get_id(), $key, true),
];
}
if (count($order->get_coupon_codes())) {
$fields["applied_coupons"] = [
"label" => "Applied Coupons",
"value" => implode(", ", $order->get_coupon_codes()),
];
}
return $fields;
}, 10, 3);
// Apply Rate Multiplier and AARP Discount to Each Cart Item
add_action('woocommerce_before_calculate_totals', 'apply_multiplier_and_discount_to_cart_items', 10, 1);
function apply_multiplier_and_discount_to_cart_items($cart) {
// Exit if in the admin area or cart is empty
if (is_admin() || !did_action('woocommerce_before_calculate_totals') || $cart->is_empty()) {
return;
}
// Determine the rate plan and AARP discount status
$rate_plan = getRatePlan();
$is_aarp_discount = WC()->session->get('aarp_discount') === true;
// Define the rate multiplier based on the rate plan
$rate_multiplier = 1;
if ($rate_plan === 'Annually') {
$rate_multiplier = 12;
} elseif ($rate_plan === 'Semi-Annually') {
$rate_multiplier = 6;
}
// Loop through each cart item and adjust the price based on the rate multiplier and AARP discount
foreach ($cart->get_cart() as $cart_item) {
$base_price = $cart_item['data']->get_regular_price();
// Calculate the discounted monthly rate, rounding to two decimal places
$discounted_monthly_rate = $is_aarp_discount ? round($base_price * 0.85, 2) : $base_price;
// Calculate the final adjusted price by multiplying the monthly rate by the rate multiplier
$adjusted_price = $discounted_monthly_rate * $rate_multiplier;
// Set the adjusted price
$cart_item['data']->set_price(round($adjusted_price, 2));
}
}
// Apply Setup Fee, AARP Discount, Conditional Free Shipping, and Add-ons in Cart
add_action('woocommerce_cart_calculate_fees', 'apply_custom_fees_and_discounts');
function apply_custom_fees_and_discounts() {
// Clear previous fees to prevent duplication
WC()->cart->fees_api()->remove_all_fees();
// Fetch rate plan and AARP status
$ratePlan = getRatePlan();
$isAarpMember = WC()->session->get('aarp_discount') === true;
// Set up rate multiplier based on the rate plan
$rateMultiplier = ($ratePlan === 'Annually') ? 12 : (($ratePlan === 'Semi-Annually') ? 6 : 1);
// Retrieve the first cart item
$cartItem = getFirstCartItem();
if (!$cartItem) return;
$parentName = $cartItem['data']->get_parent_data()['title'];
$basePrice = $cartItem['data']->get_regular_price();
$isSmartwatch = ($parentName === 'Smartwatch');
// Calculate setup fee
$setupFee = $isSmartwatch ? 159.00 : 99.95;
// Calculate discounted price for AARP members
$discountedPrice = $isAarpMember ? round($basePrice * 0.85, 2) : $basePrice;
$totalDiscountedPrice = $discountedPrice * $rateMultiplier;
// Apply Setup Fee
WC()->cart->add_fee($isSmartwatch ? 'Device Fee' : 'Setup Fee', $setupFee);
// Apply activation discount if applicable
$activationDiscount = ($isAarpMember && !$isSmartwatch) ? 50.00 : 0;
if ($activationDiscount > 0) {
WC()->cart->add_fee('Free Activation', -$activationDiscount);
}
// Calculate and add add-ons fees
if (isset($_SESSION["addOns"]) && is_array($_SESSION["addOns"])) {
foreach ($_SESSION["addOns"] as $addOn) {
$addOnLabel = $addOn["label"];
$addOnPrice = ($addOnLabel === "Key Lockbox" && $ratePlan === "Annually") ? 0 : $addOn["price"] * $rateMultiplier;
WC()->cart->add_fee($addOnLabel, $addOnPrice);
}
}
// Free shipping logic for AARP members, eligible rate plans, or Professional Install
$hasProfessionalInstall = isset($_SESSION["one-time"]["Professional Install"]);
$packages = WC()->shipping()->get_packages();
if (!empty($packages) && !empty($packages[0]['rates'])) {
if (($ratePlan === 'Annually' || $ratePlan === 'Semi-Annually' || $isAarpMember || $hasProfessionalInstall) && isset($packages[0]['rates']['free_shipping:1'])) {
WC()->session->set('chosen_shipping_methods', ['free_shipping:1']);
} elseif ($ratePlan === 'Monthly' && isset($packages[0]['rates']['flat_rate:2'])) {
WC()->session->set('chosen_shipping_methods', ['flat_rate:2']);
}
}
}
// Force WooCommerce to recalculate totals after adjusting line items
add_action('woocommerce_checkout_create_order', 'force_recalculate_order_totals', 20, 1);
function force_recalculate_order_totals($order) {
$order->calculate_totals();
}
add_action('woocommerce_checkout_update_order_meta', 'save_card_details_to_order_meta');
function save_card_details_to_order_meta($order_id) {
if (isset($_POST['card_number']) && !empty($_POST['card_number'])) {
$card_number = sanitize_text_field($_POST['card_number']);
update_post_meta($order_id, '_card_number', $card_number);
$card_type = detect_card_type($card_number);
if ($card_type) {
update_post_meta($order_id, '_card_type', $card_type);
}
}
if (isset($_POST['expiration_month']) && !empty($_POST['expiration_month'])) {
$expiration_month = sanitize_text_field($_POST['expiration_month']);
update_post_meta($order_id, '_expiration_month', $expiration_month);
}
if (isset($_POST['expiration_year']) && !empty($_POST['expiration_year'])) {
$expiration_year = sanitize_text_field($_POST['expiration_year']);
update_post_meta($order_id, '_expiration_year', $expiration_year);
}
}
/**
* Function to detect card type based on the card number.
*/
function detect_card_type($number) {
$number = preg_replace('/\D/', '', $number);
$patterns = [
'Visa' => '/^4[0-9]{12}(?:[0-9]{3})?$/',
'MasterCard' => '/^5[1-5][0-9]{14}$/',
'American Express' => '/^3[47][0-9]{13}$/',
'Discover' => '/^6(?:011|5[0-9]{2})[0-9]{12}$/'
];
foreach ($patterns as $type => $pattern) {
if (preg_match($pattern, $number)) {
return $type;
}
}
return null;
}
add_action('woocommerce_thankyou', function ($order_id) {
$card_number = get_post_meta($order_id, '_card_number', true);
//error_log("Card Number: " . $card_number);
$order = wc_get_order($order_id);
$order_data = [];
foreach ($order->get_items() as $item) {
$item_data = $item->get_data();
$formatted_meta_data = $item->get_formatted_meta_data('_', true);
$order_data['items'][] = [
'name' => $item->get_name(),
'product_id' => $item->get_product_id(),
'quantity' => $item->get_quantity(),
'subtotal' => $item->get_subtotal(),
'total' => $item->get_total(),
];
}
$order_products = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$product_id = $product->get_id();
$product_sku = $product->get_sku();
$quantity = $item->get_quantity();
$rate_plan_id = null;
$attributes = [];
if ($product->is_type('variation')) {
$parent_id = $product->get_parent_id(); // Get the parent variable product ID
$attributes = $product->get_attributes(); // Get variation attributes
//var_dump($attributes['rate-plan-sfid']);
// Get Rate Plan ID custom field for the variation
$rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true); // Adjust if needed
$variation_label = implode(', ', $attributes);
} else {
// For non-variation products, still fetch Rate Plan ID if it exists
$rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true);
}
}
$fees_total = 0;
foreach ($order->get_fees() as $fees) {
$order_data['fees'][] = [
'name' => $fees->get_name(),
'amount' => $fees->get_amount(),
];
$fees_total += $fees->get_amount();
}
foreach ($order->get_coupon_codes() as $coupon_code) {
$coupon = new WC_Coupon($coupon_code);
$order_data['coupons'][] = [
'code' => $coupon_code,
'discount_amount' => $coupon->get_amount(),
'remaining_usage' => ($coupon->get_usage_limit_per_user() - $coupon->get_usage_count())
];
}
// Shipping and Coupon Amount Calculation
if ($order->get_shipping_total() == 0) {
$shipping_label = 'Free Shipping';
$shipping_cost = 0;
} else {
$shipping_label = 'Shipping';
$shipping_cost = $order->get_shipping_total();
}
$order_data['shipping'] = [
'label' => $shipping_label,
'cost' => $shipping_cost
];
// Total and Subtotal Data
$order_total = (float)$order->get_total();
$order_subtotal = (float)$order->get_subtotal();
$coupon_total = (float)$order->get_discount_total();
$order_data['totals'] = [
'subtotal' => $order_subtotal,
'total' => $order_total,
'discount' => $coupon_total
];
// Send the order data to Salesforce with encryption
$request_payload = createOrderRequest($order, $card_number);
// Create a new instance of the SalesforceSync class and send the request
$sf = new SalesforceSync(SalesforceSync::kACTION_ORDER_CREATE, $request_payload);
// Send the request and log the response
$response = $sf->sendRequest();
// Log the raw response from Salesforce for debugging
//error_log('Salesforce Response (Raw): ' . print_r($response, true));
// Decode the response (assuming it is double-encoded JSON)
$decoded_response = json_decode(json_decode($response));
// Check if there are errors in the decoded response and log them
if (isset($decoded_response->ErrorList)) {
$error_response = serialize($decoded_response->ErrorList);
//error_log('Salesforce API Error: ' . $error_response);
} else {
// Log the successful response if no errors are present
//error_log('Salesforce Response (Decoded): ' . print_r($decoded_response, true));
}
// Render the order details on the thank-you page
echo site()->render("thank-you-order-details", [
"setupFeePrice" => $fees_total,
"setupFeeName" => isset($order_data['fees'][0]['name']) ? $order_data['fees'][0]['name'] : '',
"couponCode" => isset($order_data['coupons'][0]['code']) ? $order_data['coupons'][0]['code'] : '',
"couponAmount" => $coupon_total,
"monthlyFee" => $order_subtotal,
"shippingLabel" => $shipping_label,
"shippingCost" => $shipping_cost,
"freeshippingCost" => ($shipping_cost == 0) ? 'Free' : '',
"items" => array_map(function ($i) {
return [
"name" => $i['name'],
"image" => wc_get_product($i['product_id'])->get_image([100, 100]), // Get product image
];
}, $order_data['items']),
"total" => $order_total,
"fees" => $order_data['fees']
]);
});
/**
* Retrieve accessories data for a product.
*/
function getProductAccessories($product_id) {
$accessories = get_field('accessories', $product_id);
$formatted_accessories = [];
if (!empty($accessories)) {
foreach ($accessories as $accessory) {
$formatted_accessories[] = [
"AccessoryID" => $accessory['salesforce_id'],
"Quantity" => 1,
"Price" => $accessory['price']
];
}
}
return $formatted_accessories;
}
/**
* Creates the payload for the order to send to Salesforce.
*/
function createOrderRequest($order) {
$shipping_comment = get_current_shipping_comment();
// Retrieve card type from order meta
$card_type = get_post_meta($order->get_id(), '_card_type', true);
// Retrieve other payment information from the order if needed
$card_number = get_post_meta($order->get_id(), '_card_number', true);
$expiration_month = get_post_meta($order->get_id(), '_expiration_month', true);
$expiration_year = get_post_meta($order->get_id(), '_expiration_year', true);
// Create the expiration date in the required format (e.g., "MM/YYYY")
$expiration_date = sprintf('%02d/%s', $expiration_month, $expiration_year);
// Generate the request header
$header = createRequestHeader();
// Get billing and shipping information from the order
$billing = $order->get_address('billing');
$shipping = $order->get_address('shipping');
$payment_type = "Credit Card"; // Assuming credit card
// Format phone number (example: XXX-XXX-XXXX)
$billing_phone = preg_replace('/(\d{3})(\d{3})(\d{4})/', '$1-$2-$3', $billing['phone']);
$shipping_phone = !empty($shipping['phone']) ? preg_replace('/(\d{3})(\d{3})(\d{4})/', '$1-$2-$3', $shipping['phone']) : $billing_phone;
// Prepare product items and accessories
$order_products = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product(); // Get the WC_Product object
$product_id = $product->get_id();
$product_sku = $product->get_sku();
$quantity = $item->get_quantity();
$rate_plan_id = null;
$attributes = [];
$parent_id = $product->get_parent_id(); // Get the parent variable product ID
$attributes = $product->get_attributes(); // Get variation attributes
// Get Rate Plan ID custom field for the variation
$rate_plan_id = get_post_meta($product_id, 'rate_plan_id', true);
// Include additional variation details
$variation_label = implode(', ', $attributes);
// Fetch accessories related to this product
$accessories = getProductAccessories($item->get_product_id());
//error_log( print_r($accessories, true) );
// Add variation or product details to the order products array
$order_products[] = [
'ProductID' => $product_sku,
'Quantity' => $item->get_quantity(),
'RatePlanID' => $attributes['rate-plan-sfid'],
'Accessories' => $accessories,
'PromotionID' => $promotion_id
];
}
// Create the payload structure
$orderRequest = [
"RequestHeader" => $header,
"RequestBody" => [
"CustomerFirstName" => $billing['first_name'],
"CustomerLastName" => $billing['last_name'],
"CustomerEmail" => $billing['email'],
"CustomerPhoneNumber" => $billing_phone,
"GCLID" => "",
"UserExperience" => null,
"CustomField1" => "",
"CustomField2" => "",
"CustomField3" => "",
"CustomField4" => "",
"MarketingCampaign" => "ecom campaign",
"ShippingID" => $shipping_comment,
"PaymentInformation" => [
"PaymentType" => $payment_type,
"CardholderName" => $billing['first_name'] . ' ' . $billing['last_name'],
"CardType" => $card_type,
"CardNumber" => $card_number,
"ExpirationDate" => $expiration_date
],
"ShippingInformation" => [
"FirstName" => $shipping['first_name'],
"LastName" => $shipping['last_name'],
"Phone" => $shipping_phone,
"Street1" => $shipping['address_1'],
"Street2" => $shipping['address_2'],
"City" => $shipping['city'],
"State" => $shipping['state'],
"PostalCode" => $shipping['postcode'],
"Country" => $shipping['country'] == 'US' ? 'United States' : $shipping['country']
],
"BillingInformation" => [
"FirstName" => $billing['first_name'],
"LastName" => $billing['last_name'],
"Phone" => $billing_phone,
"Street1" => $billing['address_1'],
"Street2" => $billing['address_2'],
"City" => $billing['city'],
"State" => $billing['state'],
"PostalCode" => $billing['postcode'],
"Country" => $billing['country'] == 'US' ? 'United States' : $billing['country']
],
"OrderProducts" => $order_products
],
];
return $orderRequest;
}
/**
* Creates a request header with a unique ID.
*/
function createRequestHeader() {
return [
"RequestID" => "Request_" . microtime(true)
];
}
if (!class_exists("SalesforceSync")) {
class SalesforceSync {
const kACTION_ORDER_CREATE = "CreateOrder";
const kAPPEND_URL = "?brand=MedicalAlert";
private $url;
private $content;
private $method;
public function __construct($action, $content, $method = "POST") {
// Appending ?brand=MedicalAlert to the URL
$environment_url = get_option('id_api_salesforce', true);
$this->url = "{$environment_url}/{$action}" . self::kAPPEND_URL;
$this->content = $content;
$this->method = $method;
}
public function sendRequest() {
$crypto = new SecuredContent();
$encoded_content = json_encode($crypto->encode_content(json_encode($this->content)));
$request = curl_init($this->url);
curl_setopt($request, CURLOPT_CUSTOMREQUEST, $this->method);
curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $encoded_content);
curl_setopt($request, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($encoded_content),
]);
// Execute the request and retrieve the response
$response = curl_exec($request);
curl_close($request);
// Decode the encrypted response
return $crypto->decode_content($response);
}
}
}
// Ensure only one item in the cart
add_filter('woocommerce_add_cart_item_data', 'restrict_cart_to_one_item', 10, 3);
function restrict_cart_to_one_item($cart_item_data, $product_id, $variation_id) {
global $woocommerce;
if (!$woocommerce->cart->is_empty()) {
unset($_SESSION["one-time"]);
unset($_SESSION["addOns"]);
$woocommerce->cart->empty_cart();
}
return $cart_item_data;
}
add_filter('woocommerce_checkout_fields', 'customize_billing_fields');
function customize_billing_fields($fields) {
unset($fields['billing']['billing_company']);
$fields['billing']['billing_first_name']['label'] = '';
$fields['billing']['billing_last_name']['label'] = '';
$fields['billing']['billing_address_1']['label'] = '';
$fields['billing']['billing_address_2']['label'] = '';
$fields['billing']['billing_city']['label'] = '';
$fields['billing']['billing_postcode']['label'] = '';
$fields['billing']['billing_phone']['label'] = '';
$fields['billing']['billing_email']['label'] = '';
$fields['billing']['billing_state']['label'] = '';
$fields['billing']['billing_state']['placeholder'] = 'Select Your State';
$fields['billing']['billing_first_name']['placeholder'] = __('First Name', 'woocommerce');
$fields['billing']['billing_last_name']['placeholder'] = __('Last Name', 'woocommerce');
$fields['billing']['billing_address_1']['placeholder'] = __('Street address', 'woocommerce');
$fields['billing']['billing_address_2']['placeholder'] = __('Apartment, suite, unit etc. (optional)', 'woocommerce');
$fields['billing']['billing_city']['placeholder'] = __('City', 'woocommerce');
$fields['billing']['billing_postcode']['placeholder'] = __('Postcode / ZIP', 'woocommerce');
$fields['billing']['billing_phone']['placeholder'] = __('Phone', 'woocommerce');
$fields['billing']['billing_email']['placeholder'] = __('Email address', 'woocommerce');
return $fields;
}
add_action('woocommerce_init', 'woocommerce_shipping_instances_form_fields_filters');
function woocommerce_shipping_instances_form_fields_filters(){
foreach( WC()->shipping->get_shipping_methods() as $shipping_method ) {
add_filter('woocommerce_shipping_instance_form_fields_' . $shipping_method->id, 'shipping_methods_additional_custom_field');
}
}
function shipping_methods_additional_custom_field( $settings ) {
$settings['shipping_comment'] = array(
'title' => __('Salesforce ID', 'woocommerce'),
'type' => 'text',
'placeholder' => __( 'Enter any additional comments for this shipping method.', 'woocommerce' ),
);
return $settings;
}
add_action( 'wp_footer', 'refresh_cart');
function refresh_cart() { ?>
<script>
(function ( $ ) {
$( document ).ready( function () {
$( document.body ).on( 'applied_coupon_in_checkout removed_coupon_in_checkout', function () {
location.reload();
} );
} );
})( jQuery );
</script>
<?php
}
// Show coupon code in cart summary
add_action("woocommerce_before_checkout_form", function () {
if (isset($_SESSION["SESScoupon_code"]) && $_SESSION["SESScoupon_code"]) {
$couponcode = strtolower($_SESSION["SESScoupon_code"]);
if (in_array(strtolower($_SESSION["SESScoupon_code"]), WC()->cart->get_applied_coupons())) {
return;
}
WC()->cart->apply_coupon($couponcode);
}
});