newInstanceWithoutConstructor();
}
/**
* Class construct.
* required actions that affects woocommerce global checkout shortcode / page.
*
* @since 1.1.0
*/
public function __construct() {
// Create empty shortcode to simulate our widget page as checkout page.
add_shortcode( 'sellkit_checkout_widget_simulated', function() {
return '';
} );
add_action( 'wp_ajax_sellkit_checkout_ajax_handler', [ $this, 'ajax_handler' ] );
add_action( 'wp_ajax_nopriv_sellkit_checkout_ajax_handler', [ $this, 'ajax_handler' ] );
// Add shipping total to review order by custom hook.
add_action( 'sellkit-checkout-widget-display-shipping-price', [ $this, 'add_shipping_total_to_review_order' ] );
// Modify checkout order-review item.
add_action( 'sellkit-one-page-checkout-custom-order-item', [ $this, 'modify_checkout_order_item' ], 1, 4 );
// Modify sent data before processing & validate order.
add_filter( 'woocommerce_checkout_posted_data', [ $this, 'modify_order_data_before_validate' ], 10, 1 );
// Validate user defined fields.
add_action( 'woocommerce_checkout_process', [ $this, 'validate_user_defined_fields' ] );
// Save user defined fields.
add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_user_defined_fields' ] );
// Add custom shipping field to email.
add_filter( 'woocommerce_order_get_formatted_shipping_address', [ $this, 'attach_user_shipping_fields_to_order_email' ], 10, 3 );
// Add custom billing field to email.
add_filter( 'woocommerce_order_get_formatted_billing_address', [ $this, 'attach_user_billing_fields_to_order_email' ], 10, 3 );
// Filter checkout ajax fragment.
add_filter( 'woocommerce_update_order_review_fragments', [ $this, 'checkout_fragment' ] );
// Simulate checkout page for our widget.
add_action( 'wp', [ $this, 'simulate_our_widget_page_as_checkout' ] );
// Fix shipping method price change on ajax.
// Manage bump order discounts.
add_action( 'woocommerce_checkout_update_order_review', [ $this, 'sellkit_custom_shipping_state' ], 10, 1 );
}
/**
* Handle ajax calls.
*
* @since 1.1.0
* @return void
*/
public function ajax_handler() {
check_ajax_referer( 'sellkit_elementor', 'nonce' );
$sub_action = filter_input( INPUT_POST, 'sub_action', FILTER_SANITIZE_STRING );
if ( method_exists( $this, $sub_action ) ) {
call_user_func( [ $this, $sub_action ] );
return;
}
wp_send_json_error();
}
/**
* Modify checkout ajax response HTML.
*
* @param array $response woocommerce checkout page ajax response.
* @return array
* @since 1.1.0
*/
public function checkout_fragment( $response ) {
// Get posted data and identify if it's been sent by jupiter widget or not.
$checkout_form_data = filter_input( INPUT_POST, 'post_data', FILTER_SANITIZE_STRING );
$checkout_form_data = explode( '&', $checkout_form_data );
$posted_data = [];
foreach ( $checkout_form_data as $input ) {
$item = explode( '=', urldecode( $input ) );
$posted_data[ $item[0] ] = $item[1];
}
// Identify if it's been sent by jupiter checkout widget or not.
if ( ! array_key_exists( 'form_id', $posted_data ) && ! array_key_exists( 'post_id', $posted_data ) ) {
// Default woocommerce checkout.
return $response;
}
// Current checkout created by sellkit checkout widget: so apply what we needs.
add_filter( 'wc_get_template', function( $located, $template_name ) {
$our_path = sellkit()->plugin_dir() . 'includes/elementor/modules/checkout/templates/';
$files = [
'review-order.php',
'payment-method.php',
'payment.php',
'form-checkout.php',
'cart-item-data.php',
'cart-shipping.php',
];
$template = str_replace( 'checkout/', '', $template_name );
$template = str_replace( 'cart/', '', $template );
if ( in_array( $template, $files, true ) ) {
$located = $our_path . $template;
}
return $located;
}, 10, 2 );
// Inject widget custom coupon form by custom hook.
$widget_settings = Helper::instance()->retrieve_checkout_widget_settings( $posted_data['post_id'], $posted_data['form_id'] );
Local_Hooks::enable_disable_sections( $widget_settings, $posted_data );
// Order review fragment.
ob_start();
woocommerce_order_review();
$order_review = ob_get_clean();
// Payment fragment.
ob_start();
woocommerce_checkout_payment();
$payment = ob_get_clean();
// Shipping method fragment.
ob_start();
echo '';
wc_cart_totals_shipping_html();
echo '';
$shipping_method = ob_get_clean();
$response['.woocommerce-checkout-review-order-table'] = $order_review;
$response['.woocommerce-checkout-payment'] = $payment;
$response['.sellkit-one-page-shipping-methods'] = '';
if ( ! array_key_exists( 'show_shipping_method', $widget_settings ) ) {
$response['.sellkit-one-page-shipping-methods'] = $shipping_method;
}
return $response;
}
/**
* Apply coupon code using ajax.
*
* @return void
* @since 1.1.0
*/
public function apply_coupon() {
$code = filter_input( INPUT_POST, 'code', FILTER_SANITIZE_STRING );
if ( empty( $code ) ) {
wp_send_json_error();
}
$result = WC()->cart->add_discount( $code );
wp_send_json_success( $result );
}
/**
* Update cart item quantity in checkout page by ajax.
*
* @return void
* @since 1.1.0
*/
public function change_cart_item_qty() {
$qty = filter_input( INPUT_POST, 'qty', FILTER_SANITIZE_NUMBER_INT );
$id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_STRING );
$action = filter_input( INPUT_POST, 'mode', FILTER_SANITIZE_STRING );
if ( 'add' === $action ) {
WC()->cart->add_to_cart( $id, $qty );
return;
}
if ( 'remove' === $action ) {
$product_cart_id = WC()->cart->generate_cart_id( $id );
$cart_item_key = WC()->cart->find_product_in_cart( $product_cart_id );
if ( $cart_item_key ) {
WC()->cart->remove_cart_item( $cart_item_key );
}
return;
}
( $qty > 0 ) ? WC()->cart->set_quantity( $id, $qty ) : WC()->cart->remove_cart_item( $id );
wp_send_json_success();
}
/**
* Place shipping price based on design to checkout order-review.
*
* @return void
* @since 1.1.0
*/
public function add_shipping_total_to_review_order() {
?>
|
cart->get_shipping_total() ); ?> |
cart->get_cart();
//phpcs:disable
ob_start();
?>
get_image(); ?>
retrieve_checkout_widget_settings( $post_id, $form_id );
if ( empty( $settings ) ) {
return $data;
}
$widget_shipping_field = Helper::instance()->get_user_defined_fields_slug( $settings['shipping_list'], 'shipping_list_field' );
$widget_billing_field = Helper::instance()->get_user_defined_fields_slug( $settings['billing_list'], 'billing_list_field' );
$default_shipping_fields = Helper::instance()->shipping_fields();
$default_billing_fields = Helper::instance()->billing_fields();
// Unset removed shipping fields.
foreach ( $default_shipping_fields as $field => $details ) {
if ( ! in_array( $field, $widget_shipping_field, true ) ) {
unset( $data[ $field ] );
}
}
// Unset removed billing fields.
foreach ( $default_billing_fields as $field => $details ) {
if ( ! in_array( $field, $widget_billing_field, true ) && 'billing_email' !== $field ) {
unset( $data[ $field ] );
}
}
return $data;
}
/**
* Login user by ajax.
* sign user in by using form included in widget.
*
* @return void
* @since 1.1.0
*/
public function auth_user() {
$email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_EMAIL );
$pass = filter_input( INPUT_POST, 'pass', FILTER_SANITIZE_STRING );
$verify = filter_var( $email, FILTER_VALIDATE_EMAIL );
if ( ! $verify || empty( $email ) || empty( $pass ) ) {
wp_send_json_error( __( 'Email or password field is not valid.', 'sellkit' ) );
}
$result = wp_authenticate( $email, $pass );
if ( is_wp_error( $result ) ) {
wp_send_json_error( $result->get_error_message() );
}
wp_clear_auth_cookie();
wp_set_current_user( $result->ID );
wp_set_auth_cookie( $result->ID );
wp_send_json_success( $result );
}
/**
* Get widget settings in ajax calls using form and post id.
*
* @return void
* @since 1.1.0
*/
private function widget_settings() {
$form_id = filter_input( INPUT_POST, 'form_id', FILTER_SANITIZE_STRING );
$post_id = filter_input( INPUT_POST, 'post_id', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $form_id ) && empty( $post_id ) ) {
return;
}
$widget_settings = Helper::instance()->retrieve_checkout_widget_settings( $post_id, $form_id );
return $widget_settings;
}
/**
* Validate user defined custom value.
*
* @return void
* @since 1.1.0
*/
public function validate_user_defined_fields() {
$widget_settings = $this->widget_settings();
if ( empty( $widget_settings ) ) {
return;
}
$widget_shipping_fields = $widget_settings['shipping_list'];
$widget_billing_fields = $widget_settings['billing_list'];
Helper::instance()->validate_user_defined_fields( $widget_shipping_fields, $widget_billing_fields );
Helper::instance()->make_sure_to_convert_required_field_to_optional( $widget_shipping_fields, $widget_billing_fields );
}
/**
* Save user defined custom fields value to database.
*
* @param int $order_id id of woocommerce order.
* @return void
* @since 1.1.0
*/
public function save_user_defined_fields( $order_id ) {
$widget_settings = $this->widget_settings();
if ( empty( $widget_settings ) ) {
return;
}
$widget_shipping_fields = $widget_settings['shipping_list'];
$widget_billing_fields = $widget_settings['billing_list'];
Helper::instance()->save_user_defined_fields( $widget_shipping_fields, $widget_billing_fields, $order_id );
}
/**
* Attach user defined shipping field values to order emails.
*
* @param string $address address.
* @param string $raw_address raw address.
* @param object $order woocommerce order object.
* @return string
* @since 1.1.0
*/
public function attach_user_shipping_fields_to_order_email( $address, $raw_address, $order ) {
$order_id = $order->get_id();
$custom_fields = get_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', true );
if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
return $address;
}
foreach ( $custom_fields as $field ) {
if ( 'yes' !== $field['show_in_email'] ) {
continue;
}
$key = $field['key_name'];
$value = get_post_meta( $order_id, $key, true );
if ( strpos( $key, 'shipping' ) !== false ) {
$address .= '
' . $value;
}
}
return $address;
}
/**
* Attach user defined billing field values to order emails.
*
* @param string $address address.
* @param string $raw_address raw address.
* @param object $order woocommerce order object.
* @return string
* @since 1.1.0
*/
public function attach_user_billing_fields_to_order_email( $address, $raw_address, $order ) {
$order_id = $order->get_id();
$custom_fields = get_post_meta( $order_id, 'sellkit_checkout_widget_custom_field_of_order', true );
if ( empty( $custom_fields ) || ! is_array( $custom_fields ) ) {
return $address;
}
foreach ( $custom_fields as $field ) {
if ( 'yes' !== $field['show_in_email'] ) {
continue;
}
$key = $field['key_name'];
$value = get_post_meta( $order_id, $key, true );
if ( strpos( $key, 'billing' ) !== false ) {
$address .= '
' . $value;
}
}
return $address;
}
/**
* Place custom coupon form in checkout order-review based design.
* We have used same form in Local_Hooks. but this one is for ajax response.
*
* @see sellkit_Core\Raven\Modules\Checkout\Classes\Local_Hooks::coupon_form.
* @param array $settings widget settings.
* @return void
* @since 1.1.0
*/
public function coupon_form( $settings ) {
if ( array_key_exists( 'show_coupon_field', $settings ) ) {
return;
}
echo '| ';
Local_Hooks::form( $settings );
echo ' |
';
do_action( 'sellkit-checkout-after-coupon-form-ajax' );
}
/**
* Look for an email if exists or not.
* Is used for login process.
*
* @return void
* @since 1.1.0
*/
public function search_for_email() {
$email = filter_input( INPUT_POST, 'email', FILTER_SANITIZE_EMAIL );
$valid = filter_var( $email, FILTER_VALIDATE_EMAIL );
if ( ! $valid || empty( $email ) ) {
wp_send_json_error();
}
$check = email_exists( $email );
if ( false === $check ) {
wp_send_json_error();
}
wp_send_json_success();
}
/**
* Look for an username if exists or not.
* Is used for register process.
*
* @return void
* @since 1.1.0
*/
public function search_for_username() {
$username = filter_input( INPUT_POST, 'user', FILTER_SANITIZE_EMAIL );
if ( empty( $username ) ) {
wp_send_json_error();
}
$username = sanitize_user( $username );
$check = username_exists( $username );
if ( false !== $check ) {
wp_send_json_error();
}
wp_send_json_success();
}
/**
* Validate postcode via ajax.
*
* @since 1.1.0
* @return void
*/
public function validate_postcode() {
$country = filter_input( INPUT_POST, 'country_code', FILTER_SANITIZE_STRING );
$postcode = filter_input( INPUT_POST, 'post_code', FILTER_SANITIZE_STRING );
$parent = filter_input( INPUT_POST, 'parent', FILTER_DEFAULT );
$postcode = wc_format_postcode( $postcode, $country );
$valid = \WC_Validation::is_postcode( $postcode, $country );
if ( ! $valid ) {
wp_send_json_error( $parent );
}
wp_send_json_success( $parent );
}
/**
* Validate phone number via ajax.
*
* @since 1.1.0
* @return void
*/
public function validate_phone_number() {
$phone = filter_input( INPUT_POST, 'phone_number', FILTER_SANITIZE_STRING );
$parent = filter_input( INPUT_POST, 'parent', FILTER_DEFAULT );
$valid = \WC_Validation::is_phone( $phone );
if ( ! $valid ) {
wp_send_json_error( $parent );
}
wp_send_json_success( $parent );
}
/**
* Simulate checkout page where our widget is present. using empty shortcode [sellkit_checkout_widget_simulated].
*
* @since 1.1.0
* @return void
*/
public function simulate_our_widget_page_as_checkout() {
$page_id = get_the_ID();
$content = get_post_field( 'post_content', $page_id );
if ( false === strpos( $content, 'woocommerce_checkout' ) ) {
return;
}
add_filter( 'woocommerce_is_checkout', function() {
return true;
} );
if ( false === strpos( $content, 'sellkit_checkout_widget_simulated' ) ) {
return;
}
add_filter( 'theme_mod_jupiterx_jupiterx_checkout_cart_elements', function() {
return [];
}, 10 );
}
/**
* Integrate user country with our widget.
*
* @since 1.1.0
* @return void
*/
public function set_customer_details_ajax() {
$country = filter_input( INPUT_POST, 'country', FILTER_SANITIZE_STRING );
$state = filter_input( INPUT_POST, 'state', FILTER_SANITIZE_STRING );
$shipping_country = filter_input( INPUT_POST, 'shipping_country', FILTER_SANITIZE_STRING );
$shipping_state = filter_input( INPUT_POST, 'shipping_state', FILTER_SANITIZE_STRING );
if ( ! empty( $country ) ) {
setcookie( 'sellkit-checkout-billing-cc', $country, time() + ( 86400 * 3 ), '/' );
setcookie( 'sellkit-checkout-billing-state', $state, time() + ( 86400 * 3 ), '/' );
}
if ( ! empty( $shipping_country ) ) {
setcookie( 'sellkit-checkout-shipping-cc', $shipping_country, time() + ( 86400 * 3 ), '/' );
setcookie( 'sellkit-checkout-shipping-state', $shipping_state, time() + ( 86400 * 3 ), '/' );
}
wp_send_json_success();
}
/**
* State lookup using postcode and country.
*
* @since 1.1.0
* @return void
*/
public function sellkit_state_lookup_by_postcode() {
$country = filter_input( INPUT_POST, 'country_value', FILTER_SANITIZE_STRING );
$postcode = filter_input( INPUT_POST, 'postcode_value', FILTER_SANITIZE_STRING );
$api = 'https://api.zippopotam.us/' . $country . '/' . $postcode;
if ( empty( $country ) || empty( $postcode ) ) {
wp_send_json_error( esc_html__( 'Not valid inputs', 'sellkit' ) );
}
$response = wp_remote_get( $api );
if ( is_wp_error( $response ) || ! is_array( $response ) ) {
wp_send_json_error( esc_html__( 'Server error.', 'sellkit' ) );
}
if ( '{}' === $response['body'] ) {
wp_send_json_error( esc_html__( 'Selected country or postcode is not supported.', 'sellkit' ) );
}
wp_send_json_success( $response );
}
/**
* Modify cart contents using bundled products.
*
* @since 1.1.0
* @return void
*/
public function sellkit_checkout_modify_cart_by_bundle_products() {
$qty = filter_input( INPUT_POST, 'qty', FILTER_SANITIZE_NUMBER_INT );
$id = filter_input( INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT );
$type = filter_input( INPUT_POST, 'type', FILTER_SANITIZE_STRING );
WC()->cart->empty_cart();
if ( 'radio' === $type ) {
WC()->cart->add_to_cart( $id, $qty );
}
wp_send_json_success();
}
/**
* Fix shipping method price on checkout ajax state change.
*
* @param string $data checkout form data.
* @since 1.1.0
* @return void
*/
public function sellkit_custom_shipping_state( $data ) {
$data = explode( '&', $data );
$clear = [];
foreach ( $data as $key => $input ) {
$input = explode( '=', $input );
$clear[ $input[0] ] = $input[1];
}
if ( ! array_key_exists( 'form_id', $clear ) ) {
return;
}
if ( array_key_exists( 'shipping_state', $clear ) ) {
$_POST['s_state'] = $clear['shipping_state'];
}
if ( array_key_exists( 'billing_state', $clear ) ) {
$_POST['state'] = $clear['billing_state'];
}
Local_Hooks::order_bump( $clear );
if ( array_key_exists( 'sellkit-bundle-products', $clear ) ) {
$option = $clear['sellkit-bundle-products'];
Local_Hooks::bundle_product_action( $option );
}
}
}