Polylang Connect for Elementor – Templates Translation & Language Switcher - Version 2.1.0

Version Description

  • Fixed cross domain issues with Polylang setup with multiple domains.
  • Fix flag SVG inline with some themes.
Download this release

Release Info

Developer pacotole
Plugin Icon 128x128 Polylang Connect for Elementor – Templates Translation & Language Switcher
Version 2.1.0
Comparing to
See all releases

Code changes from version 2.0.8 to 2.1.0

README.txt CHANGED
@@ -5,7 +5,7 @@ Tags: elementor, polylang, multilingual, language switcher, languages, templates
5
  Requires at least: 5.4
6
  Tested up to: 5.9
7
  Requires PHP: 5.6
8
- Stable tag: 2.0.8
9
  License: GPL-2.0-or-later
10
  License URI: https://opensource.org/licenses/GPL-2.0
11
 
@@ -96,6 +96,7 @@ You can collaborate with your language translations in [Translating WordPress](h
96
  The following code/classes are licensed under the GPL.
97
 
98
  * v2. refactor and upgrade by [Pacotole](https://profiles.wordpress.org/pacotole/) at [Creame](https://crea.me)
 
99
  * Support [Brad Johnson](https://profiles.wordpress.org/p4fbradjohnson/)
100
  * v1. released by [David Decker](https://profiles.wordpress.org/daveshine/)
101
  * v1. Polylang Switcher class (Elementor Widget) and its CSS based on widget from plugin "Language Switcher for Elementor" by Solitweb (GPLv2 or later)
@@ -194,6 +195,10 @@ There are quite a few:
194
 
195
  == Changelog ==
196
 
 
 
 
 
197
  = 2.0.8 =
198
  * Don't load integrations if Polylang languages are not defined.
199
 
5
  Requires at least: 5.4
6
  Tested up to: 5.9
7
  Requires PHP: 5.6
8
+ Stable tag: 2.1.0
9
  License: GPL-2.0-or-later
10
  License URI: https://opensource.org/licenses/GPL-2.0
11
 
96
  The following code/classes are licensed under the GPL.
97
 
98
  * v2. refactor and upgrade by [Pacotole](https://profiles.wordpress.org/pacotole/) at [Creame](https://crea.me)
99
+ * v2.1 Cross domain fixes based on work of [Jory Hogeveen](https://profiles.wordpress.org/keraweb/) and [nicmare](https://github.com/nicmare)
100
  * Support [Brad Johnson](https://profiles.wordpress.org/p4fbradjohnson/)
101
  * v1. released by [David Decker](https://profiles.wordpress.org/daveshine/)
102
  * v1. Polylang Switcher class (Elementor Widget) and its CSS based on widget from plugin "Language Switcher for Elementor" by Solitweb (GPLv2 or later)
195
 
196
  == Changelog ==
197
 
198
+ = 2.1.0 =
199
+ * Fixed cross domain issues with Polylang setup with multiple domains.
200
+ * Fix flag SVG inline with some themes.
201
+
202
  = 2.0.8 =
203
  * Don't load integrations if Polylang languages are not defined.
204
 
connect-polylang-elementor.php CHANGED
@@ -8,7 +8,7 @@
8
  * Plugin Name: Polylang Connect for Elementor
9
  * Plugin URI: https://github.com/creame/connect-polylang-elementor
10
  * Description: Connect Polylang with Elementor. Display templates in the correct language, language switcher widget, language visibility conditions and dynamic tags.
11
- * Version: 2.0.8
12
  * Author: Creame
13
  * Author URI: https://crea.me/
14
  * License: GPL-2.0-or-later
@@ -31,7 +31,7 @@ defined( 'ABSPATH' ) || exit;
31
  *
32
  * @since 2.0.0
33
  */
34
- define( 'CPEL_PLUGIN_VERSION', '2.0.8' );
35
  define( 'CPEL_FILE', __FILE__ );
36
  define( 'CPEL_DIR', plugin_dir_path( CPEL_FILE ) );
37
  define( 'CPEL_BASENAME', plugin_basename( CPEL_FILE ) );
@@ -69,10 +69,14 @@ spl_autoload_register(
69
  );
70
 
71
 
72
- // Initialize plugin
73
  add_action( 'plugins_loaded', 'ConnectPolylangElementor\\setup', 20 );
74
  add_action( 'init', 'ConnectPolylangElementor\\load_textdomain' );
75
 
 
 
 
 
76
 
77
  /**
78
  * Plugin setup.
@@ -87,6 +91,7 @@ function setup() {
87
 
88
  if ( cpel_is_polylang_api_active() && cpel_is_elementor_active() ) {
89
 
 
90
  ConnectPlugins::instance();
91
  LanguageVisibility::instance();
92
  DynamicTags\Manager::instance();
@@ -115,3 +120,62 @@ function load_textdomain() {
115
 
116
  }
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  * Plugin Name: Polylang Connect for Elementor
9
  * Plugin URI: https://github.com/creame/connect-polylang-elementor
10
  * Description: Connect Polylang with Elementor. Display templates in the correct language, language switcher widget, language visibility conditions and dynamic tags.
11
+ * Version: 2.1.0
12
  * Author: Creame
13
  * Author URI: https://crea.me/
14
  * License: GPL-2.0-or-later
31
  *
32
  * @since 2.0.0
33
  */
34
+ define( 'CPEL_PLUGIN_VERSION', '2.1.0' );
35
  define( 'CPEL_FILE', __FILE__ );
36
  define( 'CPEL_DIR', plugin_dir_path( CPEL_FILE ) );
37
  define( 'CPEL_BASENAME', plugin_basename( CPEL_FILE ) );
69
  );
70
 
71
 
72
+ // Initialize plugin.
73
  add_action( 'plugins_loaded', 'ConnectPolylangElementor\\setup', 20 );
74
  add_action( 'init', 'ConnectPolylangElementor\\load_textdomain' );
75
 
76
+ // Fixes CROSS Domain issues (add before Elementor & Polylang start).
77
+ add_filter( 'plugins_url', 'ConnectPolylangElementor\\fix_cross_domain_assets' );
78
+ add_filter( 'pll_context', 'ConnectPolylangElementor\\fix_elementor_editor_context' );
79
+
80
 
81
  /**
82
  * Plugin setup.
91
 
92
  if ( cpel_is_polylang_api_active() && cpel_is_elementor_active() ) {
93
 
94
+ ElementorAssets::instance();
95
  ConnectPlugins::instance();
96
  LanguageVisibility::instance();
97
  DynamicTags\Manager::instance();
120
 
121
  }
122
 
123
+ /**
124
+ * Fixes cross origin domain issues with Elementor and Polylang
125
+ *
126
+ * Must be run before loading Elementor.
127
+ *
128
+ * View https://github.com/polylang/polylang/issues/590
129
+ * View https://gist.github.com/JoryHogeveen/1a9f41406f2e1f1b542d725a1954f774
130
+ *
131
+ * @since 2.1.0
132
+ * @param string $url
133
+ * @return string
134
+ */
135
+ function fix_cross_domain_assets( $url ) {
136
+
137
+ if ( false === strpos( $url, 'elementor' ) ) {
138
+ return $url;
139
+ }
140
+
141
+ if ( defined( 'WP_CLI' ) ) {
142
+ return $url;
143
+ }
144
+
145
+ $pll_options = get_option( 'polylang' );
146
+
147
+ // Is a multidomain configuration.
148
+ if ( isset( $pll_options['force_lang'], $pll_options['domains'] ) && 3 === $pll_options['force_lang'] ) {
149
+
150
+ $srv_host = $_SERVER['HTTP_HOST'];
151
+ $url_host = parse_url( $url, PHP_URL_HOST );
152
+
153
+ if ( $url_host ) {
154
+ foreach ( $pll_options['domains'] as $domain ) {
155
+ if ( false !== strpos( $domain, $srv_host ) ) {
156
+ $url = str_replace( $url_host, $srv_host, $url );
157
+ break;
158
+ }
159
+ }
160
+ }
161
+ }
162
+
163
+ return $url;
164
+
165
+ }
166
+
167
+ /**
168
+ * Fix Elementor editor context
169
+ *
170
+ * Load PLL_Admin class for Elementor editor.
171
+ *
172
+ * @since 2.1.0
173
+ * @param string $class
174
+ * @return string
175
+ */
176
+ function fix_elementor_editor_context( $class ) {
177
+
178
+ return 'PLL_Frontend' === $class && is_admin() && isset( $_GET['action'] ) && 'elementor' === $_GET['action'] ? 'PLL_Admin' : $class;
179
+
180
+ }
181
+
includes/connect-plugins.php CHANGED
@@ -65,6 +65,14 @@ class ConnectPlugins {
65
  // Don't add "_elementor_css" meta.
66
  add_filter( 'update_post_metadata', array( $this, 'prevent_elementor_css_meta' ), 10, 3 );
67
 
 
 
 
 
 
 
 
 
68
  }
69
 
70
  // Elementor editor menu links to translations
@@ -86,7 +94,7 @@ class ConnectPlugins {
86
  * @param bool $is_settings True when displaying the list in Polylang settings
87
  * @return array The list of post type names for which Polylang manages language and translations
88
  */
89
- function add_polylang_post_types( $types, $is_settings ) {
90
 
91
  $relevant_types = apply_filters(
92
  'cpel/filter/polylang/post_types',
@@ -121,7 +129,7 @@ class ConnectPlugins {
121
  *
122
  * @param WP_Query $query
123
  */
124
- function query_all_languages( $query ) {
125
 
126
  $global_widget_meta_query = array(
127
  'key' => '_elementor_template_type',
@@ -151,7 +159,7 @@ class ConnectPlugins {
151
  * @param string $meta_key
152
  * @return mixed null or empty array
153
  */
154
- function elementor_conditions_empty_on_translations( $null, $post_id, $meta_key ) {
155
 
156
  return '_elementor_conditions' === $meta_key && cpel_is_translation( $post_id ) ? array( array() ) : $null;
157
 
@@ -165,7 +173,7 @@ class ConnectPlugins {
165
  * @param array $value array of theme builder conditions
166
  * @return array filtered array
167
  */
168
- function theme_builder_conditions_remove_empty( $value ) {
169
 
170
  foreach ( $value as $location => $items ) {
171
  $value[ $location ] = array_filter( $items );
@@ -187,7 +195,7 @@ class ConnectPlugins {
187
  * @param int $post_id ID of the current post
188
  * @return string Based translation, the translation ID, or the original Post ID
189
  */
190
- function template_id_translation( $post_id ) {
191
 
192
  $post_id = pll_get_post( $post_id ) ?: $post_id;
193
  $this->template_id = $post_id; // Save for check sub_id
@@ -211,7 +219,7 @@ class ConnectPlugins {
211
  * @param array $parsed_condition condition parts
212
  * @return int original sub ID or translated ID
213
  */
214
- function condition_sub_id_translation( $sub_id, $parsed_condition ) {
215
 
216
  if ( $sub_id && cpel_is_translation( $this->template_id ) ) {
217
 
@@ -243,7 +251,7 @@ class ConnectPlugins {
243
  * @param mixed $taxonomy
244
  * @return void
245
  */
246
- function update_conditions_on_term_change( $post_id, $terms, $tt_ids, $taxonomy ) {
247
 
248
  if ( 'post_translations' === $taxonomy && 'elementor_library' === get_post_type( $post_id ) ) {
249
 
@@ -265,7 +273,7 @@ class ConnectPlugins {
265
  * @param int $post_id
266
  * @return void
267
  */
268
- function hide_language_column_pre( $column, $post_id ) {
269
 
270
  if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
271
  echo '<span aria-hidden="true">—</span><div class="hidden" aria-hidden="true">';
@@ -284,7 +292,7 @@ class ConnectPlugins {
284
  * @param int $post_id
285
  * @return void
286
  */
287
- function hide_language_column_pos( $column, $post_id ) {
288
 
289
  if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
290
  echo '</div>';
@@ -303,7 +311,7 @@ class ConnectPlugins {
303
  * @param int $post_id
304
  * @return void
305
  */
306
- function instances_column_pre( $column, $post_id ) {
307
 
308
  if ( 'instances' === $column && cpel_is_translation( $post_id ) ) {
309
 
@@ -325,7 +333,7 @@ class ConnectPlugins {
325
  * @param int $post_id
326
  * @return void
327
  */
328
- function instances_column_pos( $column, $post_id ) {
329
 
330
  if ( 'instances' === $column && cpel_is_translation( $post_id ) ) {
331
  echo '</div>';
@@ -365,7 +373,7 @@ class ConnectPlugins {
365
  * @param array $white_list
366
  * @return array
367
  */
368
- function elementor_home_url_white_list( $white_list ) {
369
 
370
  $white_list[] = array( 'file' => 'site-url.php' );
371
 
@@ -382,7 +390,7 @@ class ConnectPlugins {
382
  * @param string $path
383
  * @return string
384
  */
385
- function home_url_language_dir_slash( $url, $path ) {
386
 
387
  return empty( $path ) && ! is_admin() && $url !== get_option( 'home' )
388
  && function_exists( 'PLL' ) && 1 === PLL()->options['force_lang'] ? trailingslashit( $url ) : $url;
@@ -400,7 +408,7 @@ class ConnectPlugins {
400
  * @param string $path
401
  * @return string
402
  */
403
- function search_form_home_url_filter( $url, $path ) {
404
 
405
  return function_exists( 'PLL' ) ? PLL()->curlang->search_url : $url;
406
 
@@ -414,7 +422,7 @@ class ConnectPlugins {
414
  * @param Element_Base $element
415
  * @return void
416
  */
417
- function add_search_form_home_url_filter( $element ) {
418
 
419
  if ( 'search-form' === $element->get_name() ) {
420
  add_filter( 'home_url', array( $this, 'search_form_home_url_filter' ), 10, 2 );
@@ -447,7 +455,7 @@ class ConnectPlugins {
447
  *
448
  * @return void
449
  */
450
- function elementor_editor_script() {
451
 
452
  global $typenow, $post;
453
 
@@ -464,7 +472,7 @@ class ConnectPlugins {
464
  if ( isset( $translations[ $language->slug ] ) ) {
465
 
466
  $translation_id = $translations[ $language->slug ];
467
- $link = get_edit_post_link( $translation_id, 'edit' );
468
 
469
  if ( get_post_meta( $translation_id, '_elementor_edit_mode', true ) ) {
470
  $link = add_query_arg( 'action', 'elementor', $link );
@@ -528,7 +536,7 @@ class ConnectPlugins {
528
  * @param array $data
529
  * @return array
530
  */
531
- function elementor_site_editor_template( $data ) {
532
 
533
  $post_id = $data['id'];
534
 
@@ -558,4 +566,55 @@ class ConnectPlugins {
558
 
559
  }
560
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
561
  }
65
  // Don't add "_elementor_css" meta.
66
  add_filter( 'update_post_metadata', array( $this, 'prevent_elementor_css_meta' ), 10, 3 );
67
 
68
+ // Edit links for each language domain.
69
+ if ( ! empty( PLL()->options['domains'] ) && 3 === PLL()->options['force_lang'] ) {
70
+
71
+ add_filter( 'post_row_actions', array( $this, 'fix_edit_link' ), 12, 2 );
72
+ add_filter( 'page_row_actions', array( $this, 'fix_edit_link' ), 12, 2 );
73
+
74
+ add_filter( 'elementor/document/urls/edit', array( $this, 'fix_elementor_edit_link' ), 10, 2 );
75
+ }
76
  }
77
 
78
  // Elementor editor menu links to translations
94
  * @param bool $is_settings True when displaying the list in Polylang settings
95
  * @return array The list of post type names for which Polylang manages language and translations
96
  */
97
+ public function add_polylang_post_types( $types, $is_settings ) {
98
 
99
  $relevant_types = apply_filters(
100
  'cpel/filter/polylang/post_types',
129
  *
130
  * @param WP_Query $query
131
  */
132
+ public function query_all_languages( $query ) {
133
 
134
  $global_widget_meta_query = array(
135
  'key' => '_elementor_template_type',
159
  * @param string $meta_key
160
  * @return mixed null or empty array
161
  */
162
+ public function elementor_conditions_empty_on_translations( $null, $post_id, $meta_key ) {
163
 
164
  return '_elementor_conditions' === $meta_key && cpel_is_translation( $post_id ) ? array( array() ) : $null;
165
 
173
  * @param array $value array of theme builder conditions
174
  * @return array filtered array
175
  */
176
+ public function theme_builder_conditions_remove_empty( $value ) {
177
 
178
  foreach ( $value as $location => $items ) {
179
  $value[ $location ] = array_filter( $items );
195
  * @param int $post_id ID of the current post
196
  * @return string Based translation, the translation ID, or the original Post ID
197
  */
198
+ public function template_id_translation( $post_id ) {
199
 
200
  $post_id = pll_get_post( $post_id ) ?: $post_id;
201
  $this->template_id = $post_id; // Save for check sub_id
219
  * @param array $parsed_condition condition parts
220
  * @return int original sub ID or translated ID
221
  */
222
+ public function condition_sub_id_translation( $sub_id, $parsed_condition ) {
223
 
224
  if ( $sub_id && cpel_is_translation( $this->template_id ) ) {
225
 
251
  * @param mixed $taxonomy
252
  * @return void
253
  */
254
+ public function update_conditions_on_term_change( $post_id, $terms, $tt_ids, $taxonomy ) {
255
 
256
  if ( 'post_translations' === $taxonomy && 'elementor_library' === get_post_type( $post_id ) ) {
257
 
273
  * @param int $post_id
274
  * @return void
275
  */
276
+ public function hide_language_column_pre( $column, $post_id ) {
277
 
278
  if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
279
  echo '<span aria-hidden="true">—</span><div class="hidden" aria-hidden="true">';
292
  * @param int $post_id
293
  * @return void
294
  */
295
+ public function hide_language_column_pos( $column, $post_id ) {
296
 
297
  if ( false !== strpos( $column, 'language_' ) && 'widget' === get_post_meta( $post_id, '_elementor_template_type', true ) ) {
298
  echo '</div>';
311
  * @param int $post_id
312
  * @return void
313
  */
314
+ public function instances_column_pre( $column, $post_id ) {
315
 
316
  if ( 'instances' === $column && cpel_is_translation( $post_id ) ) {
317
 
333
  * @param int $post_id
334
  * @return void
335
  */
336
+ public function instances_column_pos( $column, $post_id ) {
337
 
338
  if ( 'instances' === $column && cpel_is_translation( $post_id ) ) {
339
  echo '</div>';
373
  * @param array $white_list
374
  * @return array
375
  */
376
+ public function elementor_home_url_white_list( $white_list ) {
377
 
378
  $white_list[] = array( 'file' => 'site-url.php' );
379
 
390
  * @param string $path
391
  * @return string
392
  */
393
+ public function home_url_language_dir_slash( $url, $path ) {
394
 
395
  return empty( $path ) && ! is_admin() && $url !== get_option( 'home' )
396
  && function_exists( 'PLL' ) && 1 === PLL()->options['force_lang'] ? trailingslashit( $url ) : $url;
408
  * @param string $path
409
  * @return string
410
  */
411
+ public function search_form_home_url_filter( $url, $path ) {
412
 
413
  return function_exists( 'PLL' ) ? PLL()->curlang->search_url : $url;
414
 
422
  * @param Element_Base $element
423
  * @return void
424
  */
425
+ public function add_search_form_home_url_filter( $element ) {
426
 
427
  if ( 'search-form' === $element->get_name() ) {
428
  add_filter( 'home_url', array( $this, 'search_form_home_url_filter' ), 10, 2 );
455
  *
456
  * @return void
457
  */
458
+ public function elementor_editor_script() {
459
 
460
  global $typenow, $post;
461
 
472
  if ( isset( $translations[ $language->slug ] ) ) {
473
 
474
  $translation_id = $translations[ $language->slug ];
475
+ $link = $this->fix_url_domain( get_edit_post_link( $translation_id, 'edit' ), $translation_id );
476
 
477
  if ( get_post_meta( $translation_id, '_elementor_edit_mode', true ) ) {
478
  $link = add_query_arg( 'action', 'elementor', $link );
536
  * @param array $data
537
  * @return array
538
  */
539
+ public function elementor_site_editor_template( $data ) {
540
 
541
  $post_id = $data['id'];
542
 
566
 
567
  }
568
 
569
+ /**
570
+ * Fix url domain
571
+ *
572
+ * @param mixed $url
573
+ * @param mixed $post_id
574
+ * @return void
575
+ */
576
+ private function fix_url_domain( $url, $post_id ) {
577
+
578
+ $current_host = parse_url( pll_current_language( 'home_url' ) ?: trailingslashit( "//{$_SERVER['HTTP_HOST']}" ), PHP_URL_HOST );
579
+ $post_host = parse_url( pll_get_post_language( $post_id, 'home_url' ), PHP_URL_HOST );
580
+
581
+ if ( $current_host !== $post_host ) {
582
+ $url = str_replace( $current_host, $post_host, $url );
583
+ }
584
+
585
+ return $url;
586
+
587
+ }
588
+
589
+ /**
590
+ * Fix domain for Elementor edit links in posts table
591
+ *
592
+ * @param array $actions
593
+ * @param WP_Post $post
594
+ * @return array
595
+ */
596
+ public function fix_edit_link( $actions, $post ) {
597
+
598
+ if ( ! empty( $actions['edit_with_elementor'] ) ) {
599
+ // $actions['edit'] = $this->fix_url_domain( $actions['edit'], $post->ID );
600
+ $actions['edit_with_elementor'] = $this->fix_url_domain( $actions['edit_with_elementor'], $post->ID );
601
+ }
602
+
603
+ return $actions;
604
+
605
+ }
606
+
607
+ /**
608
+ * Fix domain for Elementor edit links in Theme Builder
609
+ *
610
+ * @param string $url
611
+ * @param Elementor\Core\Base\Document $document
612
+ * @return string
613
+ */
614
+ public function fix_elementor_edit_link( $url, $document ) {
615
+
616
+ return $this->fix_url_domain( $url, $document->get_main_id() );
617
+
618
+ }
619
+
620
  }
includes/elementor-assets.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace ConnectPolylangElementor;
3
+
4
+ defined( 'ABSPATH' ) || exit;
5
+
6
+ /**
7
+ * Fixes cross origin domain issues with Elementor and Polylang
8
+ *
9
+ * Based on code from JoryHogeveen: https://gist.github.com/JoryHogeveen/1a9f41406f2e1f1b542d725a1954f774
10
+ */
11
+ class ElementorAssets {
12
+
13
+ use \ConnectPolylangElementor\Util\Singleton;
14
+
15
+ protected $current_domain = '';
16
+ protected $default_domain = '';
17
+ protected $current_language = '';
18
+ protected $default_language = '';
19
+ protected $all_domains = array();
20
+
21
+ protected function __construct() {
22
+
23
+ add_action( 'init', array( $this, 'init' ) );
24
+ add_action( 'admin_init', array( $this, 'editor_domain_redirect' ) );
25
+
26
+ }
27
+
28
+ /**
29
+ * Initialize
30
+ *
31
+ * @since 2.1.0
32
+ * @return void
33
+ */
34
+ public function init() {
35
+
36
+ // Prepare domains info.
37
+ $return = OBJECT;
38
+ $current_language = pll_current_language( $return );
39
+ $default_language = pll_default_language( $return );
40
+
41
+ if ( ! $current_language || ! $default_language ) {
42
+ return;
43
+ }
44
+
45
+ $is_preview = isset( $_GET['elementor_preview'] );
46
+ $is_editor = ( isset( $_GET['action'] ) && 'elementor' === $_GET['action'] );
47
+
48
+ if ( ! $is_editor && ! $is_preview ) {
49
+ return;
50
+ }
51
+
52
+ $languages = pll_the_languages( array( 'raw' => true ) );
53
+
54
+ foreach ( $languages as $language ) {
55
+ $this->all_domains[] = $language['url'];
56
+ if ( false !== stripos( $language['url'], $_SERVER['SERVER_NAME'] ) ) {
57
+ $current_language = PLL()->model->get_language( $language['slug'] );
58
+ break;
59
+ }
60
+ }
61
+
62
+ $this->current_domain = $current_language->home_url;
63
+ $this->default_domain = $default_language->home_url;
64
+ $this->current_language = $current_language->slug;
65
+ $this->default_language = $default_language->slug;
66
+
67
+ // Add filters.
68
+ add_filter( 'script_loader_src', array( $this, 'translate_url' ) );
69
+ add_filter( 'style_loader_src', array( $this, 'translate_url' ) );
70
+
71
+ add_filter( 'allowed_http_origins', array( $this, 'add_allowed_origins' ) );
72
+
73
+ add_filter( 'admin_url', array( $this, 'replace_ajax_url' ), 10, 3 );
74
+ add_filter( 'wp_get_attachment_image_attributes', array( $this, 'replace_src' ), 10, 2 );
75
+
76
+ add_filter( 'elementor/editor/localize_settings', array( $this, 'translate_url_recursive' ) );
77
+
78
+ }
79
+
80
+ /**
81
+ * Translate URL domain
82
+ *
83
+ * @since 2.1.0
84
+ * @param string $url
85
+ * @return string
86
+ */
87
+ public function translate_url( $url ) {
88
+
89
+ return str_replace( $this->default_domain, $this->current_domain, $url );
90
+
91
+ }
92
+
93
+ /**
94
+ * Translate URL domain recursive
95
+ *
96
+ * @since 2.1.0
97
+ * @param mixed $data
98
+ * @return mixed
99
+ */
100
+ public function translate_url_recursive( $data ) {
101
+
102
+ if ( is_string( $data ) ) {
103
+ $data = $this->translate_url( $data );
104
+ } elseif ( is_array( $data ) ) {
105
+ $data = array_map( array( $this, 'translate_url_recursive' ), $data );
106
+ }
107
+
108
+ return $data;
109
+
110
+ }
111
+
112
+ /**
113
+ * Add all domains to allowed origins
114
+ *
115
+ * @since 2.1.0
116
+ * @param array $origins
117
+ * @return array
118
+ */
119
+ public function add_allowed_origins( $origins ) {
120
+
121
+ $origins[] = $this->current_domain;
122
+ $origins = array_merge( $origins, $this->all_domains );
123
+
124
+ return $origins;
125
+
126
+ }
127
+
128
+ /**
129
+ * Replace domain for admin-ajax.php
130
+ *
131
+ * @since 2.1.0
132
+ * @param string $url
133
+ * @param string $path
134
+ * @param int $blog_id
135
+ * @return string
136
+ */
137
+ public function replace_ajax_url( $url, $path, $blog_id ) {
138
+
139
+ return 'admin-ajax.php' === $path ? $this->translate_url( $url ) : $url;
140
+
141
+ }
142
+
143
+ /**
144
+ * Replace domain for image src
145
+ *
146
+ * @since 2.1.0
147
+ * @param mixed $attr
148
+ * @param mixed $attachment
149
+ * @return void
150
+ */
151
+ public function replace_src( $attr, $attachment ) {
152
+
153
+ $attr['src'] = $this->translate_url( $attr['src'] );
154
+ $attr['srcset'] = $this->translate_url( $attr['srcset'] );
155
+
156
+ return $attr;
157
+
158
+ }
159
+
160
+ /**
161
+ * Redirect Elementor editor with post domain
162
+ *
163
+ * @since 2.1.0
164
+ * @return void
165
+ */
166
+ public function editor_domain_redirect() {
167
+
168
+ // Exist if not is Elementor Editor.
169
+ if ( ! isset( $_GET['action'] ) || 'elementor' !== $_GET['action'] ) {
170
+ return;
171
+ }
172
+
173
+ $current_url = add_query_arg( $_SERVER['QUERY_STRING'], '', admin_url( 'post.php' ) );
174
+ $server_host = parse_url( trailingslashit( "//{$_SERVER['HTTP_HOST']}" ), PHP_URL_HOST );
175
+ $post_host = parse_url( \pll_get_post_language( intval( $_GET['post'] ), 'home_url' ), PHP_URL_HOST );
176
+
177
+ if ( $server_host !== $post_host ) {
178
+ \wp_redirect( \str_replace( $server_host, $post_host, $current_url ) );
179
+ exit;
180
+ }
181
+
182
+ }
183
+ }
184
+
includes/widgets/polylang-language-switcher.php CHANGED
@@ -702,6 +702,13 @@ class PolylangLanguageSwitcher extends Widget_Base {
702
 
703
  $lang_links = array();
704
 
 
 
 
 
 
 
 
705
  foreach ( $languages as $lang_code => $language ) {
706
 
707
  // Hide the current language.
@@ -733,7 +740,7 @@ class PolylangLanguageSwitcher extends Widget_Base {
733
  // If data uri encoded flags are preferred.
734
  if ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) {
735
  $file_contents = file_get_contents( CPEL_DIR . $flag_svg['path'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
736
- $flag_svg['src'] = 'data:image/svg+xml;utf8,' . str_replace( array( '#', '"' ), array( '%23', "'" ), $file_contents );
737
  } else {
738
  $flag_svg['src'] = $flag_svg['url'];
739
  }
702
 
703
  $lang_links = array();
704
 
705
+ $svg_replaces = array(
706
+ '"' => "'",
707
+ '#' => '%23',
708
+ '<' => '%3C',
709
+ '>' => '%3E',
710
+ );
711
+
712
  foreach ( $languages as $lang_code => $language ) {
713
 
714
  // Hide the current language.
740
  // If data uri encoded flags are preferred.
741
  if ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) {
742
  $file_contents = file_get_contents( CPEL_DIR . $flag_svg['path'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
743
+ $flag_svg['src'] = 'data:image/svg+xml;utf8,' . str_replace( array_keys( $svg_replaces ), $svg_replaces, $file_contents );
744
  } else {
745
  $flag_svg['src'] = $flag_svg['url'];
746
  }