File: /var/www/indoadvisory/wp/wp-content/plugins/polylang-wc/frontend/frontend.php
<?php
/**
* @package Polylang-WC
*/
/**
* Manages WooCommerce specific translations on the frontend.
*
* @since 0.1
*/
class PLLWC_Frontend {
/**
* Constructor.
*
* @since 0.1
*/
public function __construct() {
if ( did_action( 'pll_language_defined' ) ) {
$this->init();
} else {
add_action( 'pll_language_defined', array( $this, 'init' ), 1 );
add_action( 'woocommerce_init', array( $this, 'override_countries' ), 1 );
// Set the language early if a form has been posted with a language value.
if ( ! empty( $_REQUEST['lang'] ) && $lang = PLL()->model->get_language( sanitize_key( $_REQUEST['lang'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
PLL()->curlang = $lang;
$GLOBALS['text_direction'] = $lang->is_rtl ? 'rtl' : 'ltr'; // phpcs:ignore WordPress.WP.GlobalVariablesOverride
do_action( 'pll_language_defined', $lang->slug, $lang );
}
}
}
/**
* Setups actions filters once the language is defined.
*
* @since 0.1
*
* @return void
*/
public function init() {
PLLWC_Filter_WC_Pages::init();
// Filters the product search form.
if ( is_callable( array( PLL()->filters_search, 'get_search_form' ) ) ) {
add_filter( 'get_product_search_form', array( PLL()->filters_search, 'get_search_form' ), 99 );
add_filter( 'render_block_woocommerce/product-search', array( PLL()->filters_search, 'get_search_form' ) );
}
if ( ! PLL()->options['force_lang'] ) {
if ( ! get_option( 'permalink_structure' ) ) {
// Fix product page when using plain permalinks and the language is set from the content.
add_filter( 'pll_check_canonical_url', array( $this, 'pll_check_canonical_url' ) );
add_filter( 'pll_translation_url', array( $this, 'pll_translation_url' ), 10, 2 );
} else {
// Fix shop link when using pretty permalinks and the language is set from the content.
add_filter( 'post_type_archive_link', array( $this, 'post_type_archive_link' ), 99, 2 ); // After Polylang.
}
// Add the language input field to forms to detect the language before wp_loaded is fired.
$actions = array(
'woocommerce_login_form_start', // Login.
'woocommerce_register_form_start', // Register.
'woocommerce_before_cart_table', // Cart.
'woocommerce_before_add_to_cart_button', // Product.
'woocommerce_lostpassword_form', // Lost password.
);
foreach ( $actions as $action ) {
add_action( $action, array( $this, 'language_form_field' ) );
}
add_filter( 'woocommerce_get_remove_url', array( $this, 'add_lang_query_arg' ) );
}
// Translates home url in widgets.
add_filter( 'pll_home_url_white_list', array( $this, 'home_url_white_list' ) );
// Layered nav chosen attributes.
add_filter( 'woocommerce_product_query_tax_query', array( $this, 'product_tax_query' ) );
if ( PLL()->options['force_lang'] > 1 ) {
add_filter( 'home_url', array( $this, 'fix_widget_price_filter' ), 10, 2 );
}
// Object cache compatibility.
add_filter( 'woocommerce_shortcode_products_query', array( $this, 'shortcode_products_query' ) ); // Since WC 3.0.2.
add_filter( 'woocommerce_get_product_subcategories_cache_key', array( $this, 'get_product_subcategories_cache_key' ) );
// Ajax endpoint.
add_filter( 'woocommerce_ajax_get_endpoint', array( $this, 'ajax_get_endpoint' ), 10, 2 );
// Handles Coming Soon for product and taxonomy pages.
add_filter( 'woocommerce_is_extension_store_page', array( $this, 'is_store_page' ) );
}
/**
* Replaces WooCommerce countries class by our own when language is set from the content.
*
* @since 1.9.2
*
* @return void
*/
public function override_countries() {
WC()->countries = new PLLWC_Countries();
}
/**
* Fixes the canonical redirection from the shop page to the product archive when using plain permalinks and the language is set from the content
*
* @since 0.3.2
*
* @param string $redirect_url Redirect url.
* @return string|false
*/
public function pll_check_canonical_url( $redirect_url ) {
if ( is_post_type_archive( 'product' ) ) {
return false;
}
return $redirect_url;
}
/**
* Fixes the translation url of the shop page (product archive) when using plain permalinks and the language is set from the content.
*
* @since 0.3.2
*
* @param string $url Translation url.
* @param string $lang Language code.
* @return string
*/
public function pll_translation_url( $url, $lang ) {
if ( is_post_type_archive( 'product' ) ) {
$lang = PLL()->model->get_language( $lang );
if ( $lang ) {
if ( PLL()->options['hide_default'] && 'page' === get_option( 'show_on_front' ) && PLL()->options['default_lang'] === $lang->slug ) {
$pages = pll_languages_list( array( 'fields' => 'page_on_front' ) );
if ( in_array( wc_get_page_id( 'shop' ), $pages ) ) {
return $lang->get_home_url();
}
}
$url = get_post_type_archive_link( 'product' );
$url = PLL()->links_model->switch_language_in_link( $url, $lang );
$url = PLL()->links_model->remove_paged_from_link( $url );
}
}
return $url;
}
/**
* Fixes the shop link when using pretty permalinks and the language is set from the content.
*
* This fixes the widget layered nav which calls get_post_type_archive_link( 'product' ).
*
* @since 0.4.6
*
* @param string $link Post type archive link.
* @param string $post_type Post type name.
* @return string Modified link.
*/
public function post_type_archive_link( $link, $post_type ) {
return 'product' === $post_type ? wc_get_page_permalink( 'shop' ) : $link;
}
/**
* Outputs the hidden language input field.
*
* @since 0.3.5
*
* @return void
*/
public function language_form_field() {
printf( '<input type="hidden" name="lang" value="%s" />', esc_attr( pll_current_language() ) );
}
/**
* Adds a lang query arg to the url.
*
* @since 0.5
*
* @param string $url URL to modify.
* @return string
*/
public function add_lang_query_arg( $url ) {
return add_query_arg( 'lang', pll_current_language(), $url );
}
/**
* Fixes the home url in widgets
*
* @since 0.5
*
* @param string[][] $arr List of files and functions to whitelist for the home_url filter.
* @return string[][]
*/
public function home_url_white_list( $arr ) {
$arr = array_merge(
$arr,
array( array( 'file' => 'abstract-wc-widget.php' ) )
);
// Avoid a redirect when the language is set from the content.
if ( PLL()->options['force_lang'] > 0 ) {
$arr = array_merge(
$arr,
array( array( 'file' => 'class-wc-widget-product-categories.php' ) )
);
}
if ( PLL()->options['force_lang'] > 1 ) {
$arr = array_merge(
$arr,
array( array( 'file' => 'class-wc-widget-price-filter.php' ) )
);
}
return $arr;
}
/**
* Fixes the layered nav chosen attributes when shared slugs are in the query,
* otherwise the query would look for products in all attributes in all languages which always returns an empty result.
*
* @since 0.5
*
* @param array $tax_query Tax query parameter in WP_Query.
* @return array
*/
public function product_tax_query( $tax_query ) {
foreach ( $tax_query as $k => $q ) {
if ( is_array( $q ) && ! empty( $q['field'] ) && 'slug' === $q['field'] ) {
$terms = get_terms( array( 'taxonomy' => $q['taxonomy'], 'slug' => $q['terms'] ) );
if ( is_array( $terms ) ) {
$tax_query[ $k ]['terms'] = wp_list_pluck( $terms, 'term_taxonomy_id' );
$tax_query[ $k ]['field'] = 'term_taxonomy_id';
}
}
}
return $tax_query;
}
/**
* Filters the form action url of the widget price filter for subdomains and multiple domains.
*
* @since 0.5
*
* @param string $url Form action url.
* @param string $path Path.
* @return string
*/
public function fix_widget_price_filter( $url, $path ) {
global $wp;
if ( ! empty( $wp->request ) && trailingslashit( $wp->request ) === $path && ! empty( PLL()->curlang ) ) {
$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
}
return $url;
}
/**
* Adds the language to the shortcodes query args to get one cache key per language.
* Needed for WC 3.0, Requires WC 3.0.2+
*
* @since 0.7.4
*
* @param array $args WP_Query arguments.
* @return array
*/
public function shortcode_products_query( $args ) {
if ( empty( PLL()->curlang ) ) {
return $args;
}
$args['tax_query'][] = array(
'taxonomy' => 'language',
'field' => 'term_taxonomy_id',
'terms' => PLL()->curlang->get_tax_prop( 'language', 'term_taxonomy_id' ),
'operator' => 'IN',
);
return $args;
}
/**
* Makes the product subcategories cache key language dependent.
*
* @since 1.2.3
*
* @param string $cache_key WooCommerce product subcategories cache key.
* @return string
*/
public function get_product_subcategories_cache_key( $cache_key ) {
$curlang = pll_current_language();
return $cache_key . '-' . $curlang;
}
/**
* Make sure that the ajax endpoint is in the right language.
* Required since WC 3.2.
*
* @since 0.9.1
*
* @param string $url Ajax endpoint.
* @param string $request Ajax endpoint request.
* @return string
*/
public function ajax_get_endpoint( $url, $request ) {
// Remove wc-ajax to avoid the value %%endpoint%% to be encoded by add_query_arg (used in plain permalinks).
$url = remove_query_arg( 'wc-ajax', $url );
if ( ! empty( PLL()->curlang ) ) {
$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
}
return add_query_arg( 'wc-ajax', $request, $url );
}
/**
* Tells that we're on a store page if it's a product or taxonomy page.
*
* @since 2.1
*
* @param bool $is_store_page Whether or not we're on a store page.
* @return bool
*/
public function is_store_page( $is_store_page ) {
if ( is_product() || is_product_taxonomy() ) {
return true;
}
return $is_store_page;
}
}