/home/sylamedg/www/wp-content/plugins/connect-polylang-elementor/includes/connect-plugins.php
<?php
namespace ConnectPolylangElementor;
use Elementor\Core\Settings\Manager as SettingsManager;
defined( 'ABSPATH' ) || exit;
class ConnectPlugins {
use \ConnectPolylangElementor\Util\Singleton;
/**
* Current template ID.
*
* @var int|null
*/
private $template_id = null;
/**
* __construct
*
* @return void
*/
private function __construct() {
// Auto add post types for translation.
add_filter( 'pll_get_post_types', array( $this, 'add_polylang_post_types' ), 10, 2 );
// Front template loading.
add_filter( 'elementor/theme/get_location_templates/template_id', array( $this, 'template_id_translation' ) );
add_filter( 'elementor/theme/get_location_templates/condition_sub_id', array( $this, 'condition_sub_id_translation' ), 10, 2 );
// Shortcode [elementor-template] translate 'template_id'.
add_filter( 'pre_do_shortcode_tag', array( $this, 'shortcode_template_translate' ), 10, 3 );
// Widget Template translate 'template_id'.
add_action( 'elementor/frontend/widget/before_render', array( $this, 'widget_template_translate' ) );
// WordPress Widget "Elementor Library" translate 'template_id'.
add_filter( 'widget_display_callback', array( $this, 'wp_widget_template_translate' ), 10, 2 );
// Elementor Kit template loading.
add_filter( 'option_elementor_active_kit', array( $this, 'elementor_kit_translation' ) );
// Fix home_url() for site-url Dynamic Tag and Search Form widget.
add_filter( 'pll_home_url_white_list', array( $this, 'elementor_home_url_white_list' ) );
add_filter( 'home_url', array( $this, 'home_url_language_dir_slash' ), 11, 2 );
// Translate Elementor order resume page (thankyou page).
add_filter( 'option_elementor_woocommerce_purchase_summary_page_id', 'pll_get_post' );
// Fix search url for Search Form widget.
add_action( 'elementor/frontend/widget/before_render', array( $this, 'add_search_form_home_url_filter' ) );
add_action( 'elementor/frontend/widget/after_render', array( $this, 'remove_search_form_home_url_filter' ) );
if ( is_admin() ) {
// All langs for template conditions & global widgets.
add_action( 'parse_query', array( $this, 'query_all_languages' ), 1 );
// Empty template conditions on translations.
add_filter( 'get_post_metadata', array( $this, 'elementor_conditions_empty_on_translations' ), 10, 3 );
add_filter( 'pre_update_option_elementor_pro_theme_builder_conditions', array( $this, 'theme_builder_conditions_remove_empty' ) );
// Global widgets hide language column.
add_action( 'manage_elementor_library_posts_custom_column', array( $this, 'hide_language_column_pre' ), 9, 2 );
add_action( 'manage_elementor_library_posts_custom_column', array( $this, 'hide_language_column_pos' ), 11, 2 );
if ( cpel_is_elementor_pro_active() ) {
// Update template conditions on language terms change.
add_action( 'set_object_terms', array( $this, 'update_conditions_on_term_change' ), 10, 4 );
// Translations conditions column.
add_action( 'manage_elementor_library_posts_custom_column', array( $this, 'instances_column_pre' ), 9, 2 );
add_action( 'manage_elementor_library_posts_custom_column', array( $this, 'instances_column_pos' ), 11, 2 );
}
// Don't add "_elementor_css" meta.
add_filter( 'update_post_metadata', array( $this, 'prevent_elementor_css_meta' ), 10, 3 );
add_action( 'pll_post_synchronized', array( $this, 'bulk_delete_elementor_css_meta' ), 10, 3 );
// Edit links for each language domain.
if ( cpel_is_polylang_multidomain() ) {
add_filter( 'post_row_actions', array( $this, 'fix_edit_link' ), 12, 2 );
add_filter( 'page_row_actions', array( $this, 'fix_edit_link' ), 12, 2 );
add_filter( 'elementor/document/urls/edit', array( $this, 'fix_elementor_edit_link' ), 10, 2 );
}
}
// Check if Elementor is installed and its version is greater than 3.25.0.
if ( cpel_elementor_min_version( '3.25.0' ) ) {
// Elementor 3.25.0 introduced a new way to handle language switcher controls.
add_action( 'elementor/documents/register_controls', array( $this, 'register_language_switcher_controls' ) );
} else {
// Deprecated way to handle language switcher controls.
// Elementor editor menu links to translations.
add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'elementor_editor_script' ) );
}
add_action( 'elementor/editor/after_enqueue_styles', array( $this, 'elementor_editor_style' ) );
// Elementor Site Editor template tweaks.
add_filter( 'elementor-pro/site-editor/data/template', array( $this, 'elementor_site_editor_template' ) );
}
/**
* Enable Elementor-specific post types automatically for Polylang translation
*
* @link https://polylang.pro/doc/filter-reference/
*
* @since 2.0.0
*
* @param array $types The list of post type names for which Polylang manages language and translations.
* @param bool $is_settings True when displaying the list in Polylang settings.
* @return array The list of post type names for which Polylang manages language and translations
*/
public function add_polylang_post_types( $types, $is_settings ) {
$relevant_types = apply_filters(
'cpel/filter/polylang/post_types',
array(
'elementor_library', // Elementor.
'e-landing-page', // Elementor Landing pages.
'oceanwp_library', // OceanWP Library.
'astra-advanced-hook', // Astra Custom Layouts (Astra Pro).
'gp_elements', // GeneratePress Elements (GP Premium).
'jet-theme-core', // JetThemeCore (Kava Pro/ CrocoBlock).
'jet-engine', // JetEngine Listing Item (CrocoBlock).
'customify_hook', // Customify (Customify Pro).
'wpbf_hooks', // Page Builder Framework Sections (WPBF Premium).
'ae_global_templates', // AnyWhere Elementor plugin.
)
);
return array_merge( $types, array_combine( $relevant_types, $relevant_types ) );
}
/**
* Query all languages if conditions meets
*
* Note: Needs to be priority 1, since Polylang uses the action parse_query
* which is fired before 'pre_get_posts'.
*
* @link https://github.com/polylang/polylang/issues/152#issuecomment-320602328
* @link https://github.com/pojome/elementor/issues/4839
*
* @since 2.0.0
*
* @param WP_Query $query current query.
* @return void
*/
public function query_all_languages( $query ) {
$global_widget_meta_query = array(
'key' => '_elementor_template_type',
'value' => 'widget',
);
$is_elementor_conditions = isset( $query->query_vars['meta_key'] )
&& '_elementor_conditions' === $query->query_vars['meta_key'];
$is_global_widget = isset( $query->query_vars['post_type'], $query->query_vars['meta_query'] )
&& 'elementor_library' === $query->query_vars['post_type']
&& is_array( $query->query_vars['meta_query'] )
&& in_array( $global_widget_meta_query, $query->query_vars['meta_query'], true );
if ( $is_elementor_conditions || $is_global_widget ) {
$query->set( 'lang', '' );
}
}
/**
* Return empty conditions on secondary translations
*
* @since 2.0.0
*
* @param mixed $null null for bypass.
* @param int $post_id current post ID.
* @param string $meta_key name of meta key.
* @return mixed null or empty array
*/
public function elementor_conditions_empty_on_translations( $null, $post_id, $meta_key ) {
return '_elementor_conditions' === $meta_key && cpel_is_translation( $post_id ) ? array( array() ) : $null;
}
/**
* Clear empty conditions before save 'elementor_pro_theme_builder_conditions' option
*
* @since 2.0.0
*
* @param array $value array of theme builder conditions.
* @return array filtered array
*/
public function theme_builder_conditions_remove_empty( $value ) {
foreach ( $value as $location => $items ) {
$value[ $location ] = array_filter( $items );
}
return array_filter( $value );
}
/**
* Bypass Elementor template shortcode with their translation for the current language (if exists).
*
* @since 2.2.0
*
* @uses pll_get_post()
*
* @param mixed $false false or string with bypass output.
* @param string $tag shortcode tag.
* @param array $attr shortcode attributes.
* @return false|string false or string with bypass output
*/
public function shortcode_template_translate( $false, $tag, $attr ) {
if ( 'elementor-template' !== $tag ) {
return $false;
}
if ( isset( $attr['skip'] ) ) {
return $false;
}
// Translate post_id safely.
if ( isset( $attr['id'] ) && '' !== $attr['id'] ) {
$id = absint( $attr['id'] );
if ( $id ) {
$attr['id'] = pll_get_post( $id ) ?: $id; //phpcs:ignore WordPress.PHP.DisallowShortTernary
}
}
// Skip next call.
$attr['skip'] = 1;
$output = '';
foreach ( $attr as $key => $val ) {
$output .= ' ' . esc_attr( sanitize_key( $key ) ) . '="' . esc_attr( $val ) . '"';
}
return do_shortcode( '[elementor-template' . $output . ']' );
}
/**
* Widget Template translate template_id
*
* @since 2.3.5
*
* @uses pll_get_post()
*
* @param \Elementor\Element_Base $element
* @return void
*/
public function widget_template_translate( $element ) {
if ( 'template' !== $element->get_name() ) {
return;
}
$template_id = pll_get_post( $element->get_settings( 'template_id' ) ) ?: $element->get_settings( 'template_id' ); //phpcs:ignore WordPress.PHP.DisallowShortTernary
$element->set_settings( 'template_id', $template_id );
}
/**
* WordPress Widget "Elementor Library" translate 'template_id'
*
* @since 2.4.4
*
* @param array $instance
* @param WP_Widget $widget
* @return array
*/
public function wp_widget_template_translate( $instance, $widget ) {
if ( is_a( $widget, 'ElementorPro\Modules\Library\WP_Widgets\Elementor_Library' ) ) {
$instance['template_id'] = pll_get_post( absint( $instance['template_id'] ) ) ?: $instance['template_id']; //phpcs:ignore WordPress.PHP.DisallowShortTernary
}
return $instance;
}
/**
* Change Elementor Kit template with their translation for the current language (if exists).
*
* @since 2.3.0
*
* @uses pll_get_post()
* @uses pll_get_post_language()
*
* @param mixed $value Value of 'elementor_active_kit' option, the ID of current Elementor Kit.
* @return int The translation ID, or the original Elementor Kit ID
*/
public function elementor_kit_translation( $value ) {
$translation = null;
// Is API REST '/wp-json/elementor/v1/globals'.
if ( defined( 'REST_REQUEST' ) && REST_REQUEST && isset( $_SERVER['HTTP_REFERER'] ) ) {
// Referrer is Elementor Editor?
$referer = esc_url_raw( $_SERVER['HTTP_REFERER'] );
wp_parse_str( wp_parse_url( $referer, PHP_URL_QUERY ), $query );
if ( isset( $query['action'], $query['post'] ) && 'elementor' === $query['action'] ) {
$translation = pll_get_post( $value, pll_get_post_language( absint( $query['post'] ) ) );
}
} elseif ( cpel_is_elementor_editor() ) {
$post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
$translation = $post_id ? pll_get_post( $value, pll_get_post_language( $post_id ) ) : null;
} elseif ( ! is_admin() ) {
$translation = pll_get_post( $value );
}
return $translation ? $translation : $value;
}
/**
* Change Elementor template with their translation for the current language (if exists).
*
* @link https://github.com/pojome/elementor/issues/4839
*
* @since 2.0.0
*
* @uses pll_get_post()
*
* @param int $post_id ID of the current post.
* @return string Based translation, the translation ID, or the original Post ID
*/
public function template_id_translation( $post_id ) {
$post_id = pll_get_post( $post_id ) ?: $post_id; //phpcs:ignore WordPress.PHP.DisallowShortTernary
$this->template_id = $post_id; // Save for check sub_id.
return $post_id;
}
/**
* Filter Elementor sub_conditions system
*
* If is translated template that is based on term or post
* return the translation ID of term or post.
*
* @since 2.0.0
*
* @uses pll_get_post()
* @uses pll_get_term()
*
* @param int $sub_id ID of the object in subcondition.
* @param array $parsed_condition condition parts.
* @return int original sub ID or translated ID
*/
public function condition_sub_id_translation( $sub_id, $parsed_condition ) {
if ( $sub_id && cpel_is_translation( $this->template_id ) ) {
if ( in_array( $parsed_condition['sub_name'], get_post_types(), true ) ) {
$sub_id = pll_get_post( $sub_id ) ?: $sub_id; //phpcs:ignore WordPress.PHP.DisallowShortTernary
} else {
$sub_id = pll_get_term( $sub_id ) ?: $sub_id; //phpcs:ignore WordPress.PHP.DisallowShortTernary
}
}
return $sub_id;
}
/**
* Update Elementor conditions
*
* On change post_translations terms on Elementor Library trigger conditions regenerate.
*
* @since 2.0.0
*
* @param mixed $post_id
* @param mixed $terms
* @param mixed $tt_ids
* @param mixed $taxonomy
* @return void
*/
public function update_conditions_on_term_change( $post_id, $terms, $tt_ids, $taxonomy ) {
if ( 'post_translations' === $taxonomy && 'elementor_library' === get_post_type( $post_id ) ) {
$theme_builder = \ElementorPro\Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
$theme_builder->get_conditions_manager()->get_cache()->regenerate();
}
}
/**
* Hide language column info pre
*
* Wrap language info for Global Widgets with a hidden div (open)
*
* @since 2.0.0
*
* @param string $column
* @param int $post_id
* @return void
*/
public function hide_language_column_pre( $column, $post_id ) {
if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
echo '<span aria-hidden="true">—</span><div class="hidden" aria-hidden="true">';
}
}
/**
* Hide language column info pos
*
* Wrap language info for Global Widgets with a hidden div (close)
*
* @since 2.0.0
*
* @param string $column
* @param int $post_id
* @return void
*/
public function hide_language_column_pos( $column, $post_id ) {
if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
echo '</div>';
}
}
/**
* Show default language instances in translations
*
* (Also wrap "None" with a hidden div)
*
* @since 2.0.4
*
* @param string $column
* @param int $post_id
* @return void
*/
public function instances_column_pre( $column, $post_id ) {
if ( 'instances' === $column && 'widget' !== get_post_meta( $post_id, '_elementor_template_type', true ) && cpel_is_translation( $post_id ) ) {
$default_post = pll_get_post( $post_id, pll_default_language() );
$theme_builder = \ElementorPro\Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
$instances = $theme_builder->get_conditions_manager()->get_document_instances( $default_post );
if ( empty( $instances ) ) {
$instances = array( 'none' => esc_html__( 'None', 'elementor-pro' ) ); // phpcs:ignore WordPress.WP.I18n
}
echo '<span style="opacity:.4">' . esc_html( implode( ', ', $instances ) ) . '</span><div class="hidden" aria-hidden="true">';
}
}
/**
* Show default language instances in translations (close)
*
* @since 2.0.4
*
* @param string $column
* @param int $post_id
* @return void
*/
public function instances_column_pos( $column, $post_id ) {
if ( 'instances' === $column && 'widget' !== get_post_meta( $post_id, '_elementor_template_type', true ) && cpel_is_translation( $post_id ) ) {
echo '</div>';
}
}
/**
* Don't copy '_elementor_css' meta on Polylang add new translation
*
* Without this meta Elementor generates the css for the new post.
*
* @since 2.0.0
*
* @param mixed $null
* @param int $post_id
* @param string $meta_key
* @return mixed null or false
*/
public function prevent_elementor_css_meta( $null, $post_id, $meta_key ) {
global $pagenow;
return '_elementor_css' === $meta_key && 'post-new.php' === $pagenow
&& isset( $_GET['from_post'], $_GET['new_lang'] )
&& ! empty( absint( wp_unslash( $_GET['from_post'] ) ) )
&& ! empty( sanitize_key( wp_unslash( $_GET['new_lang'] ) ) ) ? false : $null;
}
/**
* Delete '_elementor_css' meta on Polylang bulk translation
*
* Without this meta Elementor generates the css for the new post.
*
* @since 2.4.3
*
* @param int $post_id
* @param int $tr_id
* @param string $lang
* @return void
*/
public function bulk_delete_elementor_css_meta( $post_id, $tr_id, $lang ) {
delete_post_meta( $tr_id, '_elementor_css' );
}
/**
* Whitelist Elementor Pro home_url()
*
* Polylang add home_url() to whitelist for Elementor Pro
* "Search Form" widget and "Site Url" dynamic tag.
*
* @since 2.0.0
*
* @param array $white_list
* @return array
*/
public function elementor_home_url_white_list( $white_list ) {
$white_list[] = array( 'file' => 'site-url.php' );
return $white_list;
}
/**
* Language subdir add trailing slash
*
* @since 2.0.0
*
* @param string $url
* @param string $path
* @return string
*/
public function home_url_language_dir_slash( $url, $path ) {
return empty( $path ) && ! is_admin() && get_option( 'home' ) !== $url
&& function_exists( 'PLL' ) && 1 === PLL()->options['force_lang'] ? trailingslashit( $url ) : $url;
}
/**
* Replace home_url with correct language search url
*
* Only for Elementor Search Form that uses home_url() in form action.
*
* @since 2.0.6
*
* @param string $url
* @param string $path
* @return string
*/
public function search_form_home_url_filter( $url, $path ) {
if ( ! function_exists( 'PLL' ) || ! is_a( PLL()->curlang, 'PLL_Language', true ) ) {
return $url;
}
return method_exists( PLL()->curlang, 'get_search_url' ) ?
PLL()->curlang->get_search_url() :
PLL()->curlang->search_url;
}
/**
* Add home_url() filter before render Search Form
*
* @since 2.0.6
*
* @param Element_Base $element
* @return void
*/
public function add_search_form_home_url_filter( $element ) {
if ( 'search' === $element->get_name() || 'search-form' === $element->get_name() ) {
add_filter( 'home_url', array( $this, 'search_form_home_url_filter' ), 10, 2 );
}
}
/**
* Remove home_url() filter after render Search Form
*
* @since 2.0.6
*
* @param Element_Base $element
* @return void
*/
public function remove_search_form_home_url_filter( $element ) {
if ( 'search' === $element->get_name() || 'search-form' === $element->get_name() ) {
remove_filter( 'home_url', array( $this, 'search_form_home_url_filter' ) );
}
}
/**
* Elementor editor script
*
* Add script with links to translations on Elementor editor panel.
*
* @since 2.0.0
*
* @return void
*/
public function elementor_editor_script() {
global $typenow, $post;
// If is post type translatable.
if ( pll_is_translated_post_type( $typenow ) ) {
$languages = pll_languages_list( array( 'fields' => '' ) );
$translations = pll_get_post_translations( $post->ID );
$current = pll_get_post_language( $post->ID, 'name' );
$use_emojis = apply_filters( 'cpel/filter/use_emojis', true );
$items = array();
foreach ( $languages as $language ) {
if ( $language->name === $current ) {
$translation_id = $translations[ $language->slug ];
$items[] = array(
'name' => 'cpel-current',
'icon' => 'eicon-document-file',
'title' => sprintf(
'%s — %s',
get_the_title( $translation_id ),
$use_emojis ? cpel_flag_emoji( $language->flag_code ) : $language->name
),
'callback' => 'function(){}',
);
} elseif ( isset( $translations[ $language->slug ] ) ) {
$translation_id = $translations[ $language->slug ];
$link = $this->fix_url_domain( get_edit_post_link( $translation_id, 'edit' ), $translation_id );
if ( get_post_meta( $translation_id, '_elementor_edit_mode', true ) ) {
$link = add_query_arg( 'action', 'elementor', $link );
}
$items[] = array(
'name' => "cpel-{$language->slug}",
'icon' => 'eicon-document-file',
'title' => sprintf(
'%s — %s',
get_the_title( $translation_id ),
$use_emojis ? cpel_flag_emoji( $language->flag_code ) : $language->name
),
'type' => 'link',
'link' => $link,
);
} else {
$args = array(
'post_type' => $typenow,
'from_post' => $post->ID,
'new_lang' => $language->slug,
'_wpnonce' => wp_create_nonce( 'new-post-translation' ),
);
$link = add_query_arg( $args, admin_url( 'post-new.php' ) );
$items[] = array(
'name' => "cpel-{$language->slug}",
'icon' => 'eicon-plus',
'title' => $use_emojis
? sprintf( __( 'Add a translation — %s', 'connect-polylang-elementor' ), cpel_flag_emoji( $language->flag_code ) ) // phpcs:ignore WordPress.WP.I18n
: sprintf( __( 'Add a translation in %s', 'polylang' ), $language->name ), // phpcs:ignore WordPress.WP.I18n
'type' => 'link',
'link' => $link,
);
}
}
$group = array(
'name' => 'cpel',
'title' => __( 'Languages', 'polylang' ), // phpcs:ignore WordPress.WP.I18n
'items' => $items,
);
$script = 'jQuery(window).on("elementor:init", () => {
window.elementor.on("panel:init", () => {
setTimeout(() => { window.elementor.modules.layouts.panel.pages.menu.Menu.groups.add(' . wp_json_encode( $group ) . '); });
});
});';
// Add after Elementor editor script.
wp_add_inline_script( 'elementor-editor', $script );
}
}
/**
* Elementor editor script
*
* Add script with links to translations on Elementor editor panel.
*
* @since 2.3.5
*
* @return void
*/
public function elementor_editor_style() {
global $typenow;
// If is post type translatable.
if ( ! pll_is_translated_post_type( $typenow ) ) {
return;
}
// New language switcher styles for Elementor 3.25.0+.
if ( cpel_elementor_min_version( '3.25.0' ) ) {
$style = '
.elementor-control-cpel-languages a {
display: flex;
gap: 8px;
align-items: center;
padding: 8px 5px;
border: none;
color: inherit;
line-height: 1.25em;
font-weight: 400;
text-decoration: none;
transition: none;
}
.elementor-control-cpel-languages a.current, .elementor-control-cpel-languages a:hover {
background-color: var(--e-a-bg-hover);
color: inherit;
}
.elementor-control-cpel-languages i {
font-size: 16px;
}
.elementor-control-cpel-languages .flag {
margin-left: auto;
font-size: 16px;
}';
wp_add_inline_style( 'elementor-editor', $style );
return;
}
// Old language switcher styles for Elementor < 3.25.0
$style = '' .
".elementor-panel .elementor-panel-menu-item.elementor-panel-menu-item-cpel-current {\n" .
" background: #eceeef;\n" .
" cursor: default;\n" .
'}';
wp_add_inline_style( 'elementor-editor', $style );
$ui_theme = SettingsManager::get_settings_managers( 'editorPreferences' )->get_model()->get_settings( 'ui_theme' );
if ( 'light' !== $ui_theme ) {
$ui_theme_media_queries = 'auto' === $ui_theme ? '(prefers-color-scheme: dark)' : 'all';
$dark = '' .
"@media $ui_theme_media_queries {\n" .
" .elementor-panel .elementor-panel-menu-item.elementor-panel-menu-item-cpel-current {\n" .
" background: #7d7e82;\n" .
" }\n" .
'}';
wp_add_inline_style( 'elementor-editor-dark-mode', $dark );
}
}
/**
* Elementor Site Editor template changes
*
* At 2.0.0 named "elementor_theme_editor_title"
*
* @since 2.0.4
*
* @param array $data
* @return array
*/
public function elementor_site_editor_template( $data ) {
$post_id = $data['id'];
// Add lang info to title.
if ( apply_filters( 'cpel/filter/use_emojis', true ) ) {
$data['title'] = sprintf( '%s — %s', $data['title'], cpel_flag_emoji( pll_get_post_language( $post_id, 'flag_code' ) ) );
} else {
$data['title'] = sprintf( '%s — %s', $data['title'], pll_get_post_language( $post_id, 'name' ) );
}
// Show default language instances in translations (and recalc isActive).
if ( cpel_is_translation( $post_id ) ) {
$language = pll_default_language();
$default_post = pll_get_post( $post_id, $language );
$theme_builder = \ElementorPro\Plugin::instance()->modules_manager->get_modules( 'theme-builder' );
$instances = $theme_builder->get_conditions_manager()->get_document_instances( $default_post );
if ( empty( $instances ) ) {
$instances = array( 'no_instances' => esc_html__( 'No instances', 'elementor-pro' ) ); // phpcs:ignore WordPress.WP.I18n
$is_active = false;
} else {
$is_active = 'publish' === $data['status'];
}
$data['instances'] = array( 'cpel' => sprintf( esc_html__( '(from %s)', 'connect-polylang-elementor' ), strtoupper( $language ) ) ) + $instances; // phpcs:ignore WordPress.WP.I18n
$data['isActive'] = $is_active;
}
return $data;
}
/**
* Fix url domain
*
* @param mixed $url current url.
* @param mixed $post_id current post ID.
* @return string fixed domain url
*/
private function fix_url_domain( $url, $post_id ) {
$current_host = wp_parse_url( pll_current_language( 'home_url' ) ?: trailingslashit( '//' . sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) ), PHP_URL_HOST ); //phpcs:ignore WordPress.PHP.DisallowShortTernary
$post_host = wp_parse_url( pll_get_post_language( $post_id, 'home_url' ), PHP_URL_HOST );
if ( $current_host !== $post_host ) {
$url = str_replace( $current_host, $post_host, $url );
}
return $url;
}
/**
* Fix domain for Elementor edit links in posts table
*
* @param array $actions
* @param WP_Post $post
* @return array
*/
public function fix_edit_link( $actions, $post ) {
if ( ! empty( $actions['edit_with_elementor'] ) ) {
// $actions['edit'] = $this->fix_url_domain( $actions['edit'], $post->ID );
$actions['edit_with_elementor'] = $this->fix_url_domain( $actions['edit_with_elementor'], $post->ID );
}
return $actions;
}
/**
* Fix domain for Elementor edit links in Theme Builder
*
* @param string $url
* @param Elementor\Core\Base\Document $document
* @return string
*/
public function fix_elementor_edit_link( $url, $document ) {
return $this->fix_url_domain( $url, $document->get_main_id() );
}
/**
* Register language switcher controls in Elementor's document settings panel.
* This function adds a "Languages" section where users can manage translations for the current post.
*
* @param \Elementor\Base\Document $document The Elementor document object.
* @since 2.5.0
*/
public function register_language_switcher_controls( $document ) {
global $typenow, $post;
// Exit if is not translatable.
if ( ! pll_is_translated_post_type( $typenow ) ) {
return;
}
// Get the current post ID being edited in Elementor.
$post_id = $post->ID;
// Retrieve available languages from Polylang.
$languages = pll_languages_list( array( 'fields' => '' ) );
$translations = pll_get_post_translations( $post_id );
$raw_html = '';
// Start adding a new section in Elementor settings panel.
$document->start_controls_section(
'cpel_language_section',
array(
'label' => esc_html__( 'Languages', 'polylang' ), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'tab' => \Elementor\Controls_Manager::TAB_SETTINGS,
)
);
// Loop through each available language.
foreach ( $languages as $language ) {
$lang_parts = array(
'class' => 'cpel-language',
'href' => '',
'icon' => '',
'text' => '',
'flag' => str_replace( '<img ', '<img class="flag" ', $language->flag ),
);
// Check if a translation exists for the current language.
if ( isset( $translations[ $language->slug ] ) ) {
// Get the post ID of the translated post.
$translation_id = $translations[ $language->slug ];
$lang_parts['icon'] = '<i class="eicon-document-file"></i>';
$lang_parts['text'] = '<span class="text">' . esc_html( get_the_title( $translation_id ) ) . '</span>';
if ( $translation_id === $post_id ) {
$lang_parts['class'] .= ' current';
} else {
// Get edit link for the translated post.
$edit_link = get_edit_post_link( $translation_id, 'edit' );
// Modify edit link if it's built with Elementor.
if ( get_post_meta( $translation_id, '_elementor_edit_mode', true ) ) {
$edit_link = add_query_arg( 'action', 'elementor', $edit_link );
}
$lang_parts['href'] = $edit_link;
}
} else {
// Generate the create translation link.
$args = array(
'post_type' => get_post_type( $post_id ),
'from_post' => $post_id,
'new_lang' => $language->slug,
'_wpnonce' => wp_create_nonce( 'new-post-translation' ),
);
$create_link = add_query_arg( $args, admin_url( 'post-new.php' ) );
$lang_parts['class'] .= ' add-new';
$lang_parts['icon'] = '<i class="eicon-plus"></i>';
$lang_parts['href'] = $create_link;
$lang_parts['text'] = '<span class="text">' . sprintf( esc_html__( 'Add a translation in %s', 'polylang' ), strtolower( esc_html( $language->name ) ) ) . '</span>'; // phpcs:ignore WordPress.WP.I18n
}
$raw_html .= sprintf(
'<li><a class="%s" %s>%s %s %s</a></li>',
$lang_parts['class'],
$lang_parts['href'] ? sprintf( 'href="%s" target="_blank"', esc_url( $lang_parts['href'] ) ) : '',
$lang_parts['icon'],
$lang_parts['text'],
$lang_parts['flag']
);
}
$document->add_control(
'cpel_languages',
array(
'type' => \Elementor\Controls_Manager::RAW_HTML,
'raw' => '<ul>' . $raw_html . '</ul>',
'content_classes' => 'elementor-control-cpel-languages',
)
);
// End the controls section.
$document->end_controls_section();
}
}