<?php

defined('ABSPATH') || exit;
class WC_Checkout
{
    protected static $instance = null;
    protected $fields = null;
    protected $legacy_posted_data = array();
    private $logged_in_customer = null;
    public static function instance()
    {
        if (is_null(self::$instance)) {
            self::$instance = new self();
            add_action('woocommerce_checkout_billing', array(self::$instance, 'checkout_form_billing'));
            add_action('woocommerce_checkout_shipping', array(self::$instance, 'checkout_form_shipping'));
            do_action('woocommerce_checkout_init', self::$instance);
        }
        return self::$instance;
    }
    public function __isset($key)
    {
        return in_array($key, array('enable_signup', 'enable_guest_checkout', 'must_create_account', 'checkout_fields', 'posted', 'shipping_method', 'payment_method', 'customer_id', 'shipping_methods'), true);
    }
    public function __set($key, $value)
    {
        switch ($key) {
            case 'enable_signup':
                $bool_value = wc_string_to_bool($value);
                if ($bool_value !== $this->is_registration_enabled()) {
                    remove_filter('woocommerce_checkout_registration_enabled', '__return_true', 0);
                    remove_filter('woocommerce_checkout_registration_enabled', '__return_false', 0);
                    add_filter('woocommerce_checkout_registration_enabled', $bool_value ? '__return_true' : '__return_false', 0);
                }
                break;
            case 'enable_guest_checkout':
                $bool_value = wc_string_to_bool($value);
                if ($bool_value === $this->is_registration_required()) {
                    remove_filter('woocommerce_checkout_registration_required', '__return_true', 0);
                    remove_filter('woocommerce_checkout_registration_required', '__return_false', 0);
                    add_filter('woocommerce_checkout_registration_required', $bool_value ? '__return_false' : '__return_true', 0);
                }
                break;
            case 'checkout_fields':
                $this->fields = $value;
                break;
            case 'shipping_methods':
                WC()->session->set('chosen_shipping_methods', $value);
                break;
            case 'posted':
                $this->legacy_posted_data = $value;
                break;
        }
    }
    public function __get($key)
    {
        if (in_array($key, array('posted', 'shipping_method', 'payment_method'), true) && empty($this->legacy_posted_data)) {
            $this->legacy_posted_data = $this->get_posted_data();
        }
        switch ($key) {
            case 'enable_signup':
                return $this->is_registration_enabled();
            case 'enable_guest_checkout':
                return !$this->is_registration_required();
            case 'must_create_account':
                return $this->is_registration_required() && !is_user_logged_in();
            case 'checkout_fields':
                return $this->get_checkout_fields();
            case 'posted':
                wc_doing_it_wrong('WC_Checkout->posted', 'Use $_POST directly.', '3.0.0');
                return $this->legacy_posted_data;
            case 'shipping_method':
                return $this->legacy_posted_data['shipping_method'];
            case 'payment_method':
                return $this->legacy_posted_data['payment_method'];
            case 'customer_id':
                return apply_filters('woocommerce_checkout_customer_id', get_current_user_id());
            case 'shipping_methods':
                return (array) WC()->session->get('chosen_shipping_methods');
        }
    }
    public function __clone()
    {
        wc_doing_it_wrong(__FUNCTION__, __('Cloning is forbidden.', 'woocommerce'), '2.1');
    }
    public function __wakeup()
    {
        wc_doing_it_wrong(__FUNCTION__, __('Unserializing instances of this class is forbidden.', 'woocommerce'), '2.1');
    }
    public function is_registration_required()
    {
        return apply_filters('woocommerce_checkout_registration_required', 'yes' !== get_option('woocommerce_enable_guest_checkout'));
    }
    public function is_registration_enabled()
    {
        return apply_filters('woocommerce_checkout_registration_enabled', 'yes' === get_option('woocommerce_enable_signup_and_login_from_checkout'));
    }
    public function get_checkout_fields($fieldset = '')
    {
        if (!is_null($this->fields)) {
            return $fieldset ? $this->fields[$fieldset] : $this->fields;
        }
        $billing_country = $this->get_value('billing_country');
        $billing_country = empty($billing_country) ? WC()->countries->get_base_country() : $billing_country;
        $allowed_countries = WC()->countries->get_allowed_countries();
        if (!array_key_exists($billing_country, $allowed_countries)) {
            $billing_country = current(array_keys($allowed_countries));
        }
        $shipping_country = $this->get_value('shipping_country');
        $shipping_country = empty($shipping_country) ? WC()->countries->get_base_country() : $shipping_country;
        $allowed_countries = WC()->countries->get_shipping_countries();
        if (!array_key_exists($shipping_country, $allowed_countries)) {
            $shipping_country = current(array_keys($allowed_countries));
        }
        $this->fields = array('billing' => WC()->countries->get_address_fields($billing_country, 'billing_'), 'shipping' => WC()->countries->get_address_fields($shipping_country, 'shipping_'), 'account' => array(), 'order' => array('order_comments' => array('type' => 'textarea', 'class' => array('notes'), 'label' => __('Order notes', 'woocommerce'), 'placeholder' => esc_attr__('Notes about your order, e.g. special notes for delivery.', 'woocommerce'))));
        if ('no' === get_option('woocommerce_registration_generate_username')) {
            $this->fields['account']['account_username'] = array('type' => 'text', 'label' => __('Account username', 'woocommerce'), 'required' => true, 'placeholder' => esc_attr__('Username', 'woocommerce'));
        }
        if ('no' === get_option('woocommerce_registration_generate_password')) {
            $this->fields['account']['account_password'] = array('type' => 'password', 'label' => __('Create account password', 'woocommerce'), 'required' => true, 'placeholder' => esc_attr__('Password', 'woocommerce'));
        }
        $this->fields = apply_filters('woocommerce_checkout_fields', $this->fields);
        foreach ($this->fields as $field_type => $fields) {
            uasort($this->fields[$field_type], 'wc_checkout_fields_uasort_comparison');
            foreach ($fields as $single_field_type => $field) {
                if (empty($field['label']) && !empty($field['placeholder'])) {
                    $this->fields[$field_type][$single_field_type]['label'] = $field['placeholder'];
                    $this->fields[$field_type][$single_field_type]['label_class'] = array('screen-reader-text');
                }
            }
        }
        return $fieldset ? $this->fields[$fieldset] : $this->fields;
    }
    public function check_cart_items()
    {
        do_action('woocommerce_check_cart_items');
    }
    public function checkout_form_billing()
    {
        wc_get_template('checkout/form-billing.php', array('checkout' => $this));
    }
    public function checkout_form_shipping()
    {
        wc_get_template('checkout/form-shipping.php', array('checkout' => $this));
    }
    public function create_order($data)
    {
        $order_id = apply_filters('woocommerce_create_order', null, $this);
        if ($order_id) {
            return $order_id;
        }
        try {
            $order_id = absint(WC()->session->get('order_awaiting_payment'));
            $cart_hash = WC()->cart->get_cart_hash();
            $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
            $order = $order_id ? wc_get_order($order_id) : null;
            if ($order && $order->has_cart_hash($cart_hash) && $order->has_status(array('pending', 'failed'))) {
                do_action('woocommerce_resume_order', $order_id);
                $order->remove_order_items();
            } else {
                $order = new WC_Order();
            }
            $fields_prefix = array('shipping' => true, 'billing' => true);
            $shipping_fields = array('shipping_method' => true, 'shipping_total' => true, 'shipping_tax' => true);
            foreach ($data as $key => $value) {
                if (is_callable(array($order, "set_{$key}"))) {
                    $order->{"set_{$key}"}($value);
                } elseif (isset($fields_prefix[current(explode('_', $key))])) {
                    if (!isset($shipping_fields[$key])) {
                        $order->update_meta_data('_' . $key, $value);
                    }
                }
            }
            $order->hold_applied_coupons($data['billing_email']);
            $order->set_created_via('checkout');
            $order->set_cart_hash($cart_hash);
            $order->set_customer_id(apply_filters('woocommerce_checkout_customer_id', get_current_user_id()));
            $order->set_currency(get_woocommerce_currency());
            $order->set_prices_include_tax('yes' === get_option('woocommerce_prices_include_tax'));
            $order->set_customer_ip_address(WC_Geolocation::get_ip_address());
            $order->set_customer_user_agent(wc_get_user_agent());
            $order->set_customer_note(isset($data['order_comments']) ? $data['order_comments'] : '');
            $order->set_payment_method(isset($available_gateways[$data['payment_method']]) ? $available_gateways[$data['payment_method']] : $data['payment_method']);
            $this->set_data_from_cart($order);
            do_action('woocommerce_checkout_create_order', $order, $data);
            $order_id = $order->save();
            do_action('woocommerce_checkout_update_order_meta', $order_id, $data);
            do_action('woocommerce_checkout_order_created', $order);
            return $order_id;
        } catch (Exception $e) {
            if ($order && $order instanceof WC_Order) {
                $order->get_data_store()->release_held_coupons($order);
                do_action('woocommerce_checkout_order_exception', $order);
            }
            return new WP_Error('checkout-error', $e->getMessage());
        }
    }
    public function set_data_from_cart(&$order)
    {
        $order_vat_exempt = WC()->cart->get_customer()->get_is_vat_exempt() ? 'yes' : 'no';
        $order->add_meta_data('is_vat_exempt', $order_vat_exempt, true);
        $order->set_shipping_total(WC()->cart->get_shipping_total());
        $order->set_discount_total(WC()->cart->get_discount_total());
        $order->set_discount_tax(WC()->cart->get_discount_tax());
        $order->set_cart_tax(WC()->cart->get_cart_contents_tax() + WC()->cart->get_fee_tax());
        $order->set_shipping_tax(WC()->cart->get_shipping_tax());
        $order->set_total(WC()->cart->get_total('edit'));
        $this->create_order_line_items($order, WC()->cart);
        $this->create_order_fee_lines($order, WC()->cart);
        $this->create_order_shipping_lines($order, WC()->session->get('chosen_shipping_methods'), WC()->shipping()->get_packages());
        $this->create_order_tax_lines($order, WC()->cart);
        $this->create_order_coupon_lines($order, WC()->cart);
    }
    public function create_order_line_items(&$order, $cart)
    {
        foreach ($cart->get_cart() as $cart_item_key => $values) {
            $item = apply_filters('woocommerce_checkout_create_order_line_item_object', new WC_Order_Item_Product(), $cart_item_key, $values, $order);
            $product = $values['data'];
            $item->legacy_values = $values;
            $item->legacy_cart_item_key = $cart_item_key;
            $item->set_props(array('quantity' => $values['quantity'], 'variation' => $values['variation'], 'subtotal' => $values['line_subtotal'], 'total' => $values['line_total'], 'subtotal_tax' => $values['line_subtotal_tax'], 'total_tax' => $values['line_tax'], 'taxes' => $values['line_tax_data']));
            if ($product) {
                $item->set_props(array('name' => $product->get_name(), 'tax_class' => $product->get_tax_class(), 'product_id' => $product->is_type('variation') ? $product->get_parent_id() : $product->get_id(), 'variation_id' => $product->is_type('variation') ? $product->get_id() : 0));
            }
            $item->set_backorder_meta();
            do_action('woocommerce_checkout_create_order_line_item', $item, $cart_item_key, $values, $order);
            $order->add_item($item);
        }
    }
    public function create_order_fee_lines(&$order, $cart)
    {
        foreach ($cart->get_fees() as $fee_key => $fee) {
            $item = new WC_Order_Item_Fee();
            $item->legacy_fee = $fee;
            $item->legacy_fee_key = $fee_key;
            $item->set_props(array('name' => $fee->name, 'tax_class' => $fee->taxable ? $fee->tax_class : 0, 'amount' => $fee->amount, 'total' => $fee->total, 'total_tax' => $fee->tax, 'taxes' => array('total' => $fee->tax_data)));
            do_action('woocommerce_checkout_create_order_fee_item', $item, $fee_key, $fee, $order);
            $order->add_item($item);
        }
    }
    public function create_order_shipping_lines(&$order, $chosen_shipping_methods, $packages)
    {
        foreach ($packages as $package_key => $package) {
            if (isset($chosen_shipping_methods[$package_key], $package['rates'][$chosen_shipping_methods[$package_key]])) {
                $shipping_rate = $package['rates'][$chosen_shipping_methods[$package_key]];
                $item = new WC_Order_Item_Shipping();
                $item->legacy_package_key = $package_key;
                $item->set_props(array('method_title' => $shipping_rate->label, 'method_id' => $shipping_rate->method_id, 'instance_id' => $shipping_rate->instance_id, 'total' => wc_format_decimal($shipping_rate->cost), 'taxes' => array('total' => $shipping_rate->taxes)));
                foreach ($shipping_rate->get_meta_data() as $key => $value) {
                    $item->add_meta_data($key, $value, true);
                }
                do_action('woocommerce_checkout_create_order_shipping_item', $item, $package_key, $package, $order);
                $order->add_item($item);
            }
        }
    }
    public function create_order_tax_lines(&$order, $cart)
    {
        foreach (array_keys($cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() + $cart->get_fee_taxes()) as $tax_rate_id) {
            if ($tax_rate_id && apply_filters('woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated') !== $tax_rate_id) {
                $item = new WC_Order_Item_Tax();
                $item->set_props(array('rate_id' => $tax_rate_id, 'tax_total' => $cart->get_tax_amount($tax_rate_id), 'shipping_tax_total' => $cart->get_shipping_tax_amount($tax_rate_id), 'rate_code' => WC_Tax::get_rate_code($tax_rate_id), 'label' => WC_Tax::get_rate_label($tax_rate_id), 'compound' => WC_Tax::is_compound($tax_rate_id), 'rate_percent' => WC_Tax::get_rate_percent_value($tax_rate_id)));
                do_action('woocommerce_checkout_create_order_tax_item', $item, $tax_rate_id, $order);
                $order->add_item($item);
            }
        }
    }
    public function create_order_coupon_lines(&$order, $cart)
    {
        foreach ($cart->get_coupons() as $code => $coupon) {
            $item = new WC_Order_Item_Coupon();
            $item->set_props(array('code' => $code, 'discount' => $cart->get_coupon_discount_amount($code), 'discount_tax' => $cart->get_coupon_discount_tax_amount($code)));
            $coupon_data = $coupon->get_data();
            unset($coupon_data['used_by']);
            $item->add_meta_data('coupon_data', $coupon_data);
            do_action('woocommerce_checkout_create_order_coupon_item', $item, $code, $coupon, $order);
            $order->add_item($item);
        }
    }
    protected function maybe_skip_fieldset($fieldset_key, $data)
    {
        if ('shipping' === $fieldset_key && (!$data['ship_to_different_address'] || !WC()->cart->needs_shipping_address())) {
            return true;
        }
        if ('account' === $fieldset_key && (is_user_logged_in() || !$this->is_registration_required() && empty($data['createaccount']))) {
            return true;
        }
        return false;
    }
    public function get_posted_data()
    {
        $data = array('terms' => (int) isset($_POST['terms']), 'createaccount' => (int) ($this->is_registration_enabled() ? !empty($_POST['createaccount']) : false), 'payment_method' => isset($_POST['payment_method']) ? wc_clean(wp_unslash($_POST['payment_method'])) : '', 'shipping_method' => isset($_POST['shipping_method']) ? wc_clean(wp_unslash($_POST['shipping_method'])) : '', 'ship_to_different_address' => !empty($_POST['ship_to_different_address']) && !wc_ship_to_billing_address_only(), 'woocommerce_checkout_update_totals' => isset($_POST['woocommerce_checkout_update_totals']));
        $skipped = array();
        $form_was_shown = isset($_POST['woocommerce-process-checkout-nonce']);
        foreach ($this->get_checkout_fields() as $fieldset_key => $fieldset) {
            if ($this->maybe_skip_fieldset($fieldset_key, $data)) {
                $skipped[] = $fieldset_key;
                continue;
            }
            foreach ($fieldset as $key => $field) {
                $type = sanitize_title(isset($field['type']) ? $field['type'] : 'text');
                if (isset($_POST[$key]) && '' !== $_POST[$key]) {
                    $value = wp_unslash($_POST[$key]);
                } elseif (isset($field['default']) && 'checkbox' !== $type && !$form_was_shown) {
                    $value = $field['default'];
                } else {
                    $value = '';
                }
                if ('' !== $value) {
                    switch ($type) {
                        case 'checkbox':
                            $value = 1;
                            break;
                        case 'multiselect':
                            $value = implode(', ', wc_clean($value));
                            break;
                        case 'textarea':
                            $value = wc_sanitize_textarea($value);
                            break;
                        case 'password':
                            break;
                        default:
                            $value = wc_clean($value);
                            break;
                    }
                }
                $data[$key] = apply_filters('woocommerce_process_checkout_' . $type . '_field', apply_filters('woocommerce_process_checkout_field_' . $key, $value));
            }
        }
        if (in_array('shipping', $skipped, true) && (WC()->cart->needs_shipping_address() || wc_ship_to_billing_address_only())) {
            foreach ($this->get_checkout_fields('shipping') as $key => $field) {
                $data[$key] = isset($data['billing_' . substr($key, 9)]) ? $data['billing_' . substr($key, 9)] : '';
            }
        }
        $this->legacy_posted_data = $data;
        return apply_filters('woocommerce_checkout_posted_data', $data);
    }
    protected function validate_posted_data(&$data, &$errors)
    {
        foreach ($this->get_checkout_fields() as $fieldset_key => $fieldset) {
            $validate_fieldset = true;
            if ($this->maybe_skip_fieldset($fieldset_key, $data)) {
                $validate_fieldset = false;
            }
            foreach ($fieldset as $key => $field) {
                if (!isset($data[$key])) {
                    continue;
                }
                $required = !empty($field['required']);
                $format = array_filter(isset($field['validate']) ? (array) $field['validate'] : array());
                $field_label = isset($field['label']) ? $field['label'] : '';
                if ($validate_fieldset && (isset($field['type']) && 'country' === $field['type'] && '' !== $data[$key]) && !WC()->countries->country_exists($data[$key])) {
                    $errors->add($key . '_validation', sprintf(__("'%s' is not a valid country code.", 'woocommerce'), $data[$key]));
                }
                switch ($fieldset_key) {
                    case 'shipping':
                        $field_label = sprintf(_x('Shipping %s', 'checkout-validation', 'woocommerce'), $field_label);
                        break;
                    case 'billing':
                        $field_label = sprintf(_x('Billing %s', 'checkout-validation', 'woocommerce'), $field_label);
                        break;
                }
                if (in_array('postcode', $format, true)) {
                    $country = isset($data[$fieldset_key . '_country']) ? $data[$fieldset_key . '_country'] : WC()->customer->{"get_{$fieldset_key}_country"}();
                    $data[$key] = wc_format_postcode($data[$key], $country);
                    if ($validate_fieldset && '' !== $data[$key] && !WC_Validation::is_postcode($data[$key], $country)) {
                        switch ($country) {
                            case 'IE':
                                $postcode_validation_notice = sprintf(__('%1$s is not valid. You can look up the correct Eircode <a target="_blank" href="%2$s">here</a>.', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>', 'https://finder.eircode.ie');
                                break;
                            default:
                                $postcode_validation_notice = sprintf(__('%s is not a valid postcode / ZIP.', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>');
                        }
                        $errors->add($key . '_validation', apply_filters('woocommerce_checkout_postcode_validation_notice', $postcode_validation_notice, $country, $data[$key]), array('id' => $key));
                    }
                }
                if (in_array('phone', $format, true)) {
                    if ($validate_fieldset && '' !== $data[$key] && !WC_Validation::is_phone($data[$key])) {
                        $errors->add($key . '_validation', sprintf(__('%s is not a valid phone number.', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>'), array('id' => $key));
                    }
                }
                if (in_array('email', $format, true) && '' !== $data[$key]) {
                    $email_is_valid = is_email($data[$key]);
                    $data[$key] = sanitize_email($data[$key]);
                    if ($validate_fieldset && !$email_is_valid) {
                        $errors->add($key . '_validation', sprintf(__('%s is not a valid email address.', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>'), array('id' => $key));
                        continue;
                    }
                }
                if ('' !== $data[$key] && in_array('state', $format, true)) {
                    $country = isset($data[$fieldset_key . '_country']) ? $data[$fieldset_key . '_country'] : WC()->customer->{"get_{$fieldset_key}_country"}();
                    $valid_states = WC()->countries->get_states($country);
                    if (!empty($valid_states) && is_array($valid_states) && count($valid_states) > 0) {
                        $valid_state_values = array_map('wc_strtoupper', array_flip(array_map('wc_strtoupper', $valid_states)));
                        $data[$key] = wc_strtoupper($data[$key]);
                        if (isset($valid_state_values[$data[$key]])) {
                            $data[$key] = $valid_state_values[$data[$key]];
                        }
                        if ($validate_fieldset && !in_array($data[$key], $valid_state_values, true)) {
                            $errors->add($key . '_validation', sprintf(__('%1$s is not valid. Please enter one of the following: %2$s', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>', implode(', ', $valid_states)), array('id' => $key));
                        }
                    }
                }
                if ($validate_fieldset && $required && '' === $data[$key]) {
                    $errors->add($key . '_required', apply_filters('woocommerce_checkout_required_field_notice', sprintf(__('%s is a required field.', 'woocommerce'), '<strong>' . esc_html($field_label) . '</strong>'), $field_label), array('id' => $key));
                }
            }
        }
    }
    protected function validate_checkout(&$data, &$errors)
    {
        $this->validate_posted_data($data, $errors);
        $this->check_cart_items();
        if (empty($data['woocommerce_checkout_update_totals']) && empty($data['terms']) && !empty($_POST['terms-field'])) {
            $errors->add('terms', __('Please read and accept the terms and conditions to proceed with your order.', 'woocommerce'));
        }
        if (WC()->cart->needs_shipping()) {
            $shipping_country = isset($data['shipping_country']) ? $data['shipping_country'] : WC()->customer->get_shipping_country();
            if (empty($shipping_country)) {
                $errors->add('shipping', __('Please enter an address to continue.', 'woocommerce'));
            } elseif (!in_array($shipping_country, array_keys(WC()->countries->get_shipping_countries()), true)) {
                if (WC()->countries->country_exists($shipping_country)) {
                    $errors->add('shipping', sprintf(__('Unfortunately <strong>we do not ship %s</strong>. Please enter an alternative shipping address.', 'woocommerce'), WC()->countries->shipping_to_prefix() . ' ' . $shipping_country));
                }
            } else {
                $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
                foreach (WC()->shipping()->get_packages() as $i => $package) {
                    if (!isset($chosen_shipping_methods[$i], $package['rates'][$chosen_shipping_methods[$i]])) {
                        $errors->add('shipping', __('No shipping method has been selected. Please double check your address, or contact us if you need any help.', 'woocommerce'));
                    }
                }
            }
        }
        if (WC()->cart->needs_payment()) {
            $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
            if (!isset($available_gateways[$data['payment_method']])) {
                $errors->add('payment', __('Invalid payment method.', 'woocommerce'));
            } else {
                $available_gateways[$data['payment_method']]->validate_fields();
            }
        }
        do_action('woocommerce_after_checkout_validation', $data, $errors);
    }
    protected function set_customer_address_fields($field, $key, $data)
    {
        $billing_value = null;
        $shipping_value = null;
        if (isset($data["billing_{$field}"]) && is_callable(array(WC()->customer, "set_billing_{$field}"))) {
            $billing_value = $data["billing_{$field}"];
            $shipping_value = $data["billing_{$field}"];
        }
        if (isset($data["shipping_{$field}"]) && is_callable(array(WC()->customer, "set_shipping_{$field}"))) {
            $shipping_value = $data["shipping_{$field}"];
        }
        if (!is_null($billing_value) && is_callable(array(WC()->customer, "set_billing_{$field}"))) {
            WC()->customer->{"set_billing_{$field}"}($billing_value);
        }
        if (!is_null($shipping_value) && is_callable(array(WC()->customer, "set_shipping_{$field}"))) {
            WC()->customer->{"set_shipping_{$field}"}($shipping_value);
        }
    }
    protected function update_session($data)
    {
        $address_fields = array('first_name', 'last_name', 'company', 'email', 'phone', 'address_1', 'address_2', 'city', 'postcode', 'state', 'country');
        array_walk($address_fields, array($this, 'set_customer_address_fields'), $data);
        WC()->customer->save();
        $chosen_shipping_methods = WC()->session->get('chosen_shipping_methods');
        if (is_array($data['shipping_method'])) {
            foreach ($data['shipping_method'] as $i => $value) {
                $chosen_shipping_methods[$i] = $value;
            }
        }
        WC()->session->set('chosen_shipping_methods', $chosen_shipping_methods);
        WC()->session->set('chosen_payment_method', $data['payment_method']);
        WC()->cart->calculate_totals();
    }
    protected function process_order_payment($order_id, $payment_method)
    {
        $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
        if (!isset($available_gateways[$payment_method])) {
            return;
        }
        WC()->session->set('order_awaiting_payment', $order_id);
        $result = $available_gateways[$payment_method]->process_payment($order_id);
        if (isset($result['result']) && 'success' === $result['result']) {
            $result['order_id'] = $order_id;
            $result = apply_filters('woocommerce_payment_successful_result', $result, $order_id);
            if (!is_ajax()) {
                wp_redirect($result['redirect']);
                exit;
            }
            wp_send_json($result);
        }
    }
    protected function process_order_without_payment($order_id)
    {
        $order = wc_get_order($order_id);
        $order->payment_complete();
        wc_empty_cart();
        if (!is_ajax()) {
            wp_safe_redirect(apply_filters('woocommerce_checkout_no_payment_needed_redirect', $order->get_checkout_order_received_url(), $order));
            exit;
        }
        wp_send_json(array('result' => 'success', 'redirect' => apply_filters('woocommerce_checkout_no_payment_needed_redirect', $order->get_checkout_order_received_url(), $order)));
    }
    protected function process_customer($data)
    {
        $customer_id = apply_filters('woocommerce_checkout_customer_id', get_current_user_id());
        if (!is_user_logged_in() && ($this->is_registration_required() || !empty($data['createaccount']))) {
            $username = !empty($data['account_username']) ? $data['account_username'] : '';
            $password = !empty($data['account_password']) ? $data['account_password'] : '';
            $customer_id = wc_create_new_customer($data['billing_email'], $username, $password, array('first_name' => !empty($data['billing_first_name']) ? $data['billing_first_name'] : '', 'last_name' => !empty($data['billing_last_name']) ? $data['billing_last_name'] : ''));
            if (is_wp_error($customer_id)) {
                throw new Exception($customer_id->get_error_message());
            }
            wc_set_customer_auth_cookie($customer_id);
            WC()->session->set('reload_checkout', true);
            WC()->cart->calculate_totals();
        }
        if ($customer_id && is_multisite() && is_user_logged_in() && !is_user_member_of_blog()) {
            add_user_to_blog(get_current_blog_id(), $customer_id, 'customer');
        }
        if ($customer_id && apply_filters('woocommerce_checkout_update_customer_data', true, $this)) {
            $customer = new WC_Customer($customer_id);
            if (!empty($data['billing_first_name']) && '' === $customer->get_first_name()) {
                $customer->set_first_name($data['billing_first_name']);
            }
            if (!empty($data['billing_last_name']) && '' === $customer->get_last_name()) {
                $customer->set_last_name($data['billing_last_name']);
            }
            if (is_email($customer->get_display_name())) {
                $customer->set_display_name($customer->get_first_name() . ' ' . $customer->get_last_name());
            }
            foreach ($data as $key => $value) {
                if (is_callable(array($customer, "set_{$key}"))) {
                    $customer->{"set_{$key}"}($value);
                } elseif (0 === stripos($key, 'billing_') || 0 === stripos($key, 'shipping_')) {
                    $customer->update_meta_data($key, $value);
                }
            }
            do_action('woocommerce_checkout_update_customer', $customer, $data);
            $customer->save();
        }
        do_action('woocommerce_checkout_update_user_meta', $customer_id, $data);
    }
    protected function send_ajax_failure_response()
    {
        if (is_ajax()) {
            if (!isset(WC()->session->reload_checkout)) {
                $messages = wc_print_notices(true);
            }
            $response = array('result' => 'failure', 'messages' => isset($messages) ? $messages : '', 'refresh' => isset(WC()->session->refresh_totals), 'reload' => isset(WC()->session->reload_checkout));
            unset(WC()->session->refresh_totals, WC()->session->reload_checkout);
            wp_send_json($response);
        }
    }
    public function process_checkout()
    {
        try {
            $nonce_value = wc_get_var($_REQUEST['woocommerce-process-checkout-nonce'], wc_get_var($_REQUEST['_wpnonce'], ''));
            if (empty($nonce_value) || !wp_verify_nonce($nonce_value, 'woocommerce-process_checkout')) {
                WC()->session->set('refresh_totals', true);
                throw new Exception(__('We were unable to process your order, please try again.', 'woocommerce'));
            }
            wc_maybe_define_constant('WOOCOMMERCE_CHECKOUT', true);
            wc_set_time_limit(0);
            do_action('woocommerce_before_checkout_process');
            if (WC()->cart->is_empty()) {
                throw new Exception(sprintf(__('Sorry, your session has expired. <a href="%s" class="wc-backward">Return to shop</a>', 'woocommerce'), esc_url(wc_get_page_permalink('shop'))));
            }
            do_action('woocommerce_checkout_process');
            $errors = new WP_Error();
            $posted_data = $this->get_posted_data();
            $this->update_session($posted_data);
            $this->validate_checkout($posted_data, $errors);
            foreach ($errors->errors as $code => $messages) {
                $data = $errors->get_error_data($code);
                foreach ($messages as $message) {
                    wc_add_notice($message, 'error', $data);
                }
            }
            if (empty($posted_data['woocommerce_checkout_update_totals']) && 0 === wc_notice_count('error')) {
                $this->process_customer($posted_data);
                $order_id = $this->create_order($posted_data);
                $order = wc_get_order($order_id);
                if (is_wp_error($order_id)) {
                    throw new Exception($order_id->get_error_message());
                }
                if (!$order) {
                    throw new Exception(__('Unable to create order.', 'woocommerce'));
                }
                do_action('woocommerce_checkout_order_processed', $order_id, $posted_data, $order);
                if (apply_filters('woocommerce_cart_needs_payment', $order->needs_payment(), WC()->cart)) {
                    $this->process_order_payment($order_id, $posted_data['payment_method']);
                } else {
                    $this->process_order_without_payment($order_id);
                }
            }
        } catch (Exception $e) {
            wc_add_notice($e->getMessage(), 'error');
        }
        $this->send_ajax_failure_response();
    }
    public function get_posted_address_data($key, $type = 'billing')
    {
        if ('billing' === $type || false === $this->legacy_posted_data['ship_to_different_address']) {
            $return = isset($this->legacy_posted_data['billing_' . $key]) ? $this->legacy_posted_data['billing_' . $key] : '';
        } else {
            $return = isset($this->legacy_posted_data['shipping_' . $key]) ? $this->legacy_posted_data['shipping_' . $key] : '';
        }
        return $return;
    }
    public function get_value($input)
    {
        if (!empty($_POST[$input])) {
            return wc_clean(wp_unslash($_POST[$input]));
        }
        $value = apply_filters('woocommerce_checkout_get_value', null, $input);
        if (!is_null($value)) {
            return $value;
        }
        $customer_object = false;
        if (is_user_logged_in()) {
            if (is_null($this->logged_in_customer)) {
                $this->logged_in_customer = new WC_Customer(get_current_user_id(), true);
            }
            $customer_object = $this->logged_in_customer;
        }
        if (!$customer_object) {
            $customer_object = WC()->customer;
        }
        if (is_callable(array($customer_object, "get_{$input}"))) {
            $value = $customer_object->{"get_{$input}"}();
        } elseif ($customer_object->meta_exists($input)) {
            $value = $customer_object->get_meta($input, true);
        }
        if ('' === $value) {
            $value = null;
        }
        return apply_filters('default_checkout_' . $input, $value, $input);
    }
}