PluginProbe
Polylang / 3.8.4
Polylang v3.8.4
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / src / modules / wpml / wpml-legacy-api.php

wpml-legacy-api.php in Polylang 3.8.4, at src/modules/wpml/wpml-legacy-api.php

438 lines 15.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * Compatibility with WPML legacy API
8 * Deprecated since WPML 3.2 and no more documented
9 * But a lot of 3rd party plugins / themes are still using these functions
10 */
11
12 if ( ! function_exists( 'icl_get_home_url' ) ) {
13 /**
14 * Link to the home page in the active language
15 *
16 * @since 0.9.4
17 *
18 * @return string
19 */
20 function icl_get_home_url() {
21 return pll_home_url();
22 }
23 }
24
25 if ( ! function_exists( 'icl_get_languages' ) ) {
26 /**
27 * Used for building custom language selectors
28 * available only on frontend
29 *
30 * List of parameters accepted in $args:
31 *
32 * skip_missing => whether to skip missing translation or not, 0 or 1, defaults to 0
33 * orderby => 'id', 'code', 'name', defaults to 'id'
34 * order => 'ASC' or 'DESC', defaults to 'ASC'
35 * link_empty_to => link to use when the translation is missing {$lang} is replaced by the language code
36 *
37 * List of parameters returned per language:
38 *
39 * id => the language id
40 * active => whether this is the active language or no, 0 or 1
41 * native_name => the language name
42 * missing => whether the translation is missing or not, 0 or 1
43 * translated_name => empty, does not exist in Polylang
44 * language_code => the language code ( slug )
45 * country_flag_url => the url of the flag
46 * url => the url of the translation
47 *
48 * @since 1.0
49 *
50 * @param string|array $args optional
51 * @return array array of arrays per language
52 */
53 function icl_get_languages( $args = '' ) {
54 $args = wp_parse_args( $args, array( 'skip_missing' => 0, 'orderby' => 'id', 'order' => 'ASC' ) );
55 $orderby = ( isset( $args['orderby'] ) && 'code' == $args['orderby'] ) ? 'slug' : ( isset( $args['orderby'] ) && 'name' == $args['orderby'] ? 'name' : 'id' );
56 $order = ( ! empty( $args['order'] ) && 'desc' == $args['order'] ) ? 'DESC' : 'ASC';
57
58 $arr = array();
59
60 // NB: When 'skip_missing' is false, WPML returns all languages even if there is no content
61 $languages = PLL()->model->languages
62 ->filter( $args['skip_missing'] ? 'hide_empty' : '' )
63 ->get_list();
64 $languages = wp_list_sort( $languages, $orderby, $order ); // Since WP 4.7
65
66 foreach ( $languages as $lang ) {
67 // We can find a translation only on frontend once the global $wp_query object has been instantiated
68 if ( PLL()->links instanceof PLL_Frontend_Links && ! empty( $GLOBALS['wp_query'] ) ) {
69 $url = PLL()->links->get_translation_url( $lang );
70 }
71
72 // It seems that WPML does not bother of skip_missing parameter on admin side and before the $wp_query object has been filled
73 if ( empty( $url ) && ! empty( $args['skip_missing'] ) && ! is_admin() && did_action( 'parse_query' ) ) {
74 continue;
75 }
76
77 $arr[ $lang->slug ] = array(
78 'id' => $lang->term_id,
79 'active' => isset( PLL()->curlang->slug ) && PLL()->curlang->slug == $lang->slug ? 1 : 0,
80 'native_name' => $lang->name,
81 'missing' => empty( $url ) ? 1 : 0,
82 'translated_name' => '', // Does not exist in Polylang
83 'language_code' => $lang->slug,
84 'country_flag_url' => $lang->get_display_flag_url(),
85 'url' => ! empty( $url ) ? $url :
86 ( empty( $args['link_empty_to'] ) ? $lang->get_home_url() :
87 str_replace( '{$lang}', $lang->slug, $args['link_empty_to'] ) ),
88 );
89 }
90
91 // Apply undocumented WPML filter
92 $arr = apply_filters( 'icl_ls_languages', $arr );
93
94 return $arr;
95 }
96 }
97
98 if ( ! function_exists( 'icl_link_to_element' ) ) {
99 /**
100 * Used for creating language dependent links in themes
101 *
102 * @since 1.0
103 * @since 2.0 add support for arguments 6 and 7
104 *
105 * @param int $id object id
106 * @param string $type optional, post type or taxonomy name of the object, defaults to 'post'
107 * @param string $text optional, the link text. If not specified will produce the name of the element in the current language
108 * @param array $args optional, an array of arguments to add to the link, defaults to empty
109 * @param string $anchor optional, the anchor to add to the link, defaults to empty
110 * @param bool $echo optional, whether to echo the link, defaults to true
111 * @param bool $return_original_if_missing optional, whether to return a value if the translation is missing
112 * @return string a language dependent link
113 */
114 function icl_link_to_element( $id, $type = 'post', $text = '', $args = array(), $anchor = '', $echo = true, $return_original_if_missing = true ) {
115 if ( 'tag' == $type ) {
116 $type = 'post_tag';
117 }
118
119 $pll_type = ( 'post' == $type || pll_is_translated_post_type( $type ) ) ? 'post' : ( 'term' == $type || pll_is_translated_taxonomy( $type ) ? 'term' : false );
120 if ( $pll_type && ( $lang = pll_current_language() ) && ( $tr_id = PLL()->model->$pll_type->get_translation( $id, $lang ) ) && ( 'term' === $pll_type || PLL()->model->post->current_user_can_read( $tr_id ) ) ) {
121 $id = $tr_id;
122 } elseif ( ! $return_original_if_missing ) {
123 return '';
124 }
125
126 if ( post_type_exists( $type ) ) {
127 $link = get_permalink( $id );
128 if ( empty( $text ) ) {
129 $text = get_the_title( $id );
130 }
131 } elseif ( taxonomy_exists( $type ) ) {
132 $link = get_term_link( $id, $type );
133 if ( empty( $text ) && ( $term = get_term( $id, $type ) ) && $term instanceof WP_Term ) {
134 $text = $term->name;
135 }
136 }
137
138 if ( empty( $link ) || is_wp_error( $link ) ) {
139 return '';
140 }
141
142 if ( ! empty( $args ) ) {
143 $link .= ( false === strpos( $link, '?' ) ? '?' : '&' ) . http_build_query( $args );
144 }
145
146 if ( ! empty( $anchor ) ) {
147 $link .= '#' . $anchor;
148 }
149
150 $link = sprintf( '<a href="%s">%s</a>', esc_url( $link ), esc_html( $text ) );
151
152 if ( $echo ) {
153 echo $link; // phpcs:ignore WordPress.Security.EscapeOutput
154 }
155
156 return $link;
157 }
158 }
159
160 if ( ! function_exists( 'icl_object_id' ) ) {
161 /**
162 * Returns an element’s ID in the current language or in another specified language.
163 *
164 * @since 0.9.5
165 *
166 * @param int $element_id Object id.
167 * @param string $element_type Optional, post type or taxonomy name of the object, defaults to 'post'.
168 * @param bool $return_original_if_missing Optional, true if Polylang should return the original id if the translation is missing, defaults to false.
169 * @param string|null $ulanguage_code Optional, language code, defaults to the current language.
170 * @return int|null The object id of the translation, null if the translation is missing and $return_original_if_missing set to false.
171 */
172 function icl_object_id( $element_id, $element_type = 'post', $return_original_if_missing = false, $ulanguage_code = null ) {
173 if ( empty( $element_id ) ) {
174 return null;
175 }
176
177 $element_id = (int) $element_id;
178
179 if ( 'any' === $element_type ) {
180 $element_type = get_post_type( $element_id );
181 }
182
183 if ( empty( $element_type ) ) {
184 return null;
185 }
186
187 if ( empty( $ulanguage_code ) ) {
188 $ulanguage_code = pll_current_language();
189 }
190
191 if ( empty( $ulanguage_code ) ) {
192 return $return_original_if_missing ? $element_id : null;
193 }
194
195 if ( 'nav_menu' === $element_type ) {
196 $tr_id = false;
197 $theme = get_option( 'stylesheet' );
198 if ( isset( PLL()->options['nav_menus'][ $theme ] ) ) {
199 foreach ( PLL()->options['nav_menus'][ $theme ] as $menu ) {
200 if ( array_search( $element_id, $menu ) && ! empty( $menu[ $ulanguage_code ] ) ) {
201 $tr_id = $menu[ $ulanguage_code ];
202 break;
203 }
204 }
205 }
206 } elseif ( pll_is_translated_post_type( $element_type ) ) {
207 $tr_id = PLL()->model->post->get_translation( $element_id, $ulanguage_code );
208 } elseif ( pll_is_translated_taxonomy( $element_type ) ) {
209 $tr_id = PLL()->model->term->get_translation( $element_id, $ulanguage_code );
210 } else {
211 return $element_id; // WPML doesn't honor $return_original_if_missing if the post type or taxonomy is not translated, @see {SitePress::get_object_id()}.
212 }
213
214 if ( empty( $tr_id ) ) {
215 if ( $return_original_if_missing ) {
216 return $element_id;
217 }
218
219 return null;
220 }
221
222 return (int) $tr_id;
223 }
224 }
225
226 if ( ! function_exists( 'wpml_object_id_filter' ) ) {
227 /**
228 * Undocumented alias of `icl_object_id` introduced in WPML 3.2, used by Yith WooCommerce compare
229 *
230 * @since 2.2.4
231 *
232 * @param int $id object id
233 * @param string $type optional, post type or taxonomy name of the object, defaults to 'post'
234 * @param bool $return_original_if_missing optional, true if Polylang should return the original id if the translation is missing, defaults to false
235 * @param string $lang optional, language code, defaults to current language
236 * @return int|null the object id of the translation, null if the translation is missing and $return_original_if_missing set to false
237 */
238 function wpml_object_id_filter( $id, $type = 'post', $return_original_if_missing = false, $lang = null ) {
239 return icl_object_id( $id, $type, $return_original_if_missing, $lang );
240 }
241 }
242
243 if ( ! function_exists( 'wpml_get_language_information' ) ) {
244 /**
245 * Undocumented function used by the theme Maya
246 * returns the post language
247 *
248 * @see https://wpml.org/forums/topic/canonical-urls-for-wpml-duplicated-posts/#post-52198 for the original WPML code
249 *
250 * @since 1.8
251 *
252 * @param null $empty optional, not used
253 * @param int $post_id optional, post id, defaults to current post
254 * @return array|WP_Error
255 */
256 function wpml_get_language_information( $empty = null, $post_id = null ) {
257 if ( null === $post_id ) {
258 $post_id = get_the_ID();
259 }
260 if ( empty( $post_id ) ) {
261 return new WP_Error( 'missing_id', __( 'Missing post ID', 'polylang' ) );
262 }
263
264 $post = get_post( $post_id );
265 if ( empty( $post ) ) {
266 /* translators: %d is a Post ID. */
267 return new WP_Error( 'missing_post', sprintf( __( 'No such post for ID = %d', 'polylang' ), $post_id ) );
268 }
269
270 $lang = PLL()->model->post->get_language( $post_id );
271
272 // FIXME WPML may return a WP_Error object
273 return false === $lang ? array() : array(
274 'language_code' => $lang->slug,
275 'locale' => $lang->locale,
276 'text_direction' => (bool) $lang->is_rtl,
277 'display_name' => $lang->name, // Seems to be the post language name displayed in the current language, not a feature in Polylang
278 'native_name' => $lang->name,
279 'different_language' => pll_current_language() !== $lang->slug,
280 );
281 }
282 }
283
284 if ( ! function_exists( 'icl_register_string' ) ) {
285 /**
286 * Registers a string for translation in the "strings translation" panel
287 *
288 * The 4th and 5th parameters $allow_empty_value and $source_lang are not used by Polylang.
289 *
290 * @since 0.9.3
291 *
292 * @param string $context the group in which the string is registered, defaults to 'polylang'
293 * @param string $name a unique name for the string
294 * @param string $string the string to register
295 * @return void
296 */
297 function icl_register_string( $context, $name, $string ) {
298 PLL_WPML_Compat::instance()->register_string( $context, $name, $string );
299 }
300 }
301
302 if ( ! function_exists( 'icl_unregister_string' ) ) {
303 /**
304 * Removes a string from the "strings translation" panel
305 *
306 * @since 1.0.2
307 *
308 * @param string $context the group in which the string is registered, defaults to 'polylang'
309 * @param string $name a unique name for the string
310 * @return void
311 */
312 function icl_unregister_string( $context, $name ) {
313 PLL_WPML_Compat::instance()->unregister_string( $context, $name );
314 }
315 }
316
317 if ( ! function_exists( 'icl_t' ) ) {
318 /**
319 * Gets the translated value of a string ( previously registered with icl_register_string or pll_register_string )
320 *
321 * @since 0.9.3
322 * @since 1.9.2 argument 3 is optional
323 * @since 2.0 add support for arguments 4 to 6
324 *
325 * @param string $context the group in which the string is registered
326 * @param string $name a unique name for the string
327 * @param string $string the string to translate, optional for strings registered with icl_register_string
328 * @param bool|null $has_translation optional, not supported in Polylang
329 * @param bool $bool optional, not used
330 * @param string|null $lang optional, return the translation in this language, defaults to current language
331 * @return string the translated string
332 */
333 function icl_t( $context, $name, $string = '', &$has_translation = null, $bool = false, $lang = null ) {
334 return icl_translate( $context, $name, $string, false, $has_translation, $lang );
335 }
336 }
337
338 if ( ! function_exists( 'icl_translate' ) ) {
339 /**
340 * Undocumented function used by NextGen Gallery
341 * used in PLL_Plugins_Compat for Jetpack with only 3 arguments
342 *
343 * @since 1.0.2
344 * @since 2.0 add support for arguments 5 and 6, strings are no more automatically registered
345 *
346 * @param string $context the group in which the string is registered
347 * @param string $name a unique name for the string
348 * @param string $string the string to translate, optional for strings registered with icl_register_string
349 * @param bool $bool optional, not used
350 * @param bool|null $has_translation optional, not supported in Polylang
351 * @param string|null $lang optional, return the translation in this language, defaults to current language
352 * @return string the translated string
353 */
354 function icl_translate( $context, $name, $string = '', $bool = false, &$has_translation = null, $lang = null ) {
355 // FIXME WPML can automatically registers the string based on an option
356 if ( empty( $string ) ) {
357 $string = PLL_WPML_Compat::instance()->get_string_by_context_and_name( $context, $name );
358 }
359 return empty( $lang ) ? pll__( $string ) : pll_translate_string( $string, $lang );
360 }
361 }
362
363 if ( ! function_exists( 'wpml_get_copied_fields_for_post_edit' ) ) {
364 /**
365 * Undocumented function used by Types
366 * FIXME: tested only with Types
367 * probably incomplete as Types locks the custom fields for a new post, but not when edited
368 * This is probably linked to the fact that WPML has always an original post in the default language and not Polylang :)
369 *
370 * @since 1.1.2
371 *
372 * @return array
373 */
374 function wpml_get_copied_fields_for_post_edit() {
375 if ( empty( $_GET['from_post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
376 return array();
377 }
378
379 $arr = array( 'original_post_id' => (int) $_GET['from_post'] ); // phpcs:ignore WordPress.Security.NonceVerification
380
381 // Don't know what WPML does but Polylang does copy all public meta keys by default.
382 $keys = get_post_custom_keys( $arr['original_post_id'] );
383 if ( is_array( $keys ) ) {
384 foreach ( $keys as $k => $meta_key ) {
385 if ( is_protected_meta( $meta_key ) ) {
386 unset( $keys[ $k ] );
387 }
388 }
389 }
390
391 // Apply our filter and fill the expected output ( see /types/embedded/includes/fields-post.php )
392 /** This filter is documented in src/modules/sync/admin-sync.php */
393 $arr['fields'] = array_unique( apply_filters( 'pll_copy_post_metas', empty( $keys ) ? array() : $keys, false ) );
394 return $arr;
395 }
396 }
397
398 if ( ! function_exists( 'icl_get_default_language' ) ) {
399 /**
400 * Undocumented function used by Warp 6 by Yootheme
401 *
402 * @since 1.0.5
403 *
404 * @return string|false default language code
405 */
406 function icl_get_default_language() {
407 return pll_default_language();
408 }
409 }
410
411 if ( ! function_exists( 'wpml_get_default_language' ) ) {
412 /**
413 * Undocumented function reported to be used by Table Rate Shipping for WooCommerce
414 *
415 * @see https://wordpress.org/support/topic/add-wpml-compatibility-function
416 *
417 * @since 1.8.2
418 *
419 * @return string|false default language code
420 */
421 function wpml_get_default_language() {
422 return pll_default_language();
423 }
424 }
425
426 if ( ! function_exists( 'icl_get_current_language' ) ) {
427 /**
428 * Undocumented function used by Ultimate Member
429 *
430 * @since 2.2.4
431 *
432 * @return string Current language code
433 */
434 function icl_get_current_language() {
435 return (string) pll_current_language();
436 }
437 }
438