PluginProbe
Polylang / 1.1
Polylang v1.1
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 / include / wpml-compat.php

wpml-compat.php in Polylang 1.1, at include/wpml-compat.php

442 lines 13.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 * compatibility with WPML API. See http://wpml.org/documentation/support/wpml-coding-api/
4 */
5
6 /*
7 * defines two WPML constants once the language has been defined
8 */
9 function pll_define_wpml_constants() {
10 if(!defined('ICL_LANGUAGE_CODE'))
11 define('ICL_LANGUAGE_CODE', pll_current_language());
12
13 if(!defined('ICL_LANGUAGE_NAME'))
14 define('ICL_LANGUAGE_NAME', pll_current_language('name'));
15 }
16
17 add_action('pll_language_defined', 'pll_define_wpml_constants');
18
19 /*
20 * link to the home page in the active language
21 */
22 if (!function_exists('icl_get_home_url')) {
23 function icl_get_home_url() {
24 return pll_home_url();
25 }
26 }
27
28 /*
29 * used for building custom language selectors
30 * available only on frontend
31 */
32 if (!function_exists('icl_get_languages')) {
33 function icl_get_languages($args = '') {
34 global $polylang;
35 if (!(class_exists('Polylang_Core') && $polylang instanceof Polylang_Core))
36 return array();
37
38 $args = extract(wp_parse_args($args));
39 $orderby = (isset($orderby) && $orderby == 'code') ? 'slug' : (isset($orderby) && $orderby == 'name' ? 'name' : 'id');
40 $order = (!empty($order) && $order == 'desc') ? 'DESC' : 'ASC';
41
42 $arr = array();
43
44 foreach ($polylang->get_languages_list(array('hide_empty' => true, 'orderby' => $orderby, 'order' => $order)) as $lang) {
45 $url = $polylang->get_translation_url($lang);
46
47 if (!$url && !empty($skip_missing))
48 continue;
49
50 $arr[] = array(
51 'id' => $lang->term_id,
52 'active' => isset($polylang->curlang->slug) && $polylang->curlang->slug == $lang->slug ? 1 : 0,
53 'native_name' => $lang->name,
54 'missing' => $url ? 0 : 1,
55 'translated_name' => '', // does not exist in Polylang
56 'language_code' => $lang->slug,
57 'country_flag_url' => $polylang->get_flag($lang, true),
58 'url' => $url ? $url :
59 (empty($link_empty_to) ? $polylang->get_home_url($lang) :
60 str_replace('{$lang}', $lang->slug, $link_empty_to))
61 );
62 }
63 return $arr;
64 }
65 }
66
67 /*
68 * used for creating language dependent links in themes
69 */
70 if (!function_exists('icl_link_to_element')) {
71 function icl_link_to_element($id, $type = 'post', $text = '', $args = array(), $anchor = '') {
72 global $polylang;
73
74 if ($type == 'tag')
75 $type = 'post_tag';
76
77 if (isset($polylang) && ($lang = pll_current_language()) && $tr_id = $polylang->get_translation($type, $id, $lang))
78 $id = $tr_id;
79
80 if (post_type_exists($type)) {
81 $link = get_permalink($id);
82 if (empty($text))
83 $text = get_the_title($id);
84 }
85 elseif (taxonomy_exists($type)) {
86 $link = get_term_link($id, $type);
87 if (empty($text) && ($term = get_term($id, $type)) && !empty($term) && !is_wp_error($term))
88 $text = $term->name;
89 }
90
91 if (empty($link) || is_wp_error($link))
92 return '';
93
94 if (!empty($args))
95 $link .= (false === strpos($link, '?') ? '?' : '&' ) . http_build_query($args);
96
97 if (!empty($anchor))
98 $link .= '#' . $anchor;
99
100 return sprintf('<a href="%s">%s</a>', esc_url($link), esc_html($text));
101 }
102 }
103
104 /*
105 * used for calculating the IDs of objects (usually categories) in the current language
106 */
107 if (!function_exists('icl_object_id')) {
108 function icl_object_id($id, $type, $return_original_if_missing, $lang = false) {
109 global $polylang;
110 return isset($polylang) && ($lang = $lang ? $lang : pll_current_language()) && ($tr_id = $polylang->get_translation($type, $id, $lang)) ? $tr_id :
111 ($return_original_if_missing ? $id : null);
112 }
113 }
114
115 /*
116 * registers a string for translation in the "strings translation" panel
117 * the parameter $context is not used by Polylang
118 */
119 if (!function_exists('icl_register_string')) {
120 function icl_register_string($context, $name, $string) {
121 $GLOBALS['polylang_wpml_compat']->register_string($context, $name, $string);
122 }
123 }
124
125 /*
126 * removes a string from the "strings translation" panel
127 * the parameter $context is not used by Polylang
128 */
129 if (!function_exists('icl_unregister_string')) {
130 function icl_unregister_string($context, $name) {
131 $GLOBALS['polylang_wpml_compat']->unregister_string($context, $name);
132 }
133 }
134
135 /*
136 * gets the translated value of a string (previously registered with icl_register_string or pll_register_string)
137 * the parameters $context and $name are not used by Polylang
138 */
139 if (!function_exists('icl_t')) {
140 function icl_t($context, $name, $string) {
141 return pll__($string);
142 }
143 }
144
145 /*
146 * undocumented function used by NextGen Gallery
147 * seems to be used to both register and translate a string
148 * the parameters $context and $bool are not used by Polylang
149 */
150 if (!function_exists('icl_translate')) {
151 function icl_translate($context, $name, $string, $bool) {
152 $GLOBALS['polylang_wpml_compat']->register_string($context, $name, $string);
153 return pll__($string);
154 }
155 }
156
157 /*
158 * registers strings in a persistant way as done by WPML
159 */
160 class Polylang_WPML_Compat {
161 private $strings; // used for cache
162
163 function __construct() {
164 add_action('pll_get_strings', array(&$this, 'get_strings'));
165 }
166
167 // unlike pll_register_string, icl_register_string stores the string in database
168 // so we need to do the same as some plugins or themes may expect this
169 // we use a serialized option to do this
170 function register_string($context, $name, $string) {
171 if (empty($this->strings))
172 $this->strings = get_option('polylang_wpml_strings', array());
173
174 // registers the string if it does not exist yet
175 $to_register = array('context' => $context, 'name'=> $name, 'string' => $string, 'multiline' => false, 'icl' => true);
176 if (!in_array($to_register, $this->strings) && $to_register['string']) {
177 $this->strings[] = $to_register;
178 update_option('polylang_wpml_strings', $this->strings);
179 }
180 }
181
182 // removes a string from the registered strings list
183 function unregister_string($context, $name) {
184 if (empty($this->strings))
185 $this->strings = get_option('polylang_wpml_strings', array());
186
187 foreach ($this->strings as $key=>$string) {
188 if ($string['context'] == $context && $string['name'] == $name) {
189 unset($this->strings[$key]);
190 update_option('polylang_wpml_strings', $this->strings);
191 }
192 }
193 }
194
195 // adds strings registered by icl_register_string to those registered by pll_register_string
196 function get_strings($strings) {
197 if (empty($this->strings))
198 $this->strings = get_option('polylang_wpml_strings');
199
200 return empty($this->strings) ? $strings : array_merge($strings, $this->strings);
201 }
202 }
203
204 global $polylang_wpml_compat;
205 $polylang_wpml_compat = new Polylang_WPML_Compat();
206
207 /*
208 * reads and interprets the file wpml-config.xml
209 * see http://wpml.org/documentation/support/language-configuration-files/
210 * the language switcher configuration is not interpreted
211 * the xml parser has been adapted from http://php.net/manual/en/function.xml-parse-into-struct.php#84261
212 * many thanks to wickedfather at hotmail dot com
213 */
214 class Polylang_WPML_Config {
215 private $values;
216 private $index;
217 private $wpml_config;
218 private $strings;
219
220 function __construct() {
221 add_action('plugins_loaded', array(&$this, 'init'), 1);
222 }
223
224 function xml_parse($xml, $context) {
225 $parser = xml_parser_create();
226 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
227 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
228 xml_parse_into_struct($parser, $xml, $this->values);
229 xml_parser_free($parser);
230
231 $this->index = 0;
232 $arr = $this->xml_parse_recursive();
233 $arr = $arr['wpml-config'];
234
235 $keys = array(
236 array('custom-fields', 'custom-field'),
237 array('custom-types','custom-type'),
238 array('taxonomies','taxonomy'),
239 array('admin-texts','key')
240 );
241
242 foreach ($keys as $k) {
243 if (isset($arr[$k[0]])) {
244 if (!isset($arr[$k[0]][$k[1]][0])) {
245 $elem = $arr[$k[0]][$k[1]];
246 unset($arr[$k[0]][$k[1]]);
247 $arr[$k[0]][$k[1]][0] = $elem;
248 }
249
250 $this->wpml_config[$k[0]][$context] = $arr[$k[0]];
251 }
252 }
253 }
254
255 function xml_parse_recursive() {
256 $found = array();
257 $tagCount = array();
258
259 while (isset($this->values[$this->index])) {
260 extract($this->values[$this->index]);
261 $this->index++;
262
263 if ($type == 'close')
264 return $found;
265
266 if (isset($tagCount[$tag])) {
267 if ($tagCount[$tag] == 1)
268 $found[$tag] = array($found[$tag]);
269
270 $tagRef = &$found[$tag][$tagCount[$tag]];
271 $tagCount[$tag]++;
272 }
273 else {
274 $tagCount[$tag] = 1;
275 $tagRef = &$found[$tag];
276 }
277
278 if ($type == 'open') {
279 $tagRef = $this->xml_parse_recursive();
280 if (isset($attributes))
281 $tagRef['attributes'] = $attributes;
282 }
283
284 if ($type == 'complete') {
285 if (isset($attributes)) {
286 $tagRef['attributes'] = $attributes;
287 $tagRef = &$tagRef['value'];
288 }
289 if (isset($value))
290 $tagRef = $value;
291 }
292 }
293
294 return $found;
295 }
296
297 function init() {
298 $this->wpml_config = array();
299
300 // child theme
301 if (($template = get_template_directory()) != ($stylesheet = get_stylesheet_directory()) && file_exists($file = $stylesheet.'/wpml-config.xml'))
302 $this->xml_parse(file_get_contents($file), get_stylesheet()); // FIXME fopen + fread + fclose quicker ?
303
304 // theme
305 if (file_exists($file = $template.'/wpml-config.xml'))
306 $this->xml_parse(file_get_contents($file), get_template());
307
308 // plugins
309 foreach (get_option('active_plugins') as $plugin) {
310 if (file_exists($file = dirname(POLYLANG_DIR).'/'.dirname($plugin).'/wpml-config.xml'))
311 $this->xml_parse(file_get_contents($file), dirname($plugin));
312 }
313
314 // custom
315 if (file_exists($file = PLL_LOCAL_DIR.'/wpml-config.xml'))
316 $this->xml_parse(file_get_contents($file), 'polylang');
317
318 if (isset($this->wpml_config['custom-fields']))
319 add_filter('pll_copy_post_metas', array(&$this, 'copy_post_metas'), 10, 2);
320
321 if (isset($this->wpml_config['custom-types']))
322 add_filter('pll_get_post_types', array(&$this, 'translate_types'), 10, 2);
323
324 if (isset($this->wpml_config['taxonomies']))
325 add_filter('pll_get_taxonomies', array(&$this, 'translate_taxonomies'), 10, 2);
326
327 if (!isset($this->wpml_config['admin-texts']))
328 return;
329
330 // get a cleaner array for easy manipulation
331 foreach ($this->wpml_config['admin-texts'] as $context => $arr)
332 foreach ($arr as $keys)
333 $this->strings[$context] = $this->admin_texts_recursive($keys);
334
335 foreach ($this->strings as $context=>$options) {
336 foreach ($options as $option_name=>$value) {
337 if ($GLOBALS['polylang']->is_admin) { // backend
338 $option = get_option($option_name);
339 if (is_string($option) && $value == 1)
340 pll_register_string($option_name, $option, $context);
341 elseif (is_array($option) && is_array($value))
342 $this->register_string_recursive($context, $value, $option); // for a serialized option
343 }
344 else
345 add_filter('option_'.$option_name, array(&$this, 'translate_strings'));
346 }
347 }
348 }
349
350 // arranges strings in a cleaner way
351 function admin_texts_recursive($keys) {
352 if (!isset($keys[0])) {
353 $elem = $keys;
354 unset($keys);
355 $keys[0] = $elem;
356 }
357 foreach ($keys as $key)
358 $strings[$key['attributes']['name']] = isset($key['key']) ? $this->admin_texts_recursive($key['key']) : 1;
359
360 return $strings;
361 }
362
363 // recursively registers strings for a serialized option
364 function register_string_recursive($context, $strings, $options) {
365 foreach ($options as $name=>$value) {
366 if (isset($strings[$name])) {
367 if (is_string($value) && $strings[$name] == 1)
368 pll_register_string($name, $value, $context);
369 elseif (is_array($value) && is_array($strings[$name]))
370 $this->register_string_recursive($context, $strings[$name], $value);
371 }
372 }
373 }
374
375 function copy_post_metas($metas, $sync) {
376 foreach ($this->wpml_config['custom-fields'] as $context) {
377 foreach ($context['custom-field'] as $cf) {
378 if (!$sync && in_array($cf['attributes']['action'], array('copy', 'translate')))
379 $metas[] = $cf['value'];
380 elseif ($sync && $cf['attributes']['action'] != 'copy')
381 $metas = array_diff($metas, array($cf['value'])); // do not synchronize
382 }
383 }
384 return $metas;
385 }
386
387 // language and translation management for custom post types
388 function translate_types($types, $hide) {
389 foreach ($this->wpml_config['custom-types'] as $context) {
390 foreach ($context['custom-type'] as $pt) {
391 if ($pt['attributes']['translate'] == 1 && !$hide)
392 $types[$pt['value']] = $pt['value'];
393 elseif ($hide)
394 unset ($types[$pt['value']]); // the author decided what to do with the post type so don't allow the user to change this
395 }
396 }
397 return $types;
398 }
399
400 // language and translation management for custom taxonomies
401 function translate_taxonomies($taxonomies, $hide) {
402 foreach ($this->wpml_config['taxonomies'] as $context) {
403 foreach ($context['taxonomy'] as $tax) {
404 if ($tax['attributes']['translate'] == 1 && !$hide)
405 $taxonomies[$tax['value']] = $tax['value'];
406 elseif ($hide)
407 unset ($types[$tax['value']]); // the author decided what to do with the taxonomy so don't allow the user to change this
408 }
409 }
410
411 return $taxonomies;
412 }
413
414 // translates the strings for an option
415 function translate_strings($value) {
416 if (is_array($value)) {
417 $option = substr(current_filter(), 7);
418 foreach ($this->strings as $context=>$options) {
419 if (array_key_exists($option, $options))
420 return $this->translate_strings_recursive($options[$option], $value); // for a serialized option
421 }
422 }
423 return pll__($value);
424 }
425
426 // recursively translates strings for a serialized option
427 function translate_strings_recursive($strings, $values) {
428 foreach ($values as $name=>$value) {
429 if (isset($strings[$name])) {
430 if (is_string($value) && $strings[$name] == 1)
431 $values[$name] = pll__($value);
432 elseif (is_array($value) && is_array($strings[$name]))
433 $value = $this->translate_strings_recursive($strings[$name], $value);
434 }
435 }
436 return $values;
437 }
438
439 }
440
441 new Polylang_WPML_Config();
442