sitepress = $sitepress;
$this->woocommerce_wpml = $woocommerce_wpml;
$this->wpdb = $wpdb;
}
public function add_hooks() {
add_action( 'init', [ $this, 'init' ], 9 );
if ( ! is_admin() ) {
add_filter( 'get_the_terms', [ $this, 'shipping_class_id_in_default_language' ], 10, 3 );
add_filter( 'woocommerce_shipping_table_rate_is_available', [ $this, 'shipping_table_rate_is_available' ], 10, 3 );
}
if ( is_admin() ) {
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( Obj::prop( 'shipping_abort_reason', $_POST ) ) {
// phpcs:enable WordPress.Security.NonceVerification.Missing
add_filter( 'woocommerce_table_rate_get_shipping_rates', [ $this, 'register_abort_messages' ] );
}
add_action( 'wp_ajax_woocommerce_table_rate_delete', [ $this, 'unregister_abort_messages_ajax' ], self::PRIORITY_BEFORE_DELETE );
add_action( 'delete_product_shipping_class', [ $this, 'unregister_abort_messages_shipping_class' ], self::PRIORITY_BEFORE_DELETE );
}
add_filter( 'woocommerce_table_rate_query_rates', [ $this, 'translate_abort_messages' ] );
}
/**
* Register shipping labels for string translation.
*/
public function init() {
// Register shipping label.
if (
isset( $_GET['page'] ) &&
(
'shipping_zones' === $_GET['page'] ||
(
'wc-settings' === $_GET['page'] &&
isset( $_GET['tab'] ) &&
'shipping' === $_GET['tab']
)
)
) {
$this->show_pointer_info();
if ( isset( $_POST['shipping_label'] ) &&
isset( $_POST['woocommerce_table_rate_title'] ) ) {
do_action( 'wpml_register_single_string', WCML_WC_Shipping::STRINGS_CONTEXT, sanitize_text_field( $_POST['woocommerce_table_rate_title'] ) . '_shipping_method_title', sanitize_text_field( $_POST['woocommerce_table_rate_title'] ) );
$shipping_labels = array_map( 'wc_clean', $_POST['shipping_label'] );
foreach ( $shipping_labels as $key => $shipping_label ) {
$rate_key = isset( $_GET['instance_id'] ) ? 'table_rate' . $_GET['instance_id'] . $_POST['rate_id'][ $key ] : $shipping_label;
do_action( 'wpml_register_single_string', WCML_WC_Shipping::STRINGS_CONTEXT, $rate_key . '_shipping_method_title', $shipping_label );
}
}
}
}
/**
* @param WP_Term[] $terms
* @param int $post_id
* @param string $taxonomy
*
* @return WP_Term[]
*/
public function shipping_class_id_in_default_language( $terms, $post_id, $taxonomy ) {
global $icl_adjust_id_url_filter_off;
$is_product_object = 'product' === get_post_type( $post_id ) || 'product_variation' === get_post_type( $post_id );
if ( $terms && $is_product_object && 'product_shipping_class' === $taxonomy ) {
if ( is_admin() ) {
$shipp_class_language = $this->woocommerce_wpml->products->get_original_product_language( $post_id );
} else {
$shipp_class_language = $this->sitepress->get_default_language();
}
$cache_key = md5( wp_json_encode( $terms ) );
$cache_key .= ':' . $post_id . $shipp_class_language;
$cache_group = 'trnsl_shipping_class';
$cache_terms = wp_cache_get( $cache_key, $cache_group );
if ( $cache_terms ) {
return $cache_terms;
}
foreach ( $terms as $k => $term ) {
$shipping_class_id = apply_filters( 'translate_object_id', $term->term_id, 'product_shipping_class', false, $shipp_class_language );
$icl_adjust_id_url_filter = $icl_adjust_id_url_filter_off;
$icl_adjust_id_url_filter_off = true;
$terms[ $k ] = get_term( $shipping_class_id, 'product_shipping_class' );
$icl_adjust_id_url_filter_off = $icl_adjust_id_url_filter;
}
wp_cache_set( $cache_key, $terms, $cache_group );
}
return $terms;
}
public function show_pointer_info() {
$pointer_ui = new WCML_Pointer_UI(
/* translators: %1$s and %2$s are opening and closing HTML link tag */
sprintf( __( 'You can translate this method title on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the method title string.', 'woocommerce-multilingual' ), '', '' ),
WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
'woocommerce_table_rate_title'
);
$pointer_ui->show();
$pointer_ui = new WCML_Pointer_UI(
/* translators: %1$s and %2$s are opening and closing HTML link tag */
sprintf( __( 'You can translate the labels of your table rates on the %1$sWPML String Translation page%2$s. Use the search on the top of that page to find the labels strings.', 'woocommerce-multilingual' ), '', '' ),
WCML_Tracking_Link::getWcmlTableRateShippingDoc(),
'shipping_rates .shipping_label a'
);
$pointer_ui->show();
}
/**
* Register the new rate's shipping abort reasons.
*
* @param array[] $rates
* @return array[]
*/
public function register_abort_messages( $rates ) {
// $registerAbortReason :: array -> void
$registerAbortReason = function( $rate ) {
do_action(
'wpml_register_single_string',
WCML_WC_Shipping::STRINGS_CONTEXT,
$this->get_rate_name( $rate['rate_id'] ),
$rate['rate_abort_reason']
);
};
return wpml_collect( $rates )
->filter( Obj::prop( 'rate_abort_reason' ) )
->map( $registerAbortReason )
->toArray();
}
/**
* Unregister the deleted rate's shipping abort reasons when deleted via AJAX.
*/
public function unregister_abort_messages_ajax() {
check_ajax_referer( 'delete-rate', 'security' );
wpml_collect( (array) Obj::prop( 'rate_id', $_POST ) )
->map( Fns::unary( 'intval' ) )
->map( [ $this, 'unregister_abort_messages' ] );
}
/**
* Unregister the deleted rate's shipping abort reasons when the shipping class it's for is deleted.
*
* @param int $term_id
*/
public function unregister_abort_messages_shipping_class( $term_id ) {
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$table = $this->wpdb->prefix . 'woocommerce_shipping_table_rates';
$query = $this->wpdb->prepare(
"SELECT rate_id FROM $table WHERE rate_class=%d",
[ $term_id ]
);
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
wpml_collect( $this->wpdb->get_col( $query ) )
->map( [ $this, 'unregister_abort_messages' ] );
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Translate the rate's shipping abort reasons
*
* @param stdClass[] $rates
* @return stdClass[]
*/
public function translate_abort_messages( $rates ) {
// translateAbortReason :: stdClass -> stdClass
$translateAbortReason = function( $rate ) {
return Obj::assoc(
'rate_abort_reason',
apply_filters(
'wpml_translate_single_string',
$rate->rate_abort_reason,
WCML_WC_Shipping::STRINGS_CONTEXT,
$this->get_rate_name( $rate->rate_id )
),
$rate
);
};
return wpml_collect( $rates )
->map( Logic::ifElse( Obj::prop( 'rate_abort_reason' ), $translateAbortReason, Fns::identity() ) )
->toArray();
}
/**
* Unregister the deleted rate's shipping abort reasons for list of ids
*
* @param int $rate_id
*/
public function unregister_abort_messages( $rate_id ) {
icl_unregister_string(
WCML_WC_Shipping::STRINGS_CONTEXT,
$this->get_rate_name( $rate_id )
);
}
/**
* The name for the rate's shipping abort reason
*
* @param int $rate_id
* @return string
*/
private function get_rate_name( $rate_id ) {
return 'table_rate_shipping_abort_reason_' . $rate_id;
}
/**
* @param bool $available
* @param array $package
* @param WC_Shipping_Method $object
*
* @return bool
*/
public function shipping_table_rate_is_available( $available, $package, $object ) {
add_filter(
'option_woocommerce_table_rate_priorities_' . $object->instance_id,
[ $this, 'filter_table_rate_priorities' ]
);
remove_filter(
'woocommerce_shipping_table_rate_is_available',
[ $this, 'shipping_table_rate_is_available' ],
10
);
$available = $object->is_available( $package );
add_filter(
'woocommerce_shipping_table_rate_is_available',
[ $this, 'shipping_table_rate_is_available' ],
10,
3
);
return $available;
}
/**
* @param array $priorities
*
* @return array
*/
public function filter_table_rate_priorities( $priorities ) {
foreach ( $priorities as $slug => $priority ) {
$shipping_class_term = get_term_by( 'slug', $slug, 'product_shipping_class' );
if ( $shipping_class_term->slug !== $slug ) {
unset( $priorities[ $slug ] );
$priorities[ $shipping_class_term->slug ] = $priority;
}
}
return $priorities;
}
}