PluginProbe
Polylang / 2.9
Polylang v2.9
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 / language.php

language.php in Polylang 2.9, at include/language.php

337 lines 11.0 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 * 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
9 *
10 * Properties:
11 * term_id => id of term in 'language' taxonomy
12 * name => language name. Ex: English
13 * slug => language code used in url. Ex: en
14 * term_group => order of the language when displayed in a list of languages
15 * term_taxonomy_id => term taxonomy id in 'language' taxonomy
16 * taxonomy => 'language'
17 * description => language locale for backward compatibility
18 * parent => 0 / not used
19 * count => number of posts and pages in that language
20 * tl_term_id => id of the term in 'term_language' taxonomy
21 * tl_term_taxonomy_id => term taxonomy id in 'term_language' taxonomy
22 * tl_count => number of terms in that language ( not used by Polylang )
23 * locale => WordPress language locale. Ex: en_US
24 * is_rtl => 1 if the language is rtl
25 * w3c => W3C locale
26 * flag_code => code of the flag
27 * flag_url => url of the flag
28 * flag => html img of the flag
29 * custom_flag_url => url of the custom flag if exists, internal use only, moves to flag_url on frontend
30 * custom_flag => html img of the custom flag if exists, internal use only, moves to flag on frontend
31 * home_url => home url in this language
32 * search_url => home url to use in search forms
33 * host => host of this language
34 * mo_id => id of the post storing strings translations
35 * page_on_front => id of the page on front in this language ( set from pll_languages_list filter )
36 * page_for_posts => id of the page for posts in this language ( set from pll_languages_list filter )
37 *
38 * @since 1.2
39 */
40 class PLL_Language {
41 public $term_id, $name, $slug, $term_group, $term_taxonomy_id, $taxonomy, $description, $parent, $count;
42 public $tl_term_id, $tl_term_taxonomy_id, $tl_count;
43 public $locale, $is_rtl;
44 public $w3c, $facebook;
45 public $flag_url, $flag;
46 public $home_url, $search_url;
47 public $host, $mo_id;
48 public $page_on_front, $page_for_posts;
49
50 /**
51 * Constructor: builds a language object given its two corresponding terms in language and term_language taxonomies
52 *
53 * @since 1.2
54 *
55 * @param object|array $language 'language' term or language object properties stored as an array
56 * @param object $term_language Corresponding 'term_language' term
57 */
58 public function __construct( $language, $term_language = null ) {
59 // Build the object from all properties stored as an array
60 if ( empty( $term_language ) ) {
61 foreach ( $language as $prop => $value ) {
62 $this->$prop = $value;
63 }
64 }
65
66 // Build the object from taxonomies
67 else {
68 foreach ( $language as $prop => $value ) {
69 $this->$prop = in_array( $prop, array( 'term_id', 'term_taxonomy_id', 'count' ) ) ? (int) $language->$prop : $language->$prop;
70 }
71
72 $this->tl_term_id = (int) $term_language->term_id;
73 $this->tl_term_taxonomy_id = (int) $term_language->term_taxonomy_id;
74 $this->tl_count = (int) $term_language->count;
75
76 // The description field can contain any property
77 // Backward compatibility for is_rtl
78 $description = maybe_unserialize( $language->description );
79 foreach ( $description as $prop => $value ) {
80 'rtl' == $prop ? $this->is_rtl = $value : $this->$prop = $value;
81 }
82
83 $this->description = &$this->locale; // Backward compatibility with Polylang < 1.2
84
85 $this->mo_id = PLL_MO::get_id( $this );
86
87 $languages = include POLYLANG_DIR . '/settings/languages.php';
88 $this->w3c = isset( $languages[ $this->locale ]['w3c'] ) ? $languages[ $this->locale ]['w3c'] : str_replace( '_', '-', $this->locale );
89 if ( isset( $languages[ $this->locale ]['facebook'] ) ) {
90 $this->facebook = $languages[ $this->locale ]['facebook'];
91 }
92 }
93 }
94
95 /**
96 * Get the flag informations
97 * 'url' => Flag url
98 * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
99 * 'width' => Optional, flag width in pixels
100 * 'height' => Optional, flag height in pixels
101 *
102 * @since 2.6
103 *
104 * @param string $code Flag code.
105 * @return array Flag informations.
106 */
107 public static function get_flag_informations( $code ) {
108 $flag = array( 'url' => '' );
109
110 // Polylang builtin flags
111 if ( ! empty( $code ) && file_exists( POLYLANG_DIR . ( $file = '/flags/' . $code . '.png' ) ) ) {
112 $flag['url'] = $_url = plugins_url( $file, POLYLANG_FILE );
113 }
114
115 /**
116 * Filter flag informations
117 * 'url' => Flag url
118 * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
119 * 'width' => Optional, flag width in pixels
120 * 'height' => Optional, flag height in pixels
121 *
122 * @since 2.4
123 *
124 * @param array $flag Information about the flag
125 * @param string $code Flag code
126 */
127 $flag = apply_filters( 'pll_flag', $flag, $code );
128
129 if ( empty( $flag['src'] ) ) {
130 // If using predefined flags and base64 encoded flags are preferred
131 if ( isset( $_url ) && $flag['url'] === $_url && ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) ) {
132 list( $flag['width'], $flag['height'] ) = getimagesize( POLYLANG_DIR . $file );
133 $file_contents = file_get_contents( POLYLANG_DIR . $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
134 $flag['src'] = 'data:image/png;base64,' . base64_encode( $file_contents ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
135 } else {
136 $flag['src'] = esc_url( set_url_scheme( $flag['url'], 'relative' ) );
137 }
138 }
139
140 $flag['url'] = esc_url_raw( $flag['url'] );
141
142 return $flag;
143 }
144
145 /**
146 * Sets flag_url and flag properties
147 *
148 * @since 1.2
149 */
150 public function set_flag() {
151 $flags = array( 'flag' => self::get_flag_informations( $this->flag_code ) );
152
153 // Custom flags ?
154 $directories = array(
155 PLL_LOCAL_DIR,
156 get_stylesheet_directory() . '/polylang',
157 get_template_directory() . '/polylang',
158 );
159
160 foreach ( $directories as $dir ) {
161 if ( file_exists( $file = "{$dir}/{$this->locale}.png" ) || file_exists( $file = "{$dir}/{$this->locale}.jpg" ) || file_exists( $file = "{$dir}/{$this->locale}.svg" ) ) {
162 $flags['custom_flag']['url'] = content_url( '/' . str_replace( WP_CONTENT_DIR, '', $file ) );
163 break;
164 }
165 }
166
167 /**
168 * Filter the custom flag informations
169 * 'url' => Flag url
170 * 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
171 * 'width' => Optional, flag width in pixels
172 * 'height' => Optional, flag height in pixels
173 *
174 * @since 2.4
175 *
176 * @param array $flag Information about the custom flag
177 * @param string $code Flag code
178 */
179 $flags['custom_flag'] = apply_filters( 'pll_custom_flag', empty( $flags['custom_flag'] ) ? null : $flags['custom_flag'], $this->flag_code );
180
181 if ( ! empty( $flags['custom_flag']['url'] ) ) {
182 if ( empty( $flags['custom_flag']['src'] ) ) {
183 $flags['custom_flag']['src'] = esc_url( set_url_scheme( $flags['custom_flag']['url'], 'relative' ) );
184 }
185
186 $flags['custom_flag']['url'] = esc_url_raw( $flags['custom_flag']['url'] );
187 } else {
188 unset( $flags['custom_flag'] );
189 }
190
191 /**
192 * Filter the flag title attribute
193 * Defaults to the language name
194 *
195 * @since 0.7
196 *
197 * @param string $title the flag title attribute
198 * @param string $slug the language code
199 * @param string $locale the language locale
200 */
201 $title = apply_filters( 'pll_flag_title', $this->name, $this->slug, $this->locale );
202
203 foreach ( $flags as $key => $flag ) {
204 $this->{$key . '_url'} = empty( $flag['url'] ) ? '' : $flag['url'];
205
206 /**
207 * Filter the html markup of a flag
208 *
209 * @since 1.0.2
210 *
211 * @param string $flag html markup of the flag or empty string
212 * @param string $slug language code
213 */
214 $this->{$key} = apply_filters(
215 'pll_get_flag',
216 self::get_flag_html( $flag, $title, $this->name ),
217 $this->slug
218 );
219 }
220 }
221
222 /**
223 * Get HTML code for flag
224 *
225 * @since 2.7
226 *
227 * @param array $flag flag properties: src, width and height
228 * @param string $title optional title attribute
229 * @param string $alt optional alt attribute
230 */
231 public static function get_flag_html( $flag, $title = '', $alt = '' ) {
232 if ( empty( $flag['src'] ) ) {
233 return '';
234 }
235
236 $title_attr = empty( $title ) ? '' : sprintf( ' title="%s"', esc_attr( $title ) );
237 $alt_attr = empty( $alt ) ? '' : sprintf( ' alt="%s"', esc_attr( $alt ) );
238 $width_attr = empty( $flag['width'] ) ? '' : sprintf( ' width="%s"', (int) $flag['width'] );
239 $height_attr = empty( $flag['height'] ) ? '' : sprintf( ' height="%s"', (int) $flag['height'] );
240
241 $style = '';
242 $sizes = array_intersect_key( $flag, array_flip( array( 'width', 'height' ) ) );
243
244 if ( ! empty( $sizes ) ) {
245 array_walk(
246 $sizes,
247 function ( &$value, $key ) {
248 $value = sprintf( '%s: %dpx;', esc_attr( $key ), (int) $value );
249 }
250 );
251 $style = sprintf( ' style="%s"', implode( ' ', $sizes ) );
252 }
253
254 return sprintf(
255 '<img src="%s"%s%s%s%s%s />',
256 $flag['src'],
257 $title_attr,
258 $alt_attr,
259 $width_attr,
260 $height_attr,
261 $style
262 );
263 }
264
265 /**
266 * Returns the html of the custom flag if any, or the default flag otherwise.
267 *
268 * @since 2.8
269 */
270 public function get_display_flag() {
271 return empty( $this->custom_flag ) ? $this->flag : $this->custom_flag;
272 }
273
274 /**
275 * Returns the url of the custom flag if any, or the default flag otherwise.
276 *
277 * @since 2.8
278 */
279 public function get_display_flag_url() {
280 return empty( $this->custom_flag_url ) ? $this->flag_url : $this->custom_flag_url;
281 }
282
283 /**
284 * Updates post and term count
285 *
286 * @since 1.2
287 */
288 public function update_count() {
289 wp_update_term_count( $this->term_taxonomy_id, 'language' ); // posts count
290 wp_update_term_count( $this->tl_term_taxonomy_id, 'term_language' ); // terms count
291 }
292
293 /**
294 * Set home_url and search_url properties
295 *
296 * @since 1.3
297 *
298 * @param string $search_url
299 * @param string $home_url
300 */
301 public function set_home_url( $search_url, $home_url ) {
302 $this->search_url = $search_url;
303 $this->home_url = $home_url;
304 }
305
306 /**
307 * Sets the scheme of the home url and the flag urls
308 *
309 * This can't be cached across pages.
310 *
311 * @since 2.8
312 */
313 public function set_url_scheme() {
314 $this->home_url = set_url_scheme( $this->home_url );
315 $this->search_url = set_url_scheme( $this->search_url );
316
317 // Set url scheme, also for the flags.
318 $this->flag_url = set_url_scheme( $this->flag_url );
319 if ( ! empty( $this->custom_flag_url ) ) {
320 $this->custom_flag_url = set_url_scheme( $this->custom_flag_url );
321 }
322 }
323
324 /**
325 * Returns the language locale
326 * Converts WP locales to W3C valid locales for display
327 *
328 * @since 1.8
329 *
330 * @param string $filter either 'display' or 'raw', defaults to raw
331 * @return string
332 */
333 public function get_locale( $filter = 'raw' ) {
334 return 'display' === $filter ? $this->w3c : $this->locale;
335 }
336 }
337