PluginProbe
Polylang / 3.3
Polylang v3.3
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
← All changes | include/language.php +323 -133 2.73.3 View file →
@@ -1,88 +1,221 @@
1 1 <?php
2 +/**
3 + * @package Polylang
4 + */
2 5
3 6 /**
4 - * A language object is made of two terms in 'language' and 'term_language' taxonomies
5 - * manipulating only one object per language instead of two terms should make things easier
7 + * A language object is made of two terms in 'language' and 'term_language' taxonomies.
8 + * Manipulating only one object per language instead of two terms should make things easier.
6 9 *
7 - * Properties:
8 - * term_id => id of term in 'language' taxonomy
9 - * name => language name. Ex: English
10 - * slug => language code used in url. Ex: en
11 - * term_group => order of the language when displayed in a list of languages
12 - * term_taxonomy_id => term taxonomy id in 'language' taxonomy
13 - * taxonomy => 'language'
14 - * description => language locale for backward compatibility
15 - * parent => 0 / not used
16 - * count => number of posts and pages in that language
17 - * tl_term_id => id of the term in 'term_language' taxonomy
18 - * tl_term_taxonomy_id => term taxonomy id in 'term_language' taxonomy
19 - * tl_count => number of terms in that language ( not used by Polylang )
20 - * locale => WordPress language locale. Ex: en_US
21 - * is_rtl => 1 if the language is rtl
22 - * w3c => W3C locale
23 - * flag_code => code of the flag
24 - * flag_url => url of the flag
25 - * flag => html img of the flag
26 - * custom_flag_url => url of the custom flag if exists, internal use only, moves to flag_url on frontend
27 - * custom_flag => html img of the custom flag if exists, internal use only, moves to flag on frontend
28 - * home_url => home url in this language
29 - * search_url => home url to use in search forms
30 - * host => host of this language
31 - * mo_id => id of the post storing strings translations
32 - * page_on_front => id of the page on front in this language ( set from pll_languages_list filter )
33 - * page_for_posts => id of the page for posts in this language ( set from pll_languages_list filter )
34 - *
35 10 * @since 1.2
36 11 */
12 +#[AllowDynamicProperties]
37 13 class PLL_Language {
38 - public $term_id, $name, $slug, $term_group, $term_taxonomy_id, $taxonomy, $description, $parent, $count;
39 - public $tl_term_id, $tl_term_taxonomy_id, $tl_count;
40 - public $locale, $is_rtl;
41 - public $w3c, $facebook;
42 - public $flag_url, $flag;
43 - public $home_url, $search_url;
44 - public $host, $mo_id;
45 - public $page_on_front, $page_for_posts;
14 + /**
15 + * Id of the term in 'language' taxonomy.
16 + *
17 + * @var int
18 + */
19 + public $term_id;
46 20
47 21 /**
48 - * Constructor: builds a language object given its two corresponding terms in language and term_language taxonomies
22 + * Language name. Ex: English.
49 23 *
24 + * @var string
25 + */
26 + public $name;
27 +
28 + /**
29 + * Language code used in url. Ex: en.
30 + *
31 + * @var string
32 + */
33 + public $slug;
34 +
35 + /**
36 + * Order of the language when displayed in a list of languages.
37 + *
38 + * @var int
39 + */
40 + public $term_group;
41 +
42 + /**
43 + * Term taxonomy id in 'language' taxonomy.
44 + *
45 + * @var int
46 + */
47 + public $term_taxonomy_id;
48 +
49 + /**
50 + * Number of posts and pages in that language.
51 + *
52 + * @var int
53 + */
54 + public $count;
55 +
56 + /**
57 + * Id of the term in 'term_language' taxonomy.
58 + *
59 + * @var int
60 + */
61 + public $tl_term_id;
62 +
63 + /**
64 + * Term taxonomy id in 'term_language' taxonomy.
65 + *
66 + * @var int
67 + */
68 + public $tl_term_taxonomy_id;
69 +
70 + /**
71 + * Number of terms in that language.
72 + *
73 + * @var int
74 + */
75 + public $tl_count;
76 +
77 + /**
78 + * WordPress language locale. Ex: en_US.
79 + *
80 + * @var string
81 + */
82 + public $locale;
83 +
84 + /**
85 + * 1 if the language is rtl, 0 otherwise.
86 + *
87 + * @var int
88 + */
89 + public $is_rtl;
90 +
91 + /**
92 + * W3C locale.
93 + *
94 + * @var string
95 + */
96 + public $w3c;
97 +
98 + /**
99 + * Facebook locale.
100 + *
101 + * @var string|null
102 + */
103 + public $facebook;
104 +
105 + /**
106 + * Home url in this language.
107 + *
108 + * @var string|null
109 + */
110 + public $home_url;
111 +
112 + /**
113 + * Home url to use in search forms.
114 + *
115 + * @var string|null
116 + */
117 + public $search_url;
118 +
119 + /**
120 + * Host corresponding to this language.
121 + *
122 + * @var string|null
123 + */
124 + public $host;
125 +
126 + /**
127 + * Id of the post storing strings translations.
128 + *
129 + * @var int
130 + */
131 + public $mo_id;
132 +
133 + /**
134 + * Id of the page on front in this language ( set from pll_languages_list filter ).
135 + *
136 + * @var int|null
137 + */
138 + public $page_on_front;
139 +
140 + /**
141 + * Id of the page for posts in this language ( set from pll_languages_list filter ).
142 + *
143 + * @var int|null
144 + */
145 + public $page_for_posts;
146 +
147 + /**
148 + * Code of the flag.
149 + *
150 + * @var string
151 + */
152 + public $flag_code;
153 +
154 + /**
155 + * Url of the flag.
156 + *
157 + * @var string|null
158 + */
159 + public $flag_url;
160 +
161 + /**
162 + * Html markup of the flag.
163 + *
164 + * @var string|null
165 + */
166 + public $flag;
167 +
168 + /**
169 + * Url of the custom flag if it exists.
170 + *
171 + * @var string|null
172 + */
173 + public $custom_flag_url;
174 +
175 + /**
176 + * Html markup of the custom flag if it exists.
177 + *
178 + * @var string|null
179 + */
180 + public $custom_flag;
181 +
182 + /**
183 + * Constructor: builds a language object given its two corresponding terms in 'language' and 'term_language' taxonomies.
184 + *
50 185 * @since 1.2
51 186 *
52 - * @param object|array $language 'language' term or language object properties stored as an array
53 - * @param object $term_language Corresponding 'term_language' term
187 + * @param WP_Term|array $language Term in 'language' taxonomy or language object properties stored as an array.
188 + * @param WP_Term $term_language Corresponding 'term_language' term.
54 189 */
55 190 public function __construct( $language, $term_language = null ) {
56 - // Build the object from all properties stored as an array
57 191 if ( empty( $term_language ) ) {
192 + // Build the object from all properties stored as an array.
58 193 foreach ( $language as $prop => $value ) {
59 194 $this->$prop = $value;
60 195 }
61 - }
196 + } else {
197 + // Build the object from taxonomy terms.
198 + $this->term_id = (int) $language->term_id;
199 + $this->name = $language->name;
200 + $this->slug = $language->slug;
201 + $this->term_group = (int) $language->term_group;
202 + $this->term_taxonomy_id = (int) $language->term_taxonomy_id;
203 + $this->count = (int) $language->count;
62 204
63 - // Build the object from taxonomies
64 - else {
65 - foreach ( $language as $prop => $value ) {
66 - $this->$prop = in_array( $prop, array( 'term_id', 'term_taxonomy_id', 'count' ) ) ? (int) $language->$prop : $language->$prop;
67 - }
68 -
69 205 $this->tl_term_id = (int) $term_language->term_id;
70 206 $this->tl_term_taxonomy_id = (int) $term_language->term_taxonomy_id;
71 207 $this->tl_count = (int) $term_language->count;
72 208
73 - // The description field can contain any property
74 - // Backward compatibility for is_rtl
209 + // The description field can contain any property.
75 210 $description = maybe_unserialize( $language->description );
76 211 foreach ( $description as $prop => $value ) {
77 212 'rtl' == $prop ? $this->is_rtl = $value : $this->$prop = $value;
78 213 }
79 214
80 - $this->description = &$this->locale; // Backward compatibility with Polylang < 1.2
81 -
82 215 $this->mo_id = PLL_MO::get_id( $this );
83 216
84 - $languages = include PLL_SETTINGS_INC . '/languages.php';
217 + $languages = include POLYLANG_DIR . '/settings/languages.php';
85 218 $this->w3c = isset( $languages[ $this->locale ]['w3c'] ) ? $languages[ $this->locale ]['w3c'] : str_replace( '_', '-', $this->locale );
86 219 if ( isset( $languages[ $this->locale ]['facebook'] ) ) {
87 220 $this->facebook = $languages[ $this->locale ]['facebook'];
88 221 }
@@ -89,66 +222,74 @@
89 222 }
90 223 }
91 224
92 225 /**
93 - * Get the flag informations
94 - * 'url' => Flag url
95 - * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
96 - * 'width' => Optional, flag width in pixels
97 - * 'height' => Optional, flag height in pixels
226 + * Get the flag informations:
98 227 *
99 228 * @since 2.6
100 229 *
101 230 * @param string $code Flag code.
102 - * @return array Flag informations.
231 + * @return array {
232 + * Flag informations.
233 + *
234 + * @type string $url Flag url.
235 + * @type string $src Optional, src attribute value if different of the url, for example if base64 encoded.
236 + * @type int $width Optional, flag width in pixels.
237 + * @type int $height Optional, flag height in pixels.
238 + * }
103 239 */
104 240 public static function get_flag_informations( $code ) {
105 241 $flag = array( 'url' => '' );
106 242
107 - // Polylang builtin flags
243 + // Polylang builtin flags.
108 244 if ( ! empty( $code ) && file_exists( POLYLANG_DIR . ( $file = '/flags/' . $code . '.png' ) ) ) {
109 - $flag['url'] = $_url = plugins_url( $file, POLYLANG_FILE );
245 + $flag['url'] = plugins_url( $file, POLYLANG_FILE );
246 +
247 + // If base64 encoded flags are preferred.
248 + if ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) {
249 + list( $flag['width'], $flag['height'] ) = getimagesize( POLYLANG_DIR . $file );
250 + $file_contents = file_get_contents( POLYLANG_DIR . $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
251 + $flag['src'] = 'data:image/png;base64,' . base64_encode( $file_contents ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
252 + }
110 253 }
111 254
112 255 /**
113 - * Filter flag informations
114 - * 'url' => Flag url
115 - * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
116 - * 'width' => Optional, flag width in pixels
117 - * 'height' => Optional, flag height in pixels
256 + * Filters flag informations:
118 257 *
119 258 * @since 2.4
120 259 *
121 - * @param array $flag Information about the flag
122 - * @param string $code Flag code
260 + * @param array $flag {
261 + * Information about the flag.
262 + *
263 + * @type string $url Flag url.
264 + * @type string $src Optional, src attribute value if different of the url, for example if base64 encoded.
265 + * @type int $width Optional, flag width in pixels.
266 + * @type int $height Optional, flag height in pixels.
267 + * }
268 + * @param string $code Flag code.
123 269 */
124 270 $flag = apply_filters( 'pll_flag', $flag, $code );
125 271
272 + $flag['url'] = esc_url_raw( $flag['url'] );
273 +
126 274 if ( empty( $flag['src'] ) ) {
127 - // If using predefined flags and base64 encoded flags are preferred
128 - if ( isset( $_url ) && $flag['url'] === $_url && ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) ) {
129 - list( $flag['width'], $flag['height'] ) = getimagesize( POLYLANG_DIR . $file );
130 - $file_contents = file_get_contents( POLYLANG_DIR . $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
131 - $flag['src'] = 'data:image/png;base64,' . base64_encode( $file_contents ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
132 - } else {
133 - $flag['src'] = esc_url( set_url_scheme( $flag['url'], 'relative' ) );
134 - }
275 + $flag['src'] = esc_url( set_url_scheme( $flag['url'], 'relative' ) );
135 276 }
136 277
137 - $flag['url'] = esc_url_raw( $flag['url'] );
138 -
139 278 return $flag;
140 279 }
141 280
142 281 /**
143 - * Sets flag_url and flag properties
282 + * Sets flag_url and flag properties.
144 283 *
145 284 * @since 1.2
285 + *
286 + * @return void
146 287 */
147 288 public function set_flag() {
148 289 $flags = array( 'flag' => self::get_flag_informations( $this->flag_code ) );
149 290
150 - // Custom flags ?
291 + // Custom flags?
151 292 $directories = array(
152 293 PLL_LOCAL_DIR,
153 294 get_stylesheet_directory() . '/polylang',
154 295 get_template_directory() . '/polylang',
@@ -161,18 +302,21 @@
161 302 }
162 303 }
163 304
164 305 /**
165 - * Filter the custom flag informations
166 - * 'url' => Flag url
167 - * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
168 - * 'width' => Optional, flag width in pixels
169 - * 'height' => Optional, flag height in pixels
306 + * Filters the custom flag informations.
170 307 *
308 + * @param array $flag {
309 + * Information about the custom flag.
310 + *
311 + * @type string $url Flag url.
312 + * @type string $src Optional, src attribute value if different of the url, for example if base64 encoded.
313 + * @type int $width Optional, flag width in pixels.
314 + * @type int $height Optional, flag height in pixels.
315 + * }
316 + * @param string $code Flag code.
317 + *
171 318 * @since 2.4
172 - *
173 - * @param array $flag Information about the custom flag
174 - * @param string $code Flag code
175 319 */
176 320 $flags['custom_flag'] = apply_filters( 'pll_custom_flag', empty( $flags['custom_flag'] ) ? null : $flags['custom_flag'], $this->flag_code );
177 321
178 322 if ( ! empty( $flags['custom_flag']['url'] ) ) {
@@ -185,16 +329,16 @@
185 329 unset( $flags['custom_flag'] );
186 330 }
187 331
188 332 /**
189 - * Filter the flag title attribute
190 - * Defaults to the language name
333 + * Filters the flag title attribute.
334 + * Defaults to the language name.
191 335 *
192 336 * @since 0.7
193 337 *
194 - * @param string $title the flag title attribute
195 - * @param string $slug the language code
196 - * @param string $locale the language locale
338 + * @param string $title The flag title attribute.
339 + * @param string $slug The language code.
340 + * @param string $locale The language locale.
197 341 */
198 342 $title = apply_filters( 'pll_flag_title', $this->name, $this->slug, $this->locale );
199 343
200 344 foreach ( $flags as $key => $flag ) {
@@ -200,14 +344,14 @@
200 344 foreach ( $flags as $key => $flag ) {
201 345 $this->{$key . '_url'} = empty( $flag['url'] ) ? '' : $flag['url'];
202 346
203 347 /**
204 - * Filter the html markup of a flag
348 + * Filters the html markup of a flag.
205 349 *
206 350 * @since 1.0.2
207 351 *
208 - * @param string $flag html markup of the flag or empty string
209 - * @param string $slug language code
352 + * @param string $flag Html markup of the flag or empty string.
353 + * @param string $slug Language code.
210 354 */
211 355 $this->{$key} = apply_filters(
212 356 'pll_get_flag',
213 357 self::get_flag_html( $flag, $title, $this->name ),
@@ -216,62 +360,91 @@
216 360 }
217 361 }
218 362
219 363 /**
220 - * Get HTML code for flag
364 + * Get HTML code for flag.
221 365 *
222 366 * @since 2.7
223 367 *
224 - * @param array $flag flag properties: src, width and height
225 - * @param string $title optional title attribute
226 - * @param string $alt optional alt attribute
368 + * @param array $flag Flag properties: src, width and height.
369 + * @param string $title Optional title attribute.
370 + * @param string $alt Optional alt attribute.
371 + * @return string
227 372 */
228 373 public static function get_flag_html( $flag, $title = '', $alt = '' ) {
229 - return empty( $flag['src'] ) ? '' : sprintf(
374 + if ( empty( $flag['src'] ) ) {
375 + return '';
376 + }
377 +
378 + $alt_attr = empty( $alt ) ? '' : sprintf( ' alt="%s"', esc_attr( $alt ) );
379 + $width_attr = empty( $flag['width'] ) ? '' : sprintf( ' width="%s"', (int) $flag['width'] );
380 + $height_attr = empty( $flag['height'] ) ? '' : sprintf( ' height="%s"', (int) $flag['height'] );
381 +
382 + $style = '';
383 + $sizes = array_intersect_key( $flag, array_flip( array( 'width', 'height' ) ) );
384 +
385 + if ( ! empty( $sizes ) ) {
386 + array_walk(
387 + $sizes,
388 + function ( &$value, $key ) {
389 + $value = sprintf( '%s: %dpx;', esc_attr( $key ), (int) $value );
390 + }
391 + );
392 + $style = sprintf( ' style="%s"', implode( ' ', $sizes ) );
393 + }
394 +
395 + return sprintf(
230 396 '<img src="%s"%s%s%s%s />',
231 397 $flag['src'],
232 - empty( $title ) ? '' : sprintf( ' title="%s"', esc_attr( $title ) ),
233 - empty( $alt ) ? '' : sprintf( ' alt="%s"', esc_attr( $alt ) ),
234 - empty( $flag['width'] ) ? '' : sprintf( ' width="%s"', (int) $flag['width'] ),
235 - empty( $flag['height'] ) ? '' : sprintf( ' height="%s"', (int) $flag['height'] )
398 + $alt_attr,
399 + $width_attr,
400 + $height_attr,
401 + $style
236 402 );
237 403 }
238 404
239 405 /**
240 - * Replace flag by custom flag
241 - * Takes care of url scheme
406 + * Returns the html of the custom flag if any, or the default flag otherwise.
242 407 *
243 - * @since 1.7
408 + * @since 2.8
409 + *
410 + * @return string
244 411 */
245 - public function set_custom_flag() {
246 - // Overwrite with custom flags on frontend only
247 - if ( ! empty( $this->custom_flag ) ) {
248 - $this->flag = $this->custom_flag;
249 - $this->flag_url = $this->custom_flag_url;
250 - unset( $this->custom_flag, $this->custom_flag_url ); // hide this
251 - }
412 + public function get_display_flag() {
413 + return empty( $this->custom_flag ) ? $this->flag : $this->custom_flag;
414 + }
252 415
253 - // Set url scheme, also for default flags
254 - $this->flag_url = set_url_scheme( $this->flag_url );
416 + /**
417 + * Returns the url of the custom flag if any, or the default flag otherwise.
418 + *
419 + * @since 2.8
420 + *
421 + * @return string
422 + */
423 + public function get_display_flag_url() {
424 + return empty( $this->custom_flag_url ) ? $this->flag_url : $this->custom_flag_url;
255 425 }
256 426
257 427 /**
258 - * Updates post and term count
428 + * Updates post and term count.
259 429 *
260 430 * @since 1.2
431 + *
432 + * @return void
261 433 */
262 434 public function update_count() {
263 - wp_update_term_count( $this->term_taxonomy_id, 'language' ); // posts count
264 - wp_update_term_count( $this->tl_term_taxonomy_id, 'term_language' ); // terms count
435 + wp_update_term_count( $this->term_taxonomy_id, 'language' ); // Posts count.
436 + wp_update_term_count( $this->tl_term_taxonomy_id, 'term_language' ); // Terms count.
265 437 }
266 438
267 439 /**
268 - * Set home_url and search_url properties
440 + * Set home_url and search_url properties.
269 441 *
270 442 * @since 1.3
271 443 *
272 - * @param string $search_url
273 - * @param string $home_url
444 + * @param string $search_url Home url to use in search forms.
445 + * @param string $home_url Home url.
446 + * @return void
274 447 */
275 448 public function set_home_url( $search_url, $home_url ) {
276 449 $this->search_url = $search_url;
277 450 $this->home_url = $home_url;
@@ -277,25 +450,42 @@
277 450 $this->home_url = $home_url;
278 451 }
279 452
280 453 /**
281 - * Set home_url scheme
282 - * this can't be cached across pages
454 + * Sets the scheme of the home url and the flag urls.
283 455 *
284 - * @since 1.6.4
456 + * This can't be cached across pages.
457 + *
458 + * @since 2.8
459 + *
460 + * @return void
285 461 */
286 - public function set_home_url_scheme() {
287 - $this->home_url = set_url_scheme( $this->home_url );
288 - $this->search_url = set_url_scheme( $this->search_url );
462 + public function set_url_scheme() {
463 + if ( ! empty( $this->home_url ) ) {
464 + $this->home_url = set_url_scheme( $this->home_url );
465 + }
466 +
467 + if ( ! empty( $this->search_url ) ) {
468 + $this->search_url = set_url_scheme( $this->search_url );
469 + }
470 +
471 + // Set url scheme, also for the flags.
472 + if ( ! empty( $this->flag_url ) ) {
473 + $this->flag_url = set_url_scheme( $this->flag_url );
474 + }
475 +
476 + if ( ! empty( $this->custom_flag_url ) ) {
477 + $this->custom_flag_url = set_url_scheme( $this->custom_flag_url );
478 + }
289 479 }
290 480
291 481 /**
292 - * Returns the language locale
293 - * Converts WP locales to W3C valid locales for display
482 + * Returns the language locale.
483 + * Converts WP locales to W3C valid locales for display.
294 484 *
295 485 * @since 1.8
296 486 *
297 - * @param string $filter either 'display' or 'raw', defaults to raw
487 + * @param string $filter Either 'display' or 'raw', defaults to raw.
298 488 * @return string
299 489 */
300 490 public function get_locale( $filter = 'raw' ) {
301 491 return 'display' === $filter ? $this->w3c : $this->locale;