PluginProbe
WPSSO Core – Complete Schema Markup and Meta Tags / 22.7.0
WPSSO Core – Complete Schema Markup and Meta Tags v22.7.0
22.7.0 22.6.1 22.6.0 22.5.3 22.5.2 22.5.1 22.4.0 22.3.0 22.2.1 22.2.0 22.1.3 22.1.2 22.1.1 22.1.0 22.0.0 21.13.3 21.13.2 trunk 21.13.1
← All changes | lib/integ/lang/wpml.php +512 -0 22.6.022.7.0 View file →
@@ -1,0 +1,512 @@
1 +<?php
2 +/*
3 + * License: GPLv3
4 + * License URI: https://www.gnu.org/licenses/gpl.txt
5 + * Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/)
6 + */
7 +
8 +if ( ! defined( 'ABSPATH' ) ) {
9 +
10 + die( 'These aren\'t the droids you\'re looking for.' );
11 +}
12 +
13 +if ( ! class_exists( 'WpssoIntegLangWpml' ) ) {
14 +
15 + class WpssoIntegLangWpml {
16 +
17 + private $p; // Wpsso class object.
18 +
19 + public function __construct( &$plugin ) {
20 +
21 + $this->p =& $plugin;
22 +
23 + if ( $this->p->debug->enabled ) {
24 +
25 + $this->p->debug->mark();
26 + }
27 +
28 + add_action( 'change_locale', array( $this, 'locale_changed' ), -200, 1 );
29 +
30 + $this->p->util->add_plugin_filters( $this, array(
31 + 'sitemaps_alternates' => 2,
32 + 'post_public_ids_suppress_filters' => '__return_false',
33 + ) );
34 +
35 + $this->p->util->add_plugin_filters( $this, array(
36 + 'available_feed_locale_names' => 1,
37 + 'get_locale' => 2,
38 + ), $prio = 1000, $ext = 'sucom' ); // Note the 'sucom' filter prefix.
39 + }
40 +
41 + /*
42 + * Check that the active WPML language matches the changed WordPress locale.
43 + */
44 + public function locale_changed( $wp_locale ) {
45 +
46 + $wpml_locale = $this->get_active_locale(); // Get the active WPML locale.
47 +
48 + if ( $this->p->debug->enabled ) {
49 +
50 + $this->p->debug->log( 'wp_locale = ' . $wp_locale );
51 + $this->p->debug->log( 'wpml_locale = ' . $wpml_locale );
52 + }
53 +
54 + if ( $wpml_locale && $wpml_locale !== $wp_locale ) { // Just in case.
55 +
56 + $active_languages = $this->get_active_languages(); // Uses a local cache.
57 +
58 + if ( is_array( $active_languages ) ) { // Just in case.
59 +
60 + foreach ( $active_languages as $wpml_code => $lang ) {
61 +
62 + if ( ! empty( $lang[ 'default_locale' ] ) ) { // Just in case.
63 +
64 + if ( $wp_locale === $lang[ 'default_locale' ] ) {
65 +
66 + if ( $this->p->debug->enabled ) {
67 +
68 + $this->p->debug->log( 'switching to wpml_code = ' . $wpml_code );
69 + }
70 +
71 + do_action( 'wpml_switch_language', $wpml_code );
72 +
73 + return; // Stop here.
74 + }
75 + }
76 + }
77 + }
78 + }
79 + }
80 +
81 + public function filter_sitemaps_alternates( $alternates, $mod ) {
82 +
83 + if ( $this->p->debug->enabled ) {
84 +
85 + $this->p->debug->mark();
86 + }
87 +
88 + $element_type = null;
89 +
90 + if ( $mod[ 'is_post' ] ) {
91 +
92 + $element_type = 'post_' . $mod[ 'post_type' ];
93 +
94 + } elseif ( $mod[ 'is_term' ] ) {
95 +
96 + $element_type = 'tax_' . $mod[ 'tax_slug' ];
97 + }
98 +
99 + if ( $element_type ) {
100 +
101 + /*
102 + * See https://wpml.org/wpml-hook/wpml_element_trid/.
103 + */
104 + $element_trid = apply_filters( 'wpml_element_trid', null, $mod[ 'id' ], $element_type );
105 +
106 + if ( $this->p->debug->enabled ) {
107 +
108 + $this->p->debug->log_arr( 'element trid = ', $element_trid );
109 + }
110 +
111 + /*
112 + * See https://wpml.org/wpml-hook/wpml_get_element_translations/.
113 + */
114 + $translations = apply_filters( 'wpml_get_element_translations', null, $element_trid );
115 +
116 + if ( empty( $translations ) ) { // Just in case.
117 +
118 + if ( $this->p->debug->enabled ) {
119 +
120 + $this->p->debug->log( 'returned element translations is empty' );
121 + }
122 +
123 + } else {
124 +
125 + $active_code = $this->get_active_code();
126 + $last_code = $active_code;
127 +
128 + foreach ( $translations as $wpml_code => $transl_obj ) {
129 +
130 + if ( empty( $transl_obj->element_id ) ) { // Just in case.
131 +
132 + if ( $this->p->debug->enabled ) {
133 +
134 + $this->p->debug->log( 'skipping translation ' . $wpml_code . ': object element id is empty' );
135 +
136 + $this->p->debug->log_arr( 'transl_obj', $transl_obj ); // Logs the object variables.
137 + }
138 +
139 + continue;
140 + }
141 +
142 + if ( $this->p->debug->enabled ) {
143 +
144 + $this->p->debug->mark( 'getting alternate array for ' . $wpml_code ); // Begin timer.
145 +
146 + $this->p->debug->log_arr( 'transl_obj', $transl_obj ); // Logs the object variables.
147 + }
148 +
149 + if ( $wpml_code !== $last_code ) { // Just in case.
150 +
151 + if ( $this->p->debug->enabled ) {
152 +
153 + $this->p->debug->log( 'switching to wpml_code = ' . $wpml_code );
154 + }
155 +
156 + do_action( 'wpml_switch_language', $wpml_code );
157 +
158 + $last_code = $wpml_code;
159 + }
160 +
161 + $transl_mod = $mod[ 'obj' ]->get_mod( $transl_obj->element_id );
162 +
163 + $transl_mod[ 'wpml_code' ] = $wpml_code; // Optimize.
164 +
165 + $alternates[] = array(
166 + 'href' => $this->p->util->get_canonical_url( $transl_mod ),
167 + 'hreflang' => $this->p->schema->get_schema_lang( $transl_mod ),
168 + );
169 +
170 + if ( $this->p->debug->enabled ) {
171 +
172 + $this->p->debug->mark( 'getting alternate array for ' . $wpml_code ); // End timer.
173 + }
174 + }
175 +
176 + if ( $this->p->debug->enabled ) {
177 +
178 + $this->p->debug->log( 'switching back to wpml_code = ' . $active_code );
179 + }
180 +
181 + do_action( 'wpml_switch_language', $active_code );
182 + }
183 + }
184 +
185 + return $alternates;
186 + }
187 +
188 + public function filter_available_feed_locale_names( $locale_names ) {
189 +
190 + if ( $this->p->debug->enabled ) {
191 +
192 + $this->p->debug->mark();
193 + }
194 +
195 + $locale_names = array();
196 + $active_languages = $this->get_active_languages(); // Uses a local cache.
197 +
198 + if ( is_array( $active_languages ) ) { // Just in case.
199 +
200 + foreach ( $active_languages as $wpml_code => $lang ) {
201 +
202 + if ( ! empty( $lang[ 'default_locale' ] ) ) { // Just in case.
203 +
204 + $locale_names[ $lang[ 'default_locale' ] ] = $lang[ 'native_name' ];
205 + }
206 + }
207 + }
208 +
209 + return $locale_names;
210 + }
211 +
212 + /*
213 + * Argument can also be a numeric post ID, to return the language of that post.
214 + */
215 + public function filter_get_locale( $locale, $mixed = 'current' ) {
216 +
217 + if ( $this->p->debug->enabled ) {
218 +
219 + $this->p->debug->mark();
220 + }
221 +
222 + $wpml_locale = false;
223 +
224 + switch ( true ) {
225 +
226 + case ( is_array( $mixed ) ): // $mod array.
227 +
228 + if ( $this->p->debug->enabled ) {
229 +
230 + $this->p->debug->log( 'getting wpml_locale for array' );
231 + }
232 +
233 + if ( isset( $mixed[ 'id' ] ) && $mixed[ 'id' ] > 0 ) { // Just in case.
234 +
235 + $wpml_locale = $this->get_mod_locale( $mixed );
236 +
237 + if ( $this->p->debug->enabled ) {
238 +
239 + $this->p->debug->log( 'wpml_locale ' . $mixed[ 'name' ] . ' id ' . $mixed[ 'id' ] . ' = ' . $wpml_locale );
240 + }
241 + }
242 +
243 + break;
244 +
245 + case ( is_numeric( $mixed ) ) : // Post ID.
246 +
247 + if ( $this->p->debug->enabled ) {
248 +
249 + $this->p->debug->log( 'getting wpml_locale for post id' );
250 + }
251 +
252 + if ( $mixed > 0 ) { // Just in case.
253 +
254 + $wpml_locale = $this->get_post_locale( $mixed );
255 +
256 + if ( $this->p->debug->enabled ) {
257 +
258 + $this->p->debug->log( 'wpml_locale post id ' . $mixed . ' = ' . $wpml_locale );
259 + }
260 + }
261 +
262 + break;
263 +
264 + case ( 'default' === $mixed ): // Noting to do.
265 +
266 + if ( $this->p->debug->enabled ) {
267 +
268 + $this->p->debug->log( 'skipping wpml_locale for default' );
269 + }
270 +
271 + break;
272 +
273 + case ( 'current' === $mixed ): // Current / active locale.
274 +
275 + if ( $this->p->debug->enabled ) {
276 +
277 + $this->p->debug->log( 'getting wpml_locale for current' );
278 + }
279 +
280 + $wpml_locale = $this->get_active_locale(); // Get the active WPML locale.
281 +
282 + break;
283 +
284 + default: // Just in case.
285 +
286 + if ( $this->p->debug->enabled ) {
287 +
288 + $this->p->debug->log( 'unrecognized wpml_locale request = ' . print_r( $mixed, true ) );
289 + }
290 +
291 + break;
292 + }
293 +
294 + if ( $wpml_locale ) {
295 +
296 + if ( $this->p->debug->enabled ) {
297 +
298 + $this->p->debug->log( 'returning wpml_locale = ' . $wpml_locale );
299 + }
300 +
301 + return $wpml_locale; // Stop here.
302 + }
303 +
304 + if ( $this->p->debug->enabled ) {
305 +
306 + $this->p->debug->log( 'returning locale = ' . $locale );
307 + }
308 +
309 + return $locale; // No change.
310 + }
311 +
312 + private function get_active_code() {
313 +
314 + if ( $this->p->debug->enabled ) {
315 +
316 + $this->p->debug->mark();
317 + }
318 +
319 + $active_languages = $this->get_active_languages(); // Uses a local cache.
320 +
321 + if ( is_array( $active_languages ) ) { // Just in case.
322 +
323 + foreach ( $active_languages as $wpml_code => $lang ) {
324 +
325 + if ( ! empty( $lang[ 'active' ] ) ) { // Is the current language.
326 +
327 + if ( $this->p->debug->enabled ) {
328 +
329 + $this->p->debug->log( 'active wpml_code = ' . $wpml_code );
330 + }
331 +
332 + return $wpml_code;
333 + }
334 + }
335 + }
336 +
337 + return false;
338 + }
339 +
340 + private function get_active_languages() {
341 +
342 + if ( $this->p->debug->enabled ) {
343 +
344 + $this->p->debug->mark();
345 + }
346 +
347 + return apply_filters( 'wpml_active_languages', null );
348 + }
349 +
350 + private function get_active_locale() {
351 +
352 + if ( $this->p->debug->enabled ) {
353 +
354 + $this->p->debug->mark();
355 + }
356 +
357 + $active_languages = $this->get_active_languages(); // Uses a local cache.
358 +
359 + if ( is_array( $active_languages ) ) { // Just in case.
360 +
361 + foreach ( $active_languages as $wpml_code => $lang ) {
362 +
363 + if ( ! empty( $lang[ 'active' ] ) ) { // Is the current language.
364 +
365 + if ( ! empty( $lang[ 'default_locale' ] ) ) { // Just in case.
366 +
367 + if ( $this->p->debug->enabled ) {
368 +
369 + $this->p->debug->log( 'wpml_locale current = ' . $lang[ 'default_locale' ] );
370 + }
371 +
372 + return $lang[ 'default_locale' ];
373 + }
374 +
375 + return false;
376 + }
377 + }
378 + }
379 +
380 + return false;
381 + }
382 +
383 + private function get_post_locale( $post_id ) {
384 +
385 + if ( $this->p->debug->enabled ) {
386 +
387 + $this->p->debug->mark();
388 + }
389 +
390 + /*
391 + * See https://wpml.org/wpml-hook/wpml_post_language_details/.
392 + */
393 + $post_details = apply_filters( 'wpml_post_language_details', null, $post_id );
394 +
395 + if ( is_wp_error( $post_details ) ) {
396 +
397 + $error_pre = sprintf( '%s error:', __METHOD__ );
398 + $error_msg = 'wpml_post_language_details error: ' . $post_details->get_error_message();
399 +
400 + if ( $this->p->debug->enabled ) {
401 +
402 + $this->p->debug->log( $error_msg );
403 + }
404 +
405 + $this->p->notice->err( $error_msg );
406 +
407 + SucomUtil::safe_error_log( $error_pre . ' ' . $error_msg );
408 +
409 + } elseif ( is_array( $post_details ) ) { // Just in case.
410 +
411 + if ( ! empty( $post_details[ 'locale' ] ) ) {
412 +
413 + return $post_details[ 'locale' ];
414 + }
415 + }
416 +
417 + return false;
418 + }
419 +
420 + private function get_mod_locale( array $mod ) {
421 +
422 + if ( $this->p->debug->enabled ) {
423 +
424 + $this->p->debug->mark();
425 + }
426 +
427 + $wpml_locale = false;
428 + $wpml_code = $this->get_mod_code( $mod );
429 +
430 + if ( $wpml_code ) {
431 +
432 + $active_languages = $this->get_active_languages(); // Uses a local cache.
433 +
434 + if ( ! empty( $active_languages[ $wpml_code ][ 'default_locale' ] ) ) {
435 +
436 + return $active_languages[ $wpml_code ][ 'default_locale' ];
437 + }
438 + }
439 +
440 + return false;
441 + }
442 +
443 + private function get_mod_code( array $mod ) {
444 +
445 + if ( $this->p->debug->enabled ) {
446 +
447 + $this->p->debug->mark();
448 + }
449 +
450 + if ( $mod[ 'wpml_code' ] ) { // Set in filter_sitemaps_alternates().
451 +
452 + if ( $this->p->debug->enabled ) {
453 +
454 + $this->p->debug->log( 'module wpml_code = ' . $mod[ 'wpml_code' ] );
455 + }
456 +
457 + return $mod[ 'wpml_code' ];
458 + }
459 +
460 + $args = null;
461 + $wpml_code = null;
462 +
463 + if ( $mod[ 'is_post' ] ) {
464 +
465 + $args = array( 'element_id' => $mod[ 'id' ], 'element_type' => $mod[ 'post_type' ] );
466 +
467 + } elseif ( $mod[ 'is_term' ] ) {
468 +
469 + $args = array( 'element_id' => $mod[ 'id' ], 'element_type' => $mod[ 'tax_slug' ] );
470 + }
471 +
472 + if ( $this->p->debug->enabled ) {
473 +
474 + $this->p->debug->log_arr( 'args', $args );
475 + }
476 +
477 + if ( $args ) {
478 +
479 + /*
480 + * See https://wpml.org/wpml-hook/wpml_element_language_code/.
481 + */
482 + $wpml_code = apply_filters( 'wpml_element_language_code', null, $args );
483 +
484 + if ( is_wp_error( $wpml_code ) ) {
485 +
486 + $error_pre = sprintf( '%s error:', __METHOD__ );
487 + $error_msg = 'wpml_element_language_code error: ' . $wpml_code->get_error_message();
488 +
489 + if ( $this->p->debug->enabled ) {
490 +
491 + $this->p->debug->log( $error_msg );
492 + }
493 +
494 + $this->p->notice->err( $error_msg );
495 +
496 + SucomUtil::safe_error_log( $error_pre . ' ' . $error_msg );
497 +
498 + } else {
499 +
500 + if ( $this->p->debug->enabled ) {
501 +
502 + $this->p->debug->log( 'wpml_code = ' . $wpml_code );
503 + }
504 +
505 + return $wpml_code;
506 + }
507 + }
508 +
509 + return false;
510 + }
511 + }
512 +}