Files
2018-07-09 12:34:06 +02:00

507 lines
20 KiB
PHP

<?php
/**
* Booster for WooCommerce - Module - EU VAT Number
*
* @version 3.4.0
* @since 2.3.9
* @author Algoritmika Ltd.
* @todo clean up
*/
if ( ! defined( 'ABSPATH' ) ) exit;
if ( ! class_exists( 'WCJ_EU_VAT_Number' ) ) :
class WCJ_EU_VAT_Number extends WCJ_Module {
/**
* Constructor.
*
* @version 3.3.0
*/
function __construct() {
$this->id = 'eu_vat_number';
$this->short_desc = __( 'EU VAT Number', 'woocommerce-jetpack' );
$this->desc = __( 'Collect and validate EU VAT numbers on the checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' );
$this->link_slug = 'woocommerce-eu-vat-number';
parent::__construct();
$this->add_tools( array(
'eu_countries_vat_rates' => array(
'title' => __( 'EU Countries VAT Rates', 'woocommerce-jetpack' ),
'desc' => __( 'Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' ),
),
) );
if ( $this->is_enabled() ) {
add_action( 'init', array( $this, 'start_session' ) );
add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
// add_filter( 'woocommerce_form_field_text', array( $this, 'add_eu_vat_verify_button' ), PHP_INT_MAX, 4 );
// add_action( 'init', array( $this, 'wcj_validate_eu_vat_number' ) );
// add_filter( 'woocommerce_find_rates', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX, 2 );
add_filter( 'init', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
if ( 'after_order_table' === get_option( 'wcj_eu_vat_number_display_position', 'after_order_table' ) ) {
add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
add_action( 'woocommerce_email_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
} else {
add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'add_eu_vat_number_to_order_billing_address' ), PHP_INT_MAX, 2 );
add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'add_eu_vat_number_to_my_account_billing_address' ), PHP_INT_MAX, 3 );
add_filter( 'woocommerce_localisation_address_formats', array( $this, 'add_eu_vat_number_to_address_formats' ) );
add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'replace_eu_vat_number_in_address_formats' ), PHP_INT_MAX, 2 );
}
$this->eu_countries_vat_rates_tool = include_once( 'tools/class-wcj-eu-countries-vat-rates-tool.php' );
// EU VAT number summary on order edit page
if ( 'yes' === get_option( 'wcj_eu_vat_number_add_order_edit_metabox', 'no' ) ) {
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
// "Validate VAT and remove taxes" button
add_action( 'admin_init', array( $this, 'admin_validate_vat_and_maybe_remove_taxes' ), PHP_INT_MAX );
}
// Admin order edit - "Load billing address" button
add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'add_billing_eu_vat_number_to_ajax_get_customer_details' ), PHP_INT_MAX, 3 );
}
}
/**
* admin_validate_vat_and_maybe_remove_taxes.
*
* @version 3.3.0
* @since 3.3.0
*/
function admin_validate_vat_and_maybe_remove_taxes() {
if ( isset( $_GET['validate_vat_and_maybe_remove_taxes'] ) ) {
$order_id = $_GET['validate_vat_and_maybe_remove_taxes'];
$order = wc_get_order( $order_id );
if ( $order ) {
$vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
if ( '' != $vat_id && strlen( $vat_id ) > 2 ) {
if ( wcj_validate_vat( substr( $vat_id, 0, 2 ), substr( $vat_id, 2 ) ) ) {
foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
$item->set_taxes( false );
}
foreach ( $order->get_shipping_methods() as $item_id => $item ) {
$item->set_taxes( false );
}
$order->update_taxes();
$order->calculate_totals( false );
}
}
}
wp_safe_redirect( remove_query_arg( 'validate_vat_and_maybe_remove_taxes' ) );
exit;
}
}
/**
* add_billing_eu_vat_number_to_ajax_get_customer_details.
*
* @version 3.3.0
* @since 3.3.0
*/
function add_billing_eu_vat_number_to_ajax_get_customer_details( $data, $customer, $user_id ) {
$data['billing']['eu_vat_number'] = get_user_meta( $user_id, 'billing_eu_vat_number', true );
return $data;
}
/**
* add_meta_box.
*
* @version 2.6.0
* @since 2.6.0
*/
function add_meta_box() {
$screen = ( isset( $this->meta_box_screen ) ) ? $this->meta_box_screen : 'shop_order';
$context = ( isset( $this->meta_box_context ) ) ? $this->meta_box_context : 'side';
$priority = ( isset( $this->meta_box_priority ) ) ? $this->meta_box_priority : 'low';
add_meta_box(
'wc-jetpack-' . $this->id,
__( 'Booster', 'woocommerce-jetpack' ) . ': ' . $this->short_desc,
array( $this, 'create_meta_box' ),
$screen,
$context,
$priority
);
}
/**
* create_meta_box.
*
* @version 3.3.0
* @since 2.6.0
*/
function create_meta_box() {
$order_id = get_the_ID();
$_order = wc_get_order( $order_id );
$_customer_ip_address = ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->customer_ip_address : $_order->get_customer_ip_address() );
// Country by IP
if ( class_exists( 'WC_Geolocation' ) ) {
// Get the country by IP
$location = WC_Geolocation::geolocate_ip( $_customer_ip_address );
// Base fallback
if ( empty( $location['country'] ) ) {
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
}
$customer_country = ( isset( $location['country'] ) ) ? $location['country'] : '';
} else {
$customer_country = '';
}
// Customer EU VAT number
$customer_eu_vat_number = get_post_meta( $order_id, '_billing_eu_vat_number', true );
if ( '' == $customer_eu_vat_number ) {
$customer_eu_vat_number = '-';
}
// Taxes
$taxes = '';
$taxes_array = $_order->get_tax_totals();
if ( empty( $taxes_array ) ) {
$taxes = '-';
} else {
foreach ( $taxes_array as $tax ) {
$taxes .= $tax->label . ': ' . $tax->formatted_amount . '<br>';
}
}
// Results table
$table_data = array(
array(
__( 'Customer IP', 'woocommerce-jetpack' ),
$_customer_ip_address
),
array(
__( 'Country by IP', 'woocommerce-jetpack' ),
wcj_get_country_flag_by_code( $customer_country ) . ' ' . wcj_get_country_name_by_code( $customer_country ) . ' [' . $customer_country . ']'
),
array(
__( 'Customer EU VAT Number', 'woocommerce-jetpack' ),
$customer_eu_vat_number
),
array(
__( 'Taxes', 'woocommerce-jetpack' ),
$taxes,
),
/* array(
__( 'Customer Meta', 'woocommerce-jetpack' ),
// '<pre>' . print_r( get_user_meta( $_order->customer_user ), true ). '</pre>',
'<pre>' . print_r( get_user_by( 'ID', $_order->customer_user ), true ). '</pre>',
), */
);
echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
echo '<p>' . '<a href="' . add_query_arg( 'validate_vat_and_maybe_remove_taxes', $order_id ) . '">' .
__( 'Validate VAT and remove taxes', 'woocommerce-jetpack' ) . '</a>' . '</p>';
}
/**
* replace_eu_vat_number_in_address_formats.
*
* @version 2.5.2
* @since 2.5.2
*/
function replace_eu_vat_number_in_address_formats( $replacements, $args ) {
$field_name = 'billing_' . $this->id;
$replacements['{' . $field_name . '}'] = ( isset( $args[ $field_name ] ) ) ? $args[ $field_name ] : '';
return $replacements;
}
/**
* add_eu_vat_number_to_address_formats.
*
* @version 2.5.2
* @since 2.5.2
*/
function add_eu_vat_number_to_address_formats( $address_formats ) {
$field_name = 'billing_' . $this->id;
$modified_address_formats = array();
foreach ( $address_formats as $country => $address_format ) {
$modified_address_formats[ $country ] = $address_format . "\n{" . $field_name . '}';
}
return $modified_address_formats;
}
/**
* add_eu_vat_number_to_my_account_billing_address.
*
* @version 2.5.2
* @since 2.5.2
*/
function add_eu_vat_number_to_my_account_billing_address( $fields, $customer_id, $name ) {
if ( 'billing' === $name ) {
$field_name = 'billing_' . $this->id;
$fields[ $field_name ] = get_user_meta( $customer_id, $field_name, true );
}
return $fields;
}
/**
* add_eu_vat_number_to_order_billing_address.
*
* @version 2.7.0
* @since 2.5.2
*/
function add_eu_vat_number_to_order_billing_address( $fields, $_order ) {
$field_name = 'billing_' . $this->id;
$fields[ $field_name ] = get_post_meta( wcj_get_order_id( $_order ), '_' . $field_name, true );
return $fields;
}
/**
* add_eu_vat_number_to_order_display.
*
* @version 3.2.2
* @since 2.4.7
*/
function add_eu_vat_number_to_order_display( $order ) {
$order_id = wcj_get_order_id( $order );
$html = '';
$option_name = '_billing_' . $this->id;
$the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
if ( '' != $the_eu_vat_number ) {
$the_label = get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
$html .= '<p>' . '<strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
}
echo $html;
}
/**
* create_eu_countries_vat_rates_tool.
*
* @version 2.3.10
* @since 2.3.10
*/
function create_eu_countries_vat_rates_tool() {
return $this->eu_countries_vat_rates_tool->create_eu_countries_vat_rates_tool( $this->get_tool_header_html( 'eu_countries_vat_rates' ) );
}
/**
* add_default_checkout_billing_eu_vat_number.
*
* @version 3.4.0
*/
function add_default_checkout_billing_eu_vat_number( $default_value, $field_key ) {
if ( null !== ( $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) {
return $eu_vat_number_to_check;
} elseif ( is_user_logged_in() ) {
$current_user = wp_get_current_user();
if ( $meta = get_user_meta( $current_user->ID, 'billing_eu_vat_number', true ) ) {
return $meta;
}
}
return $default_value;
}
/**
* add_eu_vat_number_customer_meta_field.
*/
function add_eu_vat_number_customer_meta_field( $fields ) {
$fields['billing']['fields']['billing_eu_vat_number'] = array(
'label' => get_option( 'wcj_eu_vat_number_field_label' ),
'description' => ''
);
return $fields;
}
/**
* start_session.
*
* @version 3.4.0
*/
function start_session() {
wcj_session_maybe_start();
$args = array();
if ( isset( $_POST['post_data'] ) ) {
parse_str( $_POST['post_data'], $args );
if ( isset( $args['billing_eu_vat_number'] ) && wcj_session_get( 'wcj_eu_vat_number_to_check' ) != $args['billing_eu_vat_number'] ) {
wcj_session_set( 'wcj_is_eu_vat_number_valid', null );
wcj_session_set( 'wcj_eu_vat_number_to_check', null );
}
}
}
/**
* enqueue_scripts.
*
* @version 3.4.0
*/
function enqueue_scripts() {
if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/wcj-eu-vat-number.js', array(), WCJ()->version, true );
wp_localize_script( 'wcj-eu-vat-number', 'ajax_object', array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'add_progress_text' => get_option( 'wcj_eu_vat_number_add_progress_text', 'no' ),
'progress_text_validating' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validating', __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ) ) ),
'progress_text_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_valid', __( 'VAT is valid.', 'woocommerce-jetpack' ) ) ),
'progress_text_not_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_not_valid', __( 'VAT is not valid.', 'woocommerce-jetpack' ) ) ),
'progress_text_validation_failed' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validation_failed', __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ) ) ),
) );
}
}
/**
* wcj_validate_eu_vat_number.
*
* @version 3.4.0
*/
function wcj_validate_eu_vat_number( $param ) {
// if ( ! isset( $_GET['wcj_validate_eu_vat_number'] ) ) return;
if ( isset( $_POST['wcj_eu_vat_number_to_check'] ) && '' != $_POST['wcj_eu_vat_number_to_check'] ) {
$eu_vat_number_to_check = substr( $_POST['wcj_eu_vat_number_to_check'], 2 );
$eu_vat_number_country_to_check = substr( $_POST['wcj_eu_vat_number_to_check'], 0, 2 );
if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
$location = WC_Geolocation::geolocate_ip();
if ( empty( $location['country'] ) ) {
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
}
$is_valid = ( $location['country'] === $eu_vat_number_country_to_check ) ?
wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check ) :
false;
} else {
$is_valid = wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check );
}
} else {
$is_valid = null;
}
wcj_session_set( 'wcj_is_eu_vat_number_valid', $is_valid );
wcj_session_set( 'wcj_eu_vat_number_to_check', $_POST['wcj_eu_vat_number_to_check'] );
if ( false === $is_valid ) {
echo '0';
} elseif ( true === $is_valid ) {
echo '1';
} elseif ( null === $is_valid ) {
echo '2';
} else {
echo '3'; // unexpected
}
die();
}
/**
* maybe_exclude_vat.
*
* @version 3.4.0
*/
// function maybe_exclude_vat( $matched_tax_rates, $args ) {
function maybe_exclude_vat() {
if (
( is_checkout() || is_cart() || defined( 'WOOCOMMERCE_CHECKOUT' ) || defined( 'WOOCOMMERCE_CART' ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) &&
! empty( WC()->customer ) &&
'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
true === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) && null !== wcj_session_get( 'wcj_eu_vat_number_to_check' )
) {
$preserve_base_country_check_passed = true;
if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_preserve_in_base_country', 'no' ) ) ) {
$location = wc_get_base_location();
if ( empty( $location['country'] ) ) {
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
}
$selected_country = substr( wcj_session_get( 'wcj_eu_vat_number_to_check' ), 0, 2 );
if ( 'EL' === $selected_country ) {
$selected_country = 'GR';
}
$preserve_base_country_check_passed = ( strtoupper( $location['country'] ) !== strtoupper( $selected_country ) );
}
if ( $preserve_base_country_check_passed ) {
/* $modified_matched_tax_rates = array();
foreach ( $matched_tax_rates as $i => $matched_tax_rate ) {
$matched_tax_rate['rate'] = 0;
$modified_matched_tax_rates[ $i ] = $matched_tax_rate;
}
return $modified_matched_tax_rates; */
WC()->customer->set_is_vat_exempt( true );
} else {
WC()->customer->set_is_vat_exempt( false );
}
} else {
if ( ! empty( WC()->customer ) ) {
WC()->customer->set_is_vat_exempt( false );
}
}
// return $matched_tax_rates;
}
/**
* checkout_validate_vat.
*
* @version 3.4.0
*/
function checkout_validate_vat( $_posted ) {
if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
if (
( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' == $_posted['billing_eu_vat_number'] ) ||
(
( '' != $_posted['billing_eu_vat_number'] ) &&
(
null === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) || false == wcj_session_get( 'wcj_is_eu_vat_number_valid' ) ||
null === wcj_session_get( 'wcj_eu_vat_number_to_check' ) || $_posted['billing_eu_vat_number'] != wcj_session_get( 'wcj_eu_vat_number_to_check' )
)
)
) {
wc_add_notice(
get_option( 'wcj_eu_vat_number_not_valid_message', __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ) ),
'error'
);
}
}
}
/**
* add_billing_eu_vat_number_field_to_admin_order_display.
*/
function add_billing_eu_vat_number_field_to_admin_order_display( $fields ) {
$fields[ $this->id ] = array(
'type' => 'text',
'label' => get_option( 'wcj_eu_vat_number_field_label' ),
'show' => true,
);
return $fields;
}
/**
* add_eu_vat_verify_button.
*
function add_eu_vat_verify_button( $field, $key, $args, $value ) {
return ( 'billing_eu_vat_number' === $key ) ?
$field . '<span style="font-size:smaller !important;">' . '[<a name="billing_eu_vat_number_verify" href="">' . __( 'Verify', 'woocommerce-jetpack' ) . '</a>]' . '</span>' :
$field;
}
/**
* add_eu_vat_number_checkout_field_to_frontend.
*
* @version 2.4.0
*/
function add_eu_vat_number_checkout_field_to_frontend( $fields ) {
$fields['billing'][ 'billing_' . $this->id ] = array(
'type' => 'text',
// 'default' => ( null !== ( $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ? $eu_vat_number_to_check : '' ),
'label' => get_option( 'wcj_eu_vat_number_field_label' ),
'description' => get_option( 'wcj_eu_vat_number_field_description' ),
'placeholder' => get_option( 'wcj_eu_vat_number_field_placeholder' ),
'required' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) ) ? true : false,
'custom_attributes' => array(),
'clear' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_clear', 'yes' ) ) ? true : false,
'class' => array( get_option( 'wcj_eu_vat_number_field_class', 'form-row-wide' ) ),
'validate' => ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) ? array( 'eu-vat-number' ) : array(),
);
return $fields;
}
}
endif;
return new WCJ_EU_VAT_Number();