File: /storage/v4513/tepnot/public_html/wp-content/plugins/dokan-pro/includes/Shipping/Hooks.php
<?php
namespace WeDevs\DokanPro\Shipping;
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
use Automattic\WooCommerce\StoreApi\StoreApi;
use Automattic\WooCommerce\Utilities\NumberUtil;
use WC_Countries;
use WC_Shipping_Free_Shipping;
use WeDevs\DokanPro\Shipping\Blocks\CheckoutBlockSupport;
use WeDevs\DokanPro\Shipping\Blocks\ExtendEndpoint;
use WeDevs\DokanPro\Shipping\Methods\ProductShipping;
use WeDevs\DokanPro\Shipping\Methods\VendorShipping;
/**
* Dokan Shipping Class
*
* @author weDevs
*/
class Hooks {
/**
* Load automatically when class inistantiate
*
* @since 2.4
*
* @uses actions|filter hooks
*/
public function __construct() {
add_filter( 'woocommerce_shipping_methods', [ $this, 'register_shipping' ] );
add_filter( 'dokan_settings_selling_option_vendor_capability', [ $this, 'add_settings_shipping_tab' ], 10 );
add_action( 'wp_footer', [ $this, 'set_shipping_asset_in_cart_checkout_page' ] );
add_action( 'woocommerce_product_tabs', [ $this, 'register_product_tab' ] );
add_action( 'woocommerce_after_checkout_validation', [ $this, 'validate_country' ] );
add_action( 'template_redirect', [ $this, 'handle_shipping' ] );
add_filter( 'woocommerce_package_rates', [ $this, 'calculate_shipping_tax' ], 10, 2 );
add_filter( 'woocommerce_shipping_packages', [ $this, 'filter_packages' ] );
add_action( 'woocommerce_delete_shipping_zone', [ $this, 'delete_shipping_zone_data' ], 35, 1 );
add_action( 'woocommerce_after_shipping_zone_object_save', [ $this, 'vendor_zone_data_sync' ] );
add_filter( 'woocommerce_shipping_free_shipping_is_available', [ $this, 'handle_free_shipping_validity' ], 10, 3 );
add_filter( 'dokan_shipping_package_name', [ $this, 'display_free_shipping_remaining_amount' ], 10, 3 );
add_filter( 'dokan_shipping_package_name', [ $this, 'display_free_shipping_remaining_amount_for_vendor_shipping' ], 10, 3 );
add_action(
'woocommerce_blocks_checkout_block_registration',
function ( $integration_registry ) {
$integration_registry->register( new CheckoutBlockSupport() );
}
);
}
/**
* Disable product shipping tab
*
* @since 3.3.0
*
* @param array $settings_fields
*
* @return array
*/
public function add_settings_shipping_tab( $settings_fields ) {
$settings_fields['disable_shipping_tab'] = [
'name' => 'disable_shipping_tab',
'label' => __( 'Disable Shipping Tab', 'dokan' ),
'desc' => __( 'Disable shipping tab on single product page', 'dokan' ),
'type' => 'switcher',
'default' => 'off',
'refresh_after_save' => true,
'is_lite' => false,
];
return $settings_fields;
}
/**
* Register shipping method
*
* @since 2.0
*
* @param array $methods
*
* @return array
*/
public function register_shipping( $methods ) {
if ( 'sell_digital' === dokan_get_option( 'disable_shipping_tab', 'dokan_selling', 'off' ) ) {
return $methods;
}
$methods['dokan_product_shipping'] = ProductShipping::class;
$methods['dokan_vendor_shipping'] = VendorShipping::class;
return $methods;
}
/**
* Set cart page title fix script in cart checkout page.
*
* @since 3.10.1
*
* @return void
*/
public function set_shipping_asset_in_cart_checkout_page() {
if ( ! ( is_cart() || is_checkout() ) ) {
return;
}
ob_start();
?>
<script>
(function($){
$(document).ready(function(){
function format_html() {
// Fix Free shipping remaining amount html display issue on mobile screen.
let shippingTdElements = $( 'tr.woocommerce-shipping-totals.shipping td' );
let discountTdElements = $( 'tr.cart-discount td' );
let tdElements = $.merge( shippingTdElements, discountTdElements );
tdElements.each( function ( index ) {
let title = $(this).data('title');
if ( typeof title === 'undefined' ) {
return;
}
let html = $.parseHTML(title);
let text = $(html).text();
$(this).attr( 'data-title', text );
} );
}
// run initially.
format_html();
// run on added to cart and removed from cart.
$(document.body).on('added_to_cart removed_from_cart updated_cart_totals', format_html );
});
})(jQuery);
</script>
<?php
echo ob_get_clean();
}
/**
* Validate the shipping area
*
* @since 2.0
*
* @param array $posted
*
* @return void
*/
public function validate_country( $posted ) {
$shipping_method = WC()->session->get( 'chosen_shipping_methods' );
// per product shipping was not chosen
if ( ! is_array( $shipping_method ) || ! in_array( 'dokan_product_shipping', $shipping_method, true ) ) {
return;
}
if ( isset( $posted['ship_to_different_address'] ) && $posted['ship_to_different_address'] === '1' ) {
$shipping_country = $posted['shipping_country'];
} else {
$shipping_country = $posted['billing_country'];
}
// echo $shipping_country;
$packages = WC()->shipping->get_packages();
reset( $packages );
if ( ! isset( $packages[0]['contents'] ) ) {
return;
}
$products = array();
foreach ( $packages as $package ) {
array_push( $products, $package['contents'] );
}
$destination_country = isset( $packages[0]['destination']['country'] ) ? $packages[0]['destination']['country'] : '';
$destination_state = isset( $packages[0]['destination']['state'] ) ? $packages[0]['destination']['state'] : '';
// hold all the errors
$errors = array();
foreach ( $products as $key => $product ) {
$dokan_regular_shipping = new ProductShipping();
foreach ( $product as $product_obj ) {
$seller_id = get_post_field( 'post_author', $product_obj['product_id'] );
if ( ! $dokan_regular_shipping->is_method_enabled() ) {
continue;
}
if ( ! ProductShipping::is_shipping_enabled_for_seller( $seller_id ) ) {
continue;
}
if ( ProductShipping::is_product_disable_shipping( $product_obj['product_id'] ) ) {
continue;
}
$dps_country_rates = get_user_meta( $seller_id, '_dps_country_rates', true );
$dps_state_rates = get_user_meta( $seller_id, '_dps_state_rates', true );
$has_found = false;
$dps_country = ( isset( $dps_country_rates ) ) ? $dps_country_rates : array();
$dps_state = ( isset( $dps_state_rates[ $destination_country ] ) ) ? $dps_state_rates[ $destination_country ] : array();
if ( array_key_exists( $destination_country, $dps_country ) ) {
if ( $dps_state ) {
if ( array_key_exists( $destination_state, $dps_state ) ) {
$has_found = true;
} elseif ( array_key_exists( 'everywhere', $dps_state ) ) {
$has_found = true;
}
} else {
$has_found = true;
}
} elseif ( array_key_exists( 'everywhere', $dps_country ) ) {
$has_found = true;
}
if ( ! $has_found ) {
$errors[] = sprintf( '<a href="%s">%s</a>', get_permalink( $product_obj['product_id'] ), get_the_title( $product_obj['product_id'] ) );
}
}
}
if ( $errors ) {
if ( count( $errors ) === 1 ) {
// translators: Error message.
$message = sprintf( __( 'This product does not ship to your chosen location: %s', 'dokan' ), implode( ', ', $errors ) );
} else {
// translators: Error message.
$message = sprintf( __( 'These products do not ship to your chosen location.: %s', 'dokan' ), implode( ', ', $errors ) );
}
wc_add_notice( $message, 'error' );
}
}
/**
* Handle Shipping post submit
*
* @since 2.0
*
* @return void
*/
public function handle_shipping() {
if ( ! is_user_logged_in() ) {
return;
}
if ( ! dokan_is_user_seller( get_current_user_id() ) ) {
return;
}
if ( ! isset( $_POST['dokan_shipping_form_field_nonce'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['dokan_shipping_form_field_nonce'] ) ), 'dokan_shipping_form_field' ) ) {
return;
}
if ( ! current_user_can( 'dokan_view_store_shipping_menu' ) ) {
wp_die( __( 'You have no access to save this shipping options', 'dokan' ) );
}
$user_id = dokan_get_current_user_id();
$s_rates = array();
$rates = array();
// Additional extra code
if ( isset( $_POST['dps_enable_shipping'] ) ) {
update_user_meta( $user_id, '_dps_shipping_enable', sanitize_text_field( wp_unslash( $_POST['dps_enable_shipping'] ) ) );
}
if ( isset( $_POST['dokan_shipping_type'] ) ) {
update_user_meta( $user_id, '_dokan_shipping_type', sanitize_text_field( wp_unslash( $_POST['dokan_shipping_type'] ) ) );
}
if ( isset( $_POST['dps_shipping_type_price'] ) ) {
update_user_meta( $user_id, '_dps_shipping_type_price', sanitize_text_field( wp_unslash( $_POST['dps_shipping_type_price'] ) ) );
}
if ( isset( $_POST['dps_additional_product'] ) ) {
update_user_meta( $user_id, '_dps_additional_product', sanitize_text_field( wp_unslash( $_POST['dps_additional_product'] ) ) );
}
if ( isset( $_POST['dps_additional_qty'] ) ) {
update_user_meta( $user_id, '_dps_additional_qty', sanitize_text_field( wp_unslash( $_POST['dps_additional_qty'] ) ) );
}
if ( isset( $_POST['dps_pt'] ) ) {
update_user_meta( $user_id, '_dps_pt', sanitize_text_field( wp_unslash( $_POST['dps_pt'] ) ) );
}
if ( isset( $_POST['dps_ship_policy'] ) ) {
update_user_meta( $user_id, '_dps_ship_policy', wp_kses_post( wp_unslash( $_POST['dps_ship_policy'] ) ) );
}
if ( isset( $_POST['dps_refund_policy'] ) ) {
update_user_meta( $user_id, '_dps_refund_policy', wp_kses_post( wp_unslash( $_POST['dps_refund_policy'] ) ) );
}
if ( isset( $_POST['dps_form_location'] ) ) {
update_user_meta( $user_id, '_dps_form_location', sanitize_text_field( wp_unslash( $_POST['dps_form_location'] ) ) );
}
if ( isset( $_POST['dps_country_to'] ) ) {
$dps_country_to = wc_clean( wp_unslash( $_POST['dps_country_to'] ) );
$dps_country_to_price = isset( $_POST['dps_country_to_price'] ) ? wc_clean( wp_unslash( $_POST['dps_country_to_price'] ) ) : 0;
foreach ( $dps_country_to as $key => $value ) {
$country = $value;
$c_price = wc_format_decimal( $dps_country_to_price[ $key ] );
if ( ! $c_price && empty( $c_price ) ) {
$c_price = 0;
}
if ( ! empty( $value ) ) {
$rates[ $country ] = $c_price;
}
}
}
update_user_meta( $user_id, '_dps_country_rates', $rates );
if ( isset( $_POST['dps_state_to'] ) ) {
$dps_state_to = wc_clean( wp_unslash( $_POST['dps_state_to'] ) );
foreach ( $dps_state_to as $country_code => $states ) {
foreach ( $states as $key_val => $name ) {
$country_c = $country_code;
$state_code = $name;
$s_price = isset( $_POST['dps_state_to_price'][ $country_c ][ $key_val ] ) ? sanitize_text_field( wp_unslash( $_POST['dps_state_to_price'][ $country_c ][ $key_val ] ) ) : 0;
$s_price = wc_format_decimal( $s_price );
if ( ! $s_price || empty( $s_price ) ) {
$s_price = 0;
}
if ( ! empty( $name ) ) {
$s_rates[ $country_c ][ $state_code ] = $s_price;
}
}
}
}
update_user_meta( $user_id, '_dps_state_rates', $s_rates );
do_action( 'dokan_after_shipping_options_updated', $rates, $s_rates );
$shipping_url = dokan_get_navigation_url( 'settings/regular-shipping' );
wp_safe_redirect( add_query_arg( array( 'message' => 'shipping_saved' ), $shipping_url ) );
exit();
}
/**
* Adds a seller tab in product single page
*
* @since 2.0
*
* @param array $tabs
*
* @return array
*/
public function register_product_tab( $tabs ) {
if ( 'on' === dokan_get_option( 'disable_shipping_tab', 'dokan_selling', 'off' ) ) {
return $tabs;
}
global $post;
if ( get_post_meta( $post->ID, '_disable_shipping', true ) === 'yes' ) {
return $tabs;
}
if ( get_post_meta( $post->ID, '_downloadable', true ) === 'yes' ) {
return $tabs;
}
if ( 'yes' !== get_option( 'woocommerce_calc_shipping' ) ) {
return $tabs;
}
if ( 'sell_digital' === dokan_pro()->digital_product->get_selling_product_type() ) {
return $tabs;
}
$tabs['shipping'] = array(
'title' => __( 'Shipping', 'dokan' ),
'priority' => 12,
'callback' => array( $this, 'shipping_tab' ),
);
return $tabs;
}
/**
* Callback for Register_prouduct_tab function
*
* @since 2.0
*
* @return void
*/
public function shipping_tab() {
global $wpdb, $post;
$vendor_id = $post->post_author;
$shipping_zone = $wpdb->get_results(
$wpdb->prepare(
"SELECT locations.zone_id, locations.seller_id, locations.location_type as vendor_location_type, locations.location_code as vendor_location_code, wc_zones.location_code, wc_zones.location_type FROM {$wpdb->prefix}dokan_shipping_zone_locations as locations INNER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as wc_zones ON locations.zone_id = wc_zones.zone_id INNER JOIN {$wpdb->prefix}dokan_shipping_zone_methods as dokan_methods ON dokan_methods.zone_id = locations.zone_id AND dokan_methods.seller_id = locations.seller_id WHERE locations.seller_id =%d AND locations.location_type != 'postcode' ORDER BY wc_zones.zone_id ASC", $vendor_id
), ARRAY_A
);
$_overwrite_shipping = get_post_meta( $post->ID, '_overwrite_shipping', true );
$dps_processing = get_user_meta( $vendor_id, '_dps_pt', true );
$from = get_user_meta( $vendor_id, '_dps_form_location', true );
$dps_country_rates = get_user_meta( $vendor_id, '_dps_country_rates', true );
$shipping_policy = get_user_meta( $vendor_id, '_dps_ship_policy', true );
$refund_policy = get_user_meta( $vendor_id, '_dps_refund_policy', true );
$product_processing_time = get_post_meta( $post->ID, '_dps_processing_time', true );
$processing_time = $dps_processing;
if ( 'yes' === $_overwrite_shipping ) {
$processing_time = ( $product_processing_time ) ? $product_processing_time : $dps_processing;
}
$country_obj = new WC_Countries();
$countries = $country_obj->countries;
$states = $country_obj->states;
$continents = $country_obj->get_continents();
$shipping_countries = '';
$shipping_states = '';
$shipping_continents = '';
$location_code = '';
$check_countries = array();
$check_states = array();
$check_continents = array();
if ( $shipping_zone ) {
foreach ( $shipping_zone as $zone ) {
$location_code = $zone['vendor_location_code'];
if ( $zone['vendor_location_type'] === 'state' ) {
$location_codes = explode( ':', $location_code );
$country_code = isset( $location_codes[0] ) ? $location_codes[0] : '';
$state_code = isset( $location_codes[1] ) ? $location_codes[1] : '';
if ( isset( $states[ $country_code ][ $state_code ] ) && isset( $countries[ $country_code ] ) && ! in_array( $states[ $country_code ][ $state_code ], $check_states, true ) ) {
$get_state_name = $states[ $country_code ][ $state_code ];
$check_states[ $get_state_name ] = $get_state_name;
$shipping_states .= $get_state_name . ' (' . $countries[ $country_code ] . '), ';
}
}
if ( $zone['vendor_location_type'] === 'country' && $countries[ $location_code ] && ! in_array( $countries[ $location_code ], $check_countries, true ) ) {
$location_code = $countries[ $location_code ];
$check_countries[ $location_code ] = $location_code;
$shipping_countries .= $location_code . ', ';
}
if ( $zone['vendor_location_type'] === 'continent' && $continents[ $location_code ] && ! in_array( $continents[ $location_code ]['name'], $check_continents, true ) ) {
$location_code = $continents[ $location_code ]['name'];
$check_continents[ $location_code ] = $location_code;
$shipping_continents .= $location_code . ', ';
}
}
}
?>
<?php if ( $shipping_continents ) { ?>
<p>
<?php esc_html_e( 'Shipping Continents', 'dokan' ); ?>:
<strong><?php echo rtrim( $shipping_continents, ', ' ); ?></strong>
</p>
<hr>
<?php } ?>
<?php if ( $shipping_countries ) { ?>
<p>
<?php esc_html_e( 'Shipping Countries', 'dokan' ); ?>:
<strong><?php echo rtrim( $shipping_countries, ', ' ); ?></strong>
</p>
<hr>
<?php } ?>
<?php if ( $shipping_states ) { ?>
<p>
<?php esc_html_e( 'Shipping States', 'dokan' ); ?>:
<strong><?php echo rtrim( $shipping_states, ', ' ); ?></strong>
</p>
<hr>
<?php } ?>
<?php if ( $processing_time ) { ?>
<p>
<strong>
<?php esc_html_e( 'Ready to ship in', 'dokan' ); ?> <?php echo dokan_get_processing_time_value( $processing_time ); ?>
<?php
if ( $from ) {
echo __( 'from', 'dokan' ) . ' ' . $countries[ $from ];
}
?>
</strong>
</p>
<hr>
<?php } ?>
<?php if ( $shipping_policy ) { ?>
<p> </p>
<strong><?php esc_html_e( 'Shipping Policy', 'dokan' ); ?></strong>
<hr>
<?php echo wpautop( $shipping_policy ); ?>
<?php } ?>
<?php if ( $refund_policy ) { ?>
<hr>
<p> </p>
<strong><?php esc_html_e( 'Refund Policy', 'dokan' ); ?></strong>
<hr>
<?php echo wpautop( $refund_policy ); ?>
<?php } ?>
<?php
}
/**
* WooCommerce calculate taxes cart wise (cart as a whole), not vendor wise.
* So if there is any tax for non-taxable product, lets remove that tax
*
* @since 3.0.3
*
* @see https://github.com/weDevsOfficial/dokan/issues/820
* @see https://github.com/woocommerce/woocommerce/issues/20600
*
* @param \WC_Shipping_Rate $package_rates Shipping rates
* @param array $package Shipping package
*
* @return \WC_Shipping_Rate
*/
public function calculate_shipping_tax( $package_rates, $package ) {
if ( ! isset( $package['contents'] ) ) {
return $package_rates;
}
foreach ( $package['contents'] as $pack ) {
if ( ! isset( $pack['data'] ) || ! is_callable( [ $pack['data'], 'get_tax_status' ] ) ) {
return $package_rates;
}
if ( 'none' !== $pack['data']->get_tax_status() ) {
continue;
}
// so it's a non taxable shipping, lets remove the taxes
foreach ( $package_rates as $shipping_rate ) {
$rfc = new \ReflectionClass( $shipping_rate );
if ( ! $rfc->hasProperty( 'data' ) ) {
return $package_rates;
}
$data = $rfc->getProperty( 'data' );
$data->setAccessible( true );
$data->setValue(
$shipping_rate,
array_merge(
$data->getValue( $shipping_rate ),
[
'taxes' => [],
]
)
);
}
}
return $package_rates;
}
/**
* Filter pakcages, remove shipping data from cart if no shipping is required.
*
* Vendor A sales digital product with no shipping, but Vendor B sales physical product with shipping.
* When Vendor A’s product is added in the cart, there is no shipping as expected.
* But on adding Vendor B’s product, shipping is shown for both products.
*
* We'll remove package only if all the products of a vendor are non-shippable
*
* @since 3.0.3
* @since DOKAN_PRO_VERSION Remove packages those are not have contents
*
* @param array $packages
*
* @return array
*/
public function filter_packages( $packages ) {
$package_to_keep = [];
$package_to_remove = [];
foreach ( $packages as $key => $package ) {
if ( empty( $package['contents'] ) ) {
$package_to_remove[] = $key;
continue;
}
$p_seller_id = isset( $package['seller_id'] ) ? (int) $package['seller_id'] : 0;
foreach ( $package['contents'] as $content ) {
$product = ! empty( $content['product_id'] ) ? wc_get_product( $content['product_id'] ) : '';
if ( $product && $product->needs_shipping() ) {
$seller_id = dokan_get_vendor_by_product( $product->get_id(), true );
if ( $p_seller_id !== $seller_id ) {
$packages[ $key ]['seller_id'] = $seller_id;
}
$package_to_keep[] = $key;
// check if we already added same vendor under removed package
$item_exists_on_remove_package = array_search( $key, $package_to_remove, true );
if ( false !== $item_exists_on_remove_package ) {
unset( $package_to_remove[ $item_exists_on_remove_package ] );
}
}
if ( $product && ! $product->needs_shipping() && ! in_array( $key, $package_to_keep, true ) ) {
$package_to_remove[] = $key;
}
}
}
foreach ( $package_to_remove as $package ) {
unset( $packages[ $package ] );
}
/**
* @since 3.5.0
*/
return apply_filters( 'dokan_shipping_packages', $packages, $package_to_keep );
}
/**
* Delete shipping data when zone deleted from admin
*
* @since 3.2.2
*
* @param int $zone_id Shipping zone id
*
* @return void
*/
public function delete_shipping_zone_data( $zone_id ) {
global $wpdb;
// Delete dokan shipping data when deleted zone from admin area
$wpdb->delete( $wpdb->prefix . 'dokan_shipping_zone_locations', array( 'zone_id' => $zone_id ) );
$wpdb->delete( $wpdb->prefix . 'dokan_shipping_zone_methods', array( 'zone_id' => $zone_id ) );
do_action( 'dokan_delete_shipping_zone_data', $zone_id );
}
/**
* Vendors shipping data syncronize when zone update by admin
*
* @since 3.2.2
*
* @param \WC_Shipping_Zone $zone Shipping zone.
*
* @return void
*/
public function vendor_zone_data_sync( $zone ) {
if ( empty( $zone->get_id() ) ) {
return;
}
$zone_data = $zone->get_data();
$zone_locations = $zone_data['zone_locations'];
if ( empty( $zone_locations ) ) {
return;
}
$all_vendors = dokan()->vendor->get_vendors( [ 'number' => -1, 'fields' => 'ID' ] ); //phpcs:ignore
foreach ( $all_vendors as $vendor_id ) {
$args = [
'seller_id' => $vendor_id,
'zone' => $zone,
'zone_locations' => $zone_locations,
];
dokan_pro()->bg_process->sync_vendor_zone_data->push_to_queue( $args );
}
dokan_pro()->bg_process->sync_vendor_zone_data->save()->dispatch();
}
/**
* Handle free shipping availability for vendors.
*
* @since 3.7.16
*
* @param bool $is_available Is available.
* @param array $package Package to check with.
* @param WC_Shipping_Free_Shipping $shipping_instance Shipping instance.
*
* @return bool
*/
public function handle_free_shipping_validity( bool $is_available, array $package, WC_Shipping_Free_Shipping $shipping_instance ): bool {
if ( ! $is_available ) {
return false;
}
// Get dokan free shipping method instance.
$free_shipping = new FreeShippingHandler( $shipping_instance, $package );
// Return free shipping availability.
return $free_shipping->is_free_shipping_available();
}
/**
* Display Free shipping information.
*
* @since 3.7.27
*
* @param string $shipping_label Existing shipping label.
* @param int $i Index.
* @param array $package Package.
*
* @return string
*/
public function display_free_shipping_remaining_amount( $shipping_label, $i, $package ): string {
$shipping_methods = \WC_Shipping_Zones::get_zone_matching_package( $package )->get_shipping_methods( true );
$free_shipping_instance = null;
$free_shipping_available = false;
foreach ( $shipping_methods as $shipping_method ) {
if ( 'free_shipping' === $shipping_method->id ) {
$free_shipping_instance = $shipping_method;
break;
}
}
// Verify the free shipping label if free shipping is not available for this vendor
// Or no free shipping method found.
if ( empty( $free_shipping_instance ) || ! isset( $package['rates'] ) ) {
return $shipping_label;
}
foreach ( $package['rates'] as $method ) {
if ( 'free_shipping' === explode( ':', $method->id )[0] ) {
$free_shipping_available = true;
break;
}
}
if ( $free_shipping_available || ! is_a( $free_shipping_instance, WC_Shipping_Free_Shipping::class ) ) {
return $shipping_label;
}
// Get dokan free shipping method instance & collect relevant values.
$free_shipping = new FreeShippingHandler( $free_shipping_instance, $package );
$remains = $free_shipping->get_remaining_amount();
$is_available = $free_shipping->is_free_shipping_available();
$needs_coupon_only = $free_shipping->needs_coupon_for_free_shipping();
if ( $is_available || $needs_coupon_only ) {
return $shipping_label;
}
// translators: 1. Original Shipping title, 2. Remaining amount to avail free shipping, 3. Free shipping method display title.
return sprintf( __( '%1$s <br /><small>(Only %2$s away from <strong>%3$s</strong>)</small>', 'dokan' ), $shipping_label, wc_price( $remains ), $free_shipping_instance->get_title() );
}
/**
* Display Free shipping information.
*
* @since 3.15.0
*
* @param array $package Package.
*
* @return string
*/
public function display_free_shipping_remaining_amount_block( $package, $store_name ): string {
$shipping_methods = \WC_Shipping_Zones::get_zone_matching_package( $package )->get_shipping_methods( true );
$free_shipping_instance = null;
foreach ( $shipping_methods as $shipping_method ) {
if ( 'free_shipping' === $shipping_method->id ) {
$free_shipping_instance = $shipping_method;
break;
}
}
if ( empty( $free_shipping_instance ) || ! is_a( $free_shipping_instance, WC_Shipping_Free_Shipping::class ) ) {
return $store_name;
}
// Get dokan free shipping method instance & collect relevant values.
$free_shipping = new FreeShippingHandler( $free_shipping_instance, $package );
$remains = $free_shipping->get_remaining_amount();
$is_available = $free_shipping->is_free_shipping_available();
$needs_coupon_only = $free_shipping->needs_coupon_for_free_shipping();
if ( $is_available || $needs_coupon_only ) {
return $store_name;
}
// translators: 1. Original Shipping title, 2. Remaining amount to avail free shipping, 3. Free shipping method display title.
return sprintf( __( '<strong>%1$s:</strong> (Only %2$s away from <strong>%3$s</strong>)', 'dokan' ), $store_name, wc_price( $remains ), $free_shipping_instance->get_title() );
}
/**
* Display Free shipping information for vendor shipping.
*
* @since 3.7.27
*
* @param array $package Package.
* @param string $store_name Existing shipping label.
*
* @return string
*/
public function display_free_shipping_remaining_amount_for_vendor_shipping_block( $package, $store_name ): string {
if ( empty( $package['seller_id'] ) ) {
return $store_name;
}
$shipping_methods = ShippingZone::get_shipping_methods( ShippingZone::get_zone_matching_package( $package )->get_id(), $package['seller_id'] );
$free_shipping_instance = null;
$free_shipping_available = false;
foreach ( $shipping_methods as $shipping_method ) {
if ( 'yes' !== $shipping_method['enabled'] ) {
continue;
}
if ( 'free_shipping' === $shipping_method['id'] ) {
$free_shipping_instance = $shipping_method;
break;
}
}
if ( empty( $free_shipping_instance ) ) {
return $store_name;
}
// Get dokan free shipping method instance & collect relevant values.
$free_shipping = new FreeShippingHandler( $free_shipping_instance, $package );
$is_available = $free_shipping->is_free_shipping_available();
$remains = $free_shipping->get_remaining_amount();
if ( $is_available ) {
return $store_name;
}
// translators: 1. Original Shipping title, 2. Remaining amount to avail free shipping, 3. Free shipping method display title.
return sprintf( __( '<strong>%1$s</strong> (Only %2$s away from <strong>%3$s</strong>)', 'dokan' ), $store_name, wc_price( $remains ), $free_shipping_instance['title'] );
}
/**
* Display Free shipping information for vendor shipping.
*
* @since 3.7.27
*
* @param string $shipping_label Existing shipping label.
* @param int $i Index.
* @param array $package Package.
*
* @return string
*/
public function display_free_shipping_remaining_amount_for_vendor_shipping( $shipping_label, $i, $package ): string {
if ( empty( $package['seller_id'] ) ) {
return $shipping_label;
}
$shipping_methods = ShippingZone::get_shipping_methods( ShippingZone::get_zone_matching_package( $package )->get_id(), $package['seller_id'] );
$free_shipping_instance = null;
$free_shipping_available = false;
foreach ( $shipping_methods as $shipping_method ) {
if ( 'yes' !== $shipping_method['enabled'] ) {
continue;
}
if ( 'free_shipping' === $shipping_method['id'] ) {
$free_shipping_instance = $shipping_method;
break;
}
}
// Verify the free shipping label if free shipping is not available for this vendor
// Or no free shipping method found.
if ( empty( $free_shipping_instance ) || ! isset( $package['rates'] ) ) {
return $shipping_label;
}
foreach ( $package['rates'] as $method ) {
if ( 'free_shipping_dokan_vendor_shipping' === ( explode( ':', $method->id )[0] . '_' . $method->method_id ) ) {
$free_shipping_available = true;
break;
}
}
if ( $free_shipping_available ) {
return $shipping_label;
}
// Get dokan free shipping method instance & collect relevant values.
$free_shipping = new FreeShippingHandler( $free_shipping_instance, $package );
$is_available = $free_shipping->is_free_shipping_available();
$remains = $free_shipping->get_remaining_amount();
if ( $is_available ) {
return $shipping_label;
}
// translators: 1. Original Shipping title, 2. Remaining amount to avail free shipping, 3. Free shipping method display title.
return sprintf( __( '%1$s <br /><small>(Only %2$s away from <strong>%3$s</strong>)</small>', 'dokan' ), $shipping_label, wc_price( $remains ), $free_shipping_instance['title'] );
}
}