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
wpsso / lib / util-inline.php

util-inline.php in WPSSO Core – Complete Schema Markup and Meta Tags 22.7.0, at lib/util-inline.php

616 lines 13.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 ( ! defined( 'WPSSO_PLUGINDIR' ) ) {
14
15 die( 'Do. Or do not. There is no try.' );
16 }
17
18 if ( ! class_exists( 'WpssoUtilInline' ) ) {
19
20 class WpssoUtilInline {
21
22 private $p; // Wpsso class object.
23 private $u; // WpssoUtil class object.
24
25 /*
26 * Instantiated by WpssoUtil->__construct().
27 */
28 public function __construct( &$plugin, &$util ) {
29
30 $this->p =& $plugin;
31 $this->u =& $util;
32
33 if ( $this->p->debug->enabled ) {
34
35 $this->p->debug->mark();
36 }
37 }
38
39 /*
40 * Replace inline variables in the subject text.
41 *
42 * $atts can be an associative array with additional information ('canonical_url', 'canonical_short_url', 'add_page', etc.).
43 *
44 * See WpssoPage->get_title().
45 * See WpssoPage->get_description().
46 */
47 public function replace_variables( $value, $mod = false, array $atts = array() ) {
48
49 static $local_recursion = 0;
50
51 if ( 0 === $local_recursion ) { // Do not log recursions.
52
53 if ( $this->p->debug->enabled ) {
54
55 $this->p->debug->mark();
56 }
57
58 } elseif ( $local_recursion > 32 ) { // Just in case.
59
60 return $value;
61
62 }
63
64 if ( is_array( $value ) ) {
65
66 /*
67 * The $mod array argument is preferred but not required.
68 *
69 * $mod = true | false | post_id | $mod array
70 */
71 if ( ! is_array( $mod ) ) {
72
73 if ( $this->p->debug->enabled ) {
74
75 $this->p->debug->log( 'optional call to WpssoPage->get_mod()' );
76 }
77
78 $mod = $this->p->page->get_mod( $mod );
79 }
80
81 foreach ( $value as $key => $el ) {
82
83 $local_recursion++;
84
85 $value[ $key ] = $this->replace_variables( $el, $mod, $atts );
86
87 $local_recursion--;
88 }
89
90 return $value;
91
92 } elseif ( ! is_string( $value ) ) { // Just in case - accept only arrays and strings.
93
94 return $value;
95
96 } elseif ( false === strpos( $value, '%%' ) ) { // No inline variable.
97
98 return $value;
99 }
100
101 /*
102 * The $mod array argument is preferred but not required.
103 *
104 * $mod = true | false | post_id | $mod array
105 */
106 if ( ! is_array( $mod ) ) {
107
108 if ( $this->p->debug->enabled ) {
109
110 $this->p->debug->log( 'optional call to WpssoPage->get_mod()' );
111 }
112
113 $mod = $this->p->page->get_mod( $mod );
114 }
115
116 /*
117 * Use a callback to get the inline variable values we need, as we need them.
118 *
119 * See https://www.php.net/manual/en/function.preg-replace-callback.php.
120 */
121 $callback = function( $matches ) use ( $mod, $atts ) {
122
123 return $this->replace_callback( $matches, $mod, $atts );
124 };
125
126 static $local_depth = 0;
127
128 while ( ++$local_depth <= 5 && false !== strpos( $value, '%%' ) ) {
129
130 if ( $this->p->debug->enabled ) {
131
132 $this->p->debug->log( 'preg_replace_callback() for value = ' . $value );
133 }
134
135 $value = preg_replace_callback( '/%%([^%]+)%%/', $callback, $value );
136 }
137
138 $local_depth = 0;
139
140 return $value;
141 }
142
143 private function replace_callback( array $matches, array $mod, array $atts ) {
144
145 $varname = $matches[ 1 ];
146 $ret_val = '';
147 $url_enc = empty( $atts[ 'rawurlencode' ] ) ? false : true;
148
149 /*
150 * Some inline variables and values may be passed in the $atts array, so check this array first.
151 */
152 if ( isset( $atts[ $varname ] ) ) {
153
154 return $url_enc ? rawurlencode( $atts[ $varname ] ) : $atts[ $varname ];
155 }
156
157 /*
158 * Use a local cache for values that will not change for this page load.
159 */
160 static $local_cache = null;
161
162 if ( null === $local_cache ) {
163
164 $date_format = get_option( 'date_format' );
165 $time_format = get_option( 'time_format' );
166 $charset = get_bloginfo( $show = 'charset', $filter = 'raw' );
167
168 $local_cache = array(
169 'def_title_sep' => html_entity_decode( $this->p->options[ 'og_title_sep' ], ENT_QUOTES, $charset ),
170 'def_ellipsis' => html_entity_decode( $this->p->options[ 'og_ellipsis' ], ENT_QUOTES, $charset ),
171 'date_format' => $date_format,
172 'time_format' => $time_format,
173 'currentdate' => date_i18n( $date_format ),
174 'currenttime' => date_i18n( $time_format ),
175 'currentday' => date_i18n( 'j' ),
176 'currentmonth' => date_i18n( 'F' ),
177 'currentyear' => date_i18n( 'Y' ),
178 );
179 }
180
181 if ( isset( $local_cache[ $varname ] ) ) {
182
183 return $url_enc ? rawurlencode( $local_cache[ $varname ] ) : $local_cache[ $varname ];
184 }
185
186 /*
187 * Detect and prevent recursion, just in case.
188 */
189 static $local_recursion = array();
190
191 if ( ! empty( $local_recursion[ $varname ] ) ) { // Recursion detected.
192
193 return $ret_val; // Stop here.
194 }
195
196 $local_recursion[ $varname ] = true; // Prevent recursion.
197
198 if ( $this->p->debug->enabled ) {
199
200 $this->p->debug->log( 'getting the %%' . $varname . '%% value' );
201 }
202
203 $add_page = isset( $atts[ 'add_page' ] ) ? $atts[ 'add_page' ] : false;
204 $title_sep = isset( $atts[ 'title_sep' ] ) ? $atts[ 'title_sep' ] : $local_cache[ 'def_title_sep' ];
205
206 if ( 0 === strpos( $varname, 'post' ) ) { // The inline variable includes 'post' in its name.
207
208 if ( $mod[ 'is_post' ] ) { // Just in case.
209
210 switch ( $varname ) {
211
212 case 'post_date':
213
214 if ( ! empty( $mod[ 'post_time' ] ) ) {
215
216 $ret_val = mysql2date( $local_cache[ 'date_format' ], $mod[ 'post_time' ] );
217 }
218
219 break;
220
221 case 'post_description': // Used by AIOSEOP.
222
223 $ret_val = $this->p->page->get_the_description( $mod );
224
225 break;
226
227 case 'post_modified':
228 case 'post_modified_date':
229
230 if ( ! empty( $mod[ 'post_modified_time' ] ) ) {
231
232 $ret_val = mysql2date( $local_cache[ 'date_format' ], $mod[ 'post_modified_time' ] );
233 }
234
235 break;
236
237 case 'post_primary_tax_slug':
238
239 $ret_val = $mod[ 'post_primary_tax_slug' ];
240
241 break;
242
243 case 'post_title': // Used by AIOSEOP.
244
245 $ret_val = $this->p->page->get_the_title( $mod, $title_sep );
246
247 break;
248 }
249 }
250
251 } elseif ( 0 === strpos( $varname, 'term' ) ) { // The inline variable includes 'term' in its name.
252
253 if ( $mod[ 'is_term' ] ) { // Just in case.
254
255 switch ( $varname ) {
256
257 case 'term':
258 case 'term_name':
259
260 $term_obj = $this->p->term->get_mod_wp_object( $mod );
261
262 $ret_val = $term_obj->name;
263
264 break;
265
266 case 'term_description': // Used by AIOSEOP, Rank Math, and Yoast SEO.
267
268 $ret_val = $this->p->page->get_the_description( $mod );
269
270 break;
271
272 case 'term_tax_single':
273
274 $ret_val = $mod[ 'tax_label_single' ];
275
276 break;
277
278 case 'term_tax_single_lower':
279
280 $ret_val = mb_strtolower( $mod[ 'tax_label_single' ] );
281
282 break;
283
284 case 'term_hierarchy': // Used by Yoast SEO.
285
286 /*
287 * Includes parent names in the term title if the $title_sep value is not empty.
288 *
289 * Use $title_sep = false to avoid adding term parent names in the term title.
290 */
291 $term_obj = $this->p->term->get_mod_wp_object( $mod );
292
293 $ret_val = $this->p->page->get_term_title( $term_obj, null );
294
295 break;
296
297 case 'term_title': // Used by Yoast SEO.
298
299 /*
300 * Includes parent names in the term title if the $title_sep value is not empty.
301 *
302 * Use $title_sep = false to avoid adding term parent names in the term title.
303 */
304 $term_obj = $this->p->term->get_mod_wp_object( $mod );
305
306 $ret_val = $this->p->page->get_term_title( $term_obj, false );
307
308 break;
309 }
310 }
311
312 } elseif ( 0 === strpos( $varname, 'cf_' ) ) { // The inline variable includes 'cf_' in its name.
313
314 if ( $meta_key = substr( $varname, 3 ) ) { // Just in case.
315
316 if ( ! empty( $mod[ 'obj' ] ) && $mod[ 'id' ] ) { // Just in case.
317
318 $ret_val = $mod[ 'obj' ]->get_meta( $mod[ 'id' ], $meta_key, $single = true );
319
320 if ( is_array( $ret_val ) ) { // Just in case.
321
322 $ret_val = implode( $glue = ', ', $ret_val );
323 }
324 }
325 }
326
327 } else {
328
329 switch ( $varname ) {
330
331 case 'org_url': // Used by Rank Math.
332 case 'site_url':
333
334 $ret_val = SucomUtilWP::get_home_url( $this->p->options, $mod );
335
336 break;
337
338 case 'canonical_url':
339
340 $ret_val = $this->u->get_canonical_url( $mod, $add_page );
341
342 break;
343
344 case 'canonical_short_url':
345
346 $ret_val = $this->u->get_canonical_short_url( $mod, $add_page );
347
348 break;
349
350 case 'description':
351 case 'seo_description': // Used by Rank Math.
352
353 $ret_val = $this->p->page->get_the_description( $mod );
354
355 break;
356
357 case 'user_description': // Used by Rank Math.
358
359 /*
360 * Returns the description for a user module or post author.
361 */
362 $ret_val = $this->p->user->get_author_description( $mod );
363
364 break;
365
366 case 'sharing_url':
367
368 /*
369 * The $atts array may contain 'utm_medium', 'utm_source', 'utm_campaign', 'utm_content', and 'utm_term'.
370 */
371 $ret_val = $this->u->get_sharing_url( $mod, $add_page, $atts );
372
373 break;
374
375 case 'sharing_short_url':
376 case 'short_url': // Used by older WPSSO RRSSB templates.
377
378 /*
379 * The $atts array may contain 'utm_medium', 'utm_source', 'utm_campaign', 'utm_content', and 'utm_term'.
380 */
381 $ret_val = $this->u->get_sharing_short_url( $mod, $add_page, $atts );
382
383 break;
384
385 case 'request_url':
386
387 if ( is_admin() ) {
388
389 $ret_val = $this->u->get_canonical_url( $mod, $add_page );
390
391 } else {
392
393 $ret_val = SucomUtil::get_url( $remove_ignored_args = true ); // Uses a local cache.
394
395 $ret_val = apply_filters( 'wpsso_server_request_url', $ret_val );
396 }
397
398 break;
399
400 case 'org_name': // Used by Rank Math.
401 case 'sitename':
402 case 'sitetitle': // Used by SEOPress.
403
404 $ret_val = SucomUtilWP::get_site_name( $this->p->options, $mod );
405
406 break;
407
408 case 'sitealtname':
409
410 $ret_val = SucomUtilWP::get_site_name_alt( $this->p->options, $mod );
411
412 break;
413
414 case 'sitedesc': // Used by Rank Math.
415 case 'tagline': // Used by SEOPress.
416
417 $ret_val = SucomUtilWP::get_site_description( $this->p->options, $mod );
418
419 break;
420
421 case 'sep':
422 case 'separator_sa': // Used by AIOSEOP.
423
424 $ret_val = $title_sep;
425
426 break;
427
428 case 'ellipsis':
429
430 $ret_val = $local_cache[ 'def_ellipsis' ];
431
432 break;
433
434 case 'title':
435 case 'seo_title': // Used by Rank Math.
436
437 $ret_val = $this->p->page->get_the_title( $mod, $title_sep );
438
439 break;
440
441 case 'parent_title':
442
443 if ( $mod[ 'is_post' ] && $mod[ 'post_parent' ] ) { // Just in case.
444
445 $parent_mod = $this->p->post->get_mod( $mod[ 'post_parent' ] );
446
447 $ret_val = $this->p->page->get_the_title( $parent_mod, $title_sep );
448 }
449
450 break;
451
452 case 'author':
453 case 'author_name':
454 case 'name': // Used by Yoast SEO.
455
456 /*
457 * Returns the display name for a user module, comment author, or post author.
458 */
459 $ret_val = $this->p->user->get_author_name( $mod );
460
461 break;
462
463 case 'page':
464
465 $page_num = $this->u->get_page_number( $mod, $add_page );
466
467 if ( $page_num > 1 ) {
468
469 $page_transl = __( 'Page %1$d of %2$d', 'wpsso' );
470
471 $ret_val = $title_sep . ' ' . sprintf( $page_transl, $page_num, $mod[ 'paged_total' ] );
472 }
473
474 break;
475
476 case 'pagename':
477
478 if ( isset( $mod[ 'query_vars' ][ 'pagename' ] ) ) {
479
480 $ret_val = $mod[ 'query_vars' ][ 'pagename' ];
481 }
482
483 break;
484
485 case 'pagenumber':
486
487 $ret_val = $this->u->get_page_number( $mod, $add_page );
488
489 break;
490
491 case 'pagetotal':
492
493 $ret_val = $mod[ 'paged_total' ];
494
495 break;
496
497 case 'date': // Used by Yoast SEO.
498
499 if ( ! empty( $mod[ 'post_time' ] ) ) {
500
501 $ret_val = mysql2date( $local_cache[ 'date_format' ], $mod[ 'post_time' ] );
502 }
503
504 break;
505
506 case 'modified': // Used by Yoast SEO.
507
508 if ( ! empty( $mod[ 'post_modified_time' ] ) ) {
509
510 $ret_val = mysql2date( $local_cache[ 'date_format' ], $mod[ 'post_modified_time' ] );
511 }
512
513 break;
514
515 case 'excerpt':
516
517 if ( $mod[ 'is_post' ] ) { // Just in case.
518
519 $ret_val = $this->p->page->get_the_excerpt( $mod );
520
521 if ( empty( $ret_val ) ) {
522
523 $ret_val = wp_trim_excerpt( '', $mod[ 'id' ] );
524 }
525 }
526
527 break;
528
529 case 'excerpt_only':
530
531 if ( $mod[ 'is_post' ] ) { // Just in case.
532
533 $ret_val = $this->p->page->get_the_excerpt( $mod );
534 }
535
536 break;
537
538 case 'comment_author':
539
540 $ret_val = $mod[ 'comment_author_name' ];
541
542 break;
543
544 case 'comment_date':
545
546 if ( ! empty( $mod[ 'comment_time' ] ) ) {
547
548 $ret_val = mysql2date( $local_cache[ 'date_format' ], $mod[ 'comment_time' ] );
549 }
550
551 break;
552
553 case 'query_search':
554 case 'search_keywords': // Used by SEOPress.
555 case 'search_query': // Used by Rank Math.
556 case 'searchphrase': // Used by Yoast SEO.
557
558 if ( isset( $mod[ 'query_vars' ][ 's' ] ) ) {
559
560 $ret_val = $mod[ 'query_vars' ][ 's' ];
561 }
562
563 break;
564
565 case 'query_year':
566
567 if ( isset( $mod[ 'query_vars' ][ 'year' ] ) ) {
568
569 $ret_val = $mod[ 'query_vars' ][ 'year' ];
570
571 } elseif ( ! empty( $mod[ 'query_vars' ][ 'm' ] ) ) {
572
573 $ret_val = substr( $mod[ 'query_vars' ][ 'm' ], 0, 4 );
574 }
575
576 break;
577
578 case 'query_month':
579 case 'query_monthnum':
580
581 if ( isset( $mod[ 'query_vars' ][ 'monthnum' ] ) ) {
582
583 $ret_val = $mod[ 'query_vars' ][ 'monthnum' ];
584
585 } elseif ( ! empty( $mod[ 'query_vars' ][ 'm' ] ) ) {
586
587 $ret_val = substr( $mod[ 'query_vars' ][ 'm' ], 4, 2 );
588 }
589
590 if ( 'query_month' === $varname ) { // Convert month number to month name.
591
592 global $wp_locale;
593
594 $ret_val = $ret_val ? $wp_locale->get_month( $ret_val ) : '';
595 }
596
597 break;
598
599 case 'query_day':
600
601 if ( isset( $mod[ 'query_vars' ][ 'day' ] ) ) {
602
603 $ret_val = $mod[ 'query_vars' ][ 'day' ];
604 }
605
606 break;
607 }
608 }
609
610 unset( $local_recursion[ $varname ] ); // Done preventing recursion.
611
612 return $url_enc ? rawurlencode( $ret_val ) : $ret_val;
613 }
614 }
615 }
616