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 / options.php

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

2,108 lines 59.7 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( 'WpssoOptions' ) ) {
19
20 class WpssoOptions {
21
22 private $p; // Wpsso class object.
23 private $upgrade; // WpssoUpgrade class object.
24 private $filters; // WpssoOptionsFilters class object.
25
26 private static $cache_allowed = false;
27
28 /*
29 * Instantiated by Wpsso->set_objects().
30 */
31 public function __construct( &$plugin ) {
32
33 $this->p =& $plugin;
34
35 if ( $this->p->debug->enabled ) {
36
37 $this->p->debug->mark();
38 }
39
40 require_once WPSSO_PLUGINDIR . 'lib/options-filters.php';
41
42 $this->filters = new WpssoOptionsFilters( $plugin );
43
44 $this->p->util->add_plugin_actions( $this, array(
45 'init_objects' => 0,
46 ), $prio = 1000 );
47 }
48
49 /*
50 * This action is called by Wpsso->set_objects() to initialize additional class objects.
51 */
52 public function action_init_objects() {
53
54 if ( $this->p->debug->enabled ) {
55
56 $this->p->debug->log( 'setting cache_allowed to true' );
57 }
58
59 self::$cache_allowed = true;
60 }
61
62 public static function is_cache_allowed() {
63
64 return self::$cache_allowed;
65 }
66
67 public function get_defaults( $opt_key = false, $force_filter = false ) {
68
69 if ( $this->p->debug->enabled ) {
70
71 $this->p->debug->log_args( array(
72 'opt_key' => $opt_key,
73 'force_filter' => $force_filter,
74 ) );
75 }
76
77 static $local_cache = array();
78
79 $is_cache_allowed = self::is_cache_allowed();
80
81 if ( empty( $local_cache ) || ! $is_cache_allowed ) {
82
83 $local_cache = $this->p->cf[ 'opt' ][ 'defaults' ];
84 }
85
86 if ( $force_filter || empty( $local_cache[ 'opt_filtered' ] ) ) {
87
88 if ( $this->p->debug->enabled ) {
89
90 $this->p->debug->mark( 'get_defaults filters' ); // Begin timer.
91 }
92
93 /*
94 * Set before calling filters to prevent recursion.
95 */
96 if ( $this->p->debug->enabled ) {
97
98 $this->p->debug->log( 'setting opt_filtered to 1' );
99 }
100
101 $local_cache[ 'opt_filtered' ] = 1;
102
103 /*
104 * If there is a plugin auth method configured, make sure the option key exists.
105 */
106 foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
107
108 if ( ! empty( $info[ 'update_auth' ] ) && 'none' !== $info[ 'update_auth' ] ) { // Just in case.
109
110 $local_cache[ 'plugin_' . $ext . '_' . $info[ 'update_auth' ] ] = '';
111 }
112 }
113
114 /*
115 * Complete the options array for custom post types and taxonomies.
116 */
117 $this->add_custom_post_tax_options( $local_cache );
118
119 /*
120 * Define the default organization or person ID for Knowledge Graph markup in the home page.
121 */
122 if ( isset( $this->p->options[ 'site_pub_schema_type' ] ) ) {
123
124 switch ( $this->p->options[ 'site_pub_schema_type' ] ) {
125
126 case 'person':
127
128 $local_cache[ 'schema_def_pub_org_id' ] = 'none';
129 $local_cache[ 'schema_def_pub_person_id' ] = $this->p->options[ 'site_pub_person_id' ];
130
131 break;
132
133 case 'organization':
134
135 $local_cache[ 'schema_def_pub_org_id' ] = 'site';
136 $local_cache[ 'schema_def_pub_person_id' ] = 'none';
137
138 break;
139 }
140 }
141
142 /*
143 * Update default place options based on the open graph defaults.
144 */
145 if ( isset( $this->p->options[ 'og_def_country' ] ) ) $local_cache[ 'schema_def_place_country' ] = $this->p->options[ 'og_def_country' ];
146 if ( isset( $this->p->options[ 'og_def_timezone' ] ) ) $local_cache[ 'schema_def_place_timezone' ] = $this->p->options[ 'og_def_timezone' ];
147
148 /*
149 * Get translated strings for variable based options.
150 */
151 $this->set_default_text( $local_cache, 'plugin_title_part_site' ); // Title Tag Site Prefix / Suffix.
152 $this->set_default_text( $local_cache, 'plugin_title_part_tagline' ); // Title Tag Tagline Prefix / Suffix.
153 $this->set_default_text( $local_cache, 'plugin_img_alt_prefix' ); // Content Image Alt Prefix.
154 $this->set_default_text( $local_cache, 'plugin_p_cap_prefix' ); // WP Caption Text Prefix.
155 $this->set_default_text( $local_cache, 'plugin_comment_title' ); // Comment Title.
156 $this->set_default_text( $local_cache, 'plugin_comment_reply_title' ); // Reply Comment Title.
157 $this->set_default_text( $local_cache, 'plugin_comment_review_title' ); // Review Comment Title.
158 $this->set_default_text( $local_cache, 'plugin_product_var_title' ); // Product Variation Title.
159 $this->set_default_text( $local_cache, 'plugin_feed_title' ); // RSS Feed Title.
160 $this->set_default_text( $local_cache, 'plugin_404_page_title' ); // 404 Page Title.
161 $this->set_default_text( $local_cache, 'plugin_404_page_desc' ); // 404 Page Description.
162 $this->set_default_text( $local_cache, 'plugin_no_title_text' ); // No Title Text.
163 $this->set_default_text( $local_cache, 'plugin_no_desc_text' ); // No Description Text.
164 $this->set_default_text( $local_cache, 'plugin_term_page_title' ); // Term Archive Title.
165 $this->set_default_text( $local_cache, 'plugin_term_page_desc' ); // Term Archive Description.
166 $this->set_default_text( $local_cache, 'plugin_author_page_title' ); // Author Archive Title.
167 $this->set_default_text( $local_cache, 'plugin_author_page_desc' ); // Author Archive Description.
168 $this->set_default_text( $local_cache, 'plugin_search_page_title' ); // Search Results Title.
169 $this->set_default_text( $local_cache, 'plugin_search_page_desc' ); // Search Results Description.
170 $this->set_default_text( $local_cache, 'plugin_year_page_title' ); // Year Archive Title.
171 $this->set_default_text( $local_cache, 'plugin_year_page_desc' ); // Year Archive Description.
172 $this->set_default_text( $local_cache, 'plugin_month_page_title' ); // Month Archive Title.
173 $this->set_default_text( $local_cache, 'plugin_month_page_desc' ); // Month Archive Description.
174 $this->set_default_text( $local_cache, 'plugin_day_page_title' ); // Day Archive Title.
175 $this->set_default_text( $local_cache, 'plugin_day_page_desc' ); // Day Archive Description.
176
177 /*
178 * Translate contact method field labels for current language.
179 */
180 if ( $this->p->debug->enabled ) {
181
182 $this->p->debug->log( 'translating plugin contact field labels' );
183 }
184
185 SucomUtilOptions::transl_key_values( '/^plugin_(cm_.*_label|.*_prefix)$/', $local_cache, 'wpsso' );
186
187 /*
188 * Define the default Facebook locale and current locale values.
189 */
190 if ( $this->p->debug->enabled ) {
191
192 $this->p->debug->log( 'calling get_fb_locale() for default' );
193 }
194
195 $local_cache[ 'fb_locale' ] = $this->p->og->get_fb_locale( $mixed = 'default', $use_opts = false );
196
197 $current_fb_locale_key = SucomUtilOptions::get_key_locale( 'fb_locale' );
198
199 if ( 'fb_locale' !== $current_fb_locale_key ) {
200
201 if ( $this->p->debug->enabled ) {
202
203 $this->p->debug->log( 'calling get_fb_locale() for current' );
204 }
205
206 $local_cache[ $current_fb_locale_key ] = $this->p->og->get_fb_locale( $mixed = 'current', $use_opts = false );
207 }
208
209 /*
210 * Check to see if we have a full webpage cache plugin or service active.
211 */
212 if ( ! empty( $this->p->avail[ 'cache' ][ 'any' ] ) ) {
213
214 $local_cache[ 'plugin_page_cache_active' ] = 1;
215 }
216
217 /*
218 * Import metadata and block attributes from known SEO plugins.
219 */
220 foreach ( array(
221 'aioseop' => 'aioseo_options', // All in One SEO Pack.
222 'rankmath' => 'rank-math-options-general', // Rank Math SEO.
223 'seoframework' => 'autodescription-site-settings', // The SEO Framework.
224 'wpmetaseo' => 'wpmetaseo', // WP Meta SEO.
225 'wpseo' => 'wpseo', // Yoast SEO.
226 ) as $avail_key => $seo_option_key ) {
227
228 if ( ! empty( $this->p->avail[ 'seo' ][ $avail_key ] ) ||
229 ( empty( $this->p->avail[ 'seo' ][ 'any' ] ) && get_option( $seo_option_key ) ) ) {
230
231 foreach ( array( 'meta', 'blocks' ) as $import_type ) {
232
233 /*
234 * Option key examples:
235 *
236 * 'plugin_import_aioseop_meta'
237 * 'plugin_import_rankmath_meta'
238 * 'plugin_import_seoframework_meta'
239 * 'plugin_import_wpmetaseo_meta'
240 * 'plugin_import_wpseo_meta'
241 * 'plugin_import_wpseo_blocks'
242 */
243 $key = 'plugin_import_' . $avail_key . '_' . $import_type;
244
245 if ( isset( $local_cache[ $key ] ) ) { // Make sure the option exists.
246
247 $local_cache[ $key ] = 1;
248 }
249 }
250 }
251 }
252
253 /*
254 * Check for website verification IDs and enable/disable meta tags as required.
255 */
256 foreach ( WpssoConfig::$cf[ 'opt' ][ 'site_verify_meta_names' ] as $site_verify => $meta_name ) {
257
258 $fixed[ 'add_meta_name_' . $meta_name ] = empty( $opts[ $site_verify ] ) ? 0 : 1;
259 }
260
261 /*
262 * Check for default values from network admin settings.
263 */
264 if ( is_multisite() && is_array( $this->p->site_options ) ) {
265
266 foreach ( $this->p->site_options as $site_opt_key => $site_opt_val ) {
267
268 if ( isset( $local_cache[ $site_opt_key ] ) && isset( $this->p->site_options[ $site_opt_key . ':use' ] ) ) {
269
270 if ( 'default' === $this->p->site_options[ $site_opt_key . ':use' ] ) {
271
272 $local_cache[ $site_opt_key ] = $this->p->site_options[ $site_opt_key ];
273 }
274 }
275 }
276 }
277
278 if ( $this->p->debug->enabled ) {
279
280 $this->p->debug->log( 'applying filters "wpsso_get_defaults"' );
281 }
282
283 $local_cache = apply_filters( 'wpsso_get_defaults', $local_cache );
284
285 if ( ! $is_cache_allowed ) {
286
287 unset( $local_cache[ 'opt_filtered' ] );
288 }
289
290 if ( $this->p->debug->enabled ) {
291
292 $this->p->debug->mark( 'get_defaults filters' ); // End timer.
293 }
294
295 } elseif ( $this->p->debug->enabled ) {
296
297 $this->p->debug->log( 'skipped filters: opt_filtered is true' );
298 }
299
300 if ( false !== $opt_key ) {
301
302 if ( isset( $local_cache[ $opt_key ] ) ) {
303
304 return $local_cache[ $opt_key ];
305 }
306
307 return null;
308 }
309
310 return $local_cache;
311 }
312
313 public function get_site_defaults( $opt_key = false, $force_filter = false ) {
314
315 if ( $this->p->debug->enabled ) {
316
317 $this->p->debug->log_args( array(
318 'opt_key' => $opt_key,
319 'force_filter' => $force_filter,
320 ) );
321 }
322
323 static $local_cache = array();
324
325 $is_cache_allowed = self::is_cache_allowed();
326
327 if ( empty( $local_cache ) || ! $is_cache_allowed ) {
328
329 /*
330 * Automatically include all advanced plugin options.
331 */
332 $local_cache = SucomUtil::preg_grep_keys( '/^plugin_/', $this->p->cf[ 'opt' ][ 'defaults' ] );
333
334 /*
335 * Add a "Site Use" for each option.
336 */
337 foreach ( $local_cache as $key => $val ) {
338
339 if ( false === strpos( $key, ':' ) ) { // Just in case.
340
341 $local_cache[ $key . ':use' ] = 'default';
342 }
343 }
344
345 $local_cache = array_merge( $local_cache, $this->p->cf[ 'opt' ][ 'site_defaults' ] );
346 }
347
348 if ( $force_filter || empty( $local_cache[ 'opt_filtered' ] ) ) {
349
350 if ( $this->p->debug->enabled ) {
351
352 $this->p->debug->mark( 'get_site_defaults filters' ); // Begin timer.
353 }
354
355 /*
356 * Set before calling filters to prevent recursion.
357 */
358 if ( $this->p->debug->enabled ) {
359
360 $this->p->debug->log( 'setting opt_filtered to 1' );
361 }
362
363 $local_cache[ 'opt_filtered' ] = 1;
364
365 /*
366 * If there is a plugin auth method configured, make sure the option key exists.
367 */
368 foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
369
370 if ( ! empty( $info[ 'update_auth' ] ) && 'none' !== $info[ 'update_auth' ] ) { // Just in case.
371
372 $local_cache[ 'plugin_' . $ext . '_' . $info[ 'update_auth' ] ] = '';
373
374 $local_cache[ 'plugin_' . $ext . '_' . $info[ 'update_auth' ] . ':use' ] = 'default';
375 }
376 }
377
378 if ( $this->p->debug->enabled ) {
379
380 $this->p->debug->log( 'applying filters "wpsso_get_site_defaults"' );
381 }
382
383 $local_cache = apply_filters( 'wpsso_get_site_defaults', $local_cache );
384
385 if ( ! $is_cache_allowed ) {
386
387 unset( $local_cache[ 'opt_filtered' ] );
388 }
389
390 if ( $this->p->debug->enabled ) {
391
392 $this->p->debug->mark( 'get_site_defaults filters' ); // End timer.
393 }
394 }
395
396 if ( false !== $opt_key ) {
397
398 if ( isset( $local_cache[ $opt_key ] ) ) {
399
400 return $local_cache[ $opt_key ];
401 }
402
403 return null;
404 }
405
406 return $local_cache;
407 }
408
409 /*
410 * Returns a checked, fixed, and/or upgraded options array.
411 *
412 * See WpssoAdmin->init_check_options().
413 * See WpssoAdmin->import_plugin_settings_json().
414 */
415 public function check_options( $options_name, array $opts, $network = false ) {
416
417 if ( $this->p->debug->enabled ) {
418
419 $this->p->debug->mark( 'checking options' ); // Begin timer.
420 }
421
422 $defs = null; // Optimize and only get the defaults array when needed.
423 $fixed = array();
424 $save_changes = false;
425 $is_plugin_upg = $this->is_plugin_upgrading( $opts ); // Existing plugin versions have changed.
426 $is_option_upg = $this->is_upgrade_required( $opts ); // Existing option versions have changed.
427
428 /*
429 * Upgrade the options array if necessary (rename or remove keys).
430 */
431 if ( $is_option_upg ) {
432
433 if ( $this->p->debug->enabled ) {
434
435 $this->p->debug->log( 'upgrading ' . $options_name . ' options' );
436 }
437
438 if ( ! is_object( $this->upgrade ) ) {
439
440 require_once WPSSO_PLUGINDIR . 'lib/upgrade.php';
441
442 $this->upgrade = new WpssoUpgrade( $this->p );
443 }
444
445 $defs = $network ? $this->get_site_defaults() : $this->get_defaults();
446
447 $opts = $this->upgrade->options( $options_name, $opts, $defs, $network );
448 }
449
450 /*
451 * Complete the options array for any custom post types and/or custom taxonomies.
452 */
453 $this->add_custom_post_tax_options( $opts );
454
455 /*
456 * Note that generator meta tags are required for plugin support.
457 *
458 * If you disable the generator meta tags, requests for plugin support will be denied.
459 */
460 $fixed[ 'add_meta_name_generator' ] = SucomUtil::get_const( 'WPSSO_META_GENERATOR_DISABLE' ) ? 0 : 1;
461
462 /*
463 * Google does not recognize all Schema Organization sub-types as valid organization and publisher types.
464 * The site organization type ID should be "organization" unless you are confident that Google will
465 * recognize your preferred Schema Organization sub-type as a valid organization. To select a different
466 * organization type ID for your site, define the WPSSO_SCHEMA_ORGANIZATION_TYPE_ID constant with your
467 * preferred type ID (not the Schema type URL).
468 */
469 $site_org_type_id = SucomUtil::get_const( 'WPSSO_SCHEMA_ORGANIZATION_TYPE_ID', 'organization' );
470
471 if ( ! preg_match( '/^[a-z\.]+$/', $site_org_type_id ) ) { // Quick sanitation to allow only valid IDs.
472
473 $site_org_type_id = 'organization';
474 }
475
476 $fixed[ 'site_org_schema_type' ] = $site_org_type_id;
477
478 /*
479 * Include VAT in Product Prices.
480 *
481 * Allow the WPSSO_PRODUCT_PRICE_INCLUDE_VAT constant to override the 'plugin_product_include_vat' value.
482 */
483 if ( defined( 'WPSSO_PRODUCT_PRICE_INCLUDE_VAT' ) ) {
484
485 $fixed[ 'plugin_product_include_vat' ] = WPSSO_PRODUCT_PRICE_INCLUDE_VAT ? 1 : 0;
486 }
487
488 /*
489 * Adjust / cleanup non-network options.
490 */
491 if ( ! $network ) {
492
493 /*
494 * Adjust SEO options.
495 */
496 if ( empty( $this->p->avail[ 'seo' ][ 'any' ] ) ) { // No SEO plugin active.
497
498 if ( empty( $opts[ 'plugin_wpsso_tid' ] ) ) {
499
500 $fixed[ 'add_link_rel_canonical' ] = 1;
501 $fixed[ 'add_meta_name_description' ] = 1;
502 $fixed[ 'add_meta_name_robots' ] = 1;
503 $fixed[ 'plugin_title_tag' ] = 'seo_title';
504 }
505
506 } else { // An SEO plugin is active.
507
508 $fixed[ 'add_link_rel_canonical' ] = 0;
509 $fixed[ 'add_meta_name_description' ] = 0;
510 $fixed[ 'add_meta_name_robots' ] = 0;
511 $fixed[ 'plugin_title_tag' ] = 'wp_title';
512
513 foreach ( array(
514 'aioseop', // All in One SEO Pack.
515 'rankmath', // Rank Math SEO.
516 'seoframework', // The SEO Framework.
517 'wpseo', // Yoast SEO.
518 ) as $avail_key ) {
519
520 /*
521 * Disable the metadata import of all others (ie. non-active SEO plugins).
522 */
523 if ( empty( $this->p->avail[ 'seo' ][ $avail_key ] ) ) {
524
525 foreach ( array( 'meta', 'blocks' ) as $import_type ) {
526
527 $key = 'plugin_import_' . $avail_key . '_' . $import_type;
528
529 if ( isset( $opts[ $key ] ) ) { // Make sure the option exists.
530
531 $fixed[ $key ] = 0;
532 }
533 }
534 }
535 }
536 }
537
538 /*
539 * Fixed value / unchangeable options.
540 */
541 foreach ( array( 'og:image', 'og:video' ) as $mt_name ) {
542
543 $fixed[ 'add_meta_property_' . $mt_name . ':secure_url' ] = 0; // Always unchecked.
544 $fixed[ 'add_meta_property_' . $mt_name . ':url' ] = 0; // Always unchecked.
545 $fixed[ 'add_meta_property_' . $mt_name ] = 1; // Always checked (canonical URL).
546 }
547
548 /*
549 * Check for website verification IDs and enable/disable meta tags as required.
550 */
551 foreach ( WpssoConfig::$cf[ 'opt' ][ 'site_verify_meta_names' ] as $site_verify => $meta_name ) {
552
553 $fixed[ 'add_meta_name_' . $meta_name ] = empty( $opts[ $site_verify ] ) ? 0 : 1;
554 }
555
556 /*
557 * Check for invalid update transaction status.
558 */
559 if ( class_exists( 'WpssoUmConfig' ) ) {
560
561 foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
562
563 $ext_auth_type = $this->p->check->get_ext_auth_type( $ext );
564 $ext_auth_key = 'plugin_' . $ext . '_' . $ext_auth_type; // Options key for authentication ID.
565 $ext_filter_key = 'update_filter_for_' . $ext; // Options key for version filter.
566
567 if ( ! empty( $opts[ $ext_auth_key ] ) ) {
568
569 if ( $txn_status = SucomUpdate::get_option( $ext, 'txn_status' ) ) {
570
571 switch ( $txn_status ) {
572
573 case 'Completed':
574 case 'Updates':
575
576 break; // Nothing to do.
577
578 default: // Invalid status.
579
580 $opts[ $ext_auth_key ] = '';
581 $opts[ $ext_filter_key ] = 'stable';
582
583 $save_changes = true; // Save the options.
584
585 break;
586 }
587 }
588 }
589 }
590 }
591
592 /*
593 * Check for incompatible option values between plugin editions.
594 */
595 if ( empty( $opts[ 'plugin_wpsso_tid' ] ) ) {
596
597 if ( null === $defs ) { // Optimize and only get the defaults array when needed.
598
599 $defs = $network ? $this->get_site_defaults() : $this->get_defaults();
600 }
601
602 $adv_incl = array(
603 'add_.*',
604 'og_type_for_.*',
605 'og_vid_.*',
606 'plugin_.*',
607 'schema_def_.*',
608 'schema_type_for_.*',
609 '.*_img_(width|height|crop|crop_x|crop_y)',
610 );
611
612 $adv_excl = apply_filters( 'wpsso_plugin_upgrade_advanced_exclude', array(
613 'plugin_clean_on_uninstall',
614 'plugin_schema_json_min',
615 'plugin_load_mofiles',
616 'plugin_cache_disable',
617 'plugin_debug_html',
618 'plugin_.*_tid',
619 ) );
620
621 $adv_check = SucomUtil::preg_grep_keys( '/^(' . implode( '|', $adv_incl ) . ')$/', $defs );
622 $adv_check = SucomUtil::preg_grep_keys( '/^(' . implode( '|', $adv_excl ) . ')$/', $adv_check, $invert = true );
623
624 foreach ( $fixed as $key => $val ) {
625
626 unset( $adv_check[ $key ] );
627 }
628
629 foreach ( $adv_check as $key => $val ) {
630
631 if ( ! isset( $opts[ $key ] ) || $opts[ $key ] !== $val ) {
632
633 $opts[ $key ] = $val;
634
635 $save_changes = true; // Save the options.
636 }
637 }
638 }
639 }
640
641 /*
642 * Check if options need to be changed and saved.
643 *
644 * Disable these options as they would get changed back anyway.
645 */
646 foreach ( $fixed as $key => $val ) {
647
648 $opts[ $key . ':disabled' ] = true;
649
650 if ( ! isset( $opts[ $key ] ) || $opts[ $key ] !== $val ) { // Check for changes.
651
652 $opts[ $key ] = $val; // Update the option value.
653
654 $save_changes = true; // Save the options.
655 }
656 }
657
658 /*
659 * Save options and show reminders.
660 */
661 if ( $save_changes || $is_plugin_upg || $is_option_upg ) {
662
663 $this->save_options( $options_name, $opts, $network );
664 }
665
666 if ( $this->p->debug->enabled ) {
667
668 $this->p->debug->mark( 'checking options' ); // End timer.
669 }
670
671 return $opts;
672 }
673
674 /*
675 * Sanitize and validate options, including both the plugin options and custom meta options arrays.
676 *
677 * Called by WpssoAdmin->settings_sanitation().
678 * Called by WpssoAdmin->save_site_settings().
679 * Called by WpssoAbstractWpMeta->get_submit_opts().
680 */
681 public function sanitize( array $opts, $defs = array(), $network = false, $mod = false ) {
682
683 if ( $this->p->debug->enabled ) {
684
685 $this->p->debug->mark();
686 }
687
688 /*
689 * Add any missing options from the defaults, unless sanitizing for a module, in which case we do not
690 * complete the options array.
691 */
692 if ( empty( $mod[ 'name' ] ) ) {
693
694 if ( ! empty( $defs ) && is_array( $defs ) ) { // Just in case.
695
696 $opts = array_merge( $defs, $opts ); // Complete the array with default options.
697 }
698 }
699
700 /*
701 * Sort the options to re-order 0, 1, 10, 2 suffixes as 0, 1, 2, 10.
702 */
703 ksort( $opts, SORT_FLAG_CASE | SORT_NATURAL );
704
705 /*
706 * Sanitize values.
707 */
708 unset( $opts[ 'opt_filtered' ] ); // Just in case.
709
710 foreach ( $opts as $opt_key => $opt_val ) {
711
712 if ( empty( $opt_key ) ) { // Just in case.
713
714 continue;
715
716 /*
717 * Maybe save the disabled option, but don't save the ':disabled' qualifier.
718 */
719 } elseif ( false !== strpos( $opt_key, ':disabled' ) ) {
720
721 unset( $opts[ $opt_key ] );
722
723 continue;
724
725 /*
726 * Ignore all other controller qualifiers (ie. ':use', ':width', ':height', etc.).
727 */
728 } elseif ( strpos( $opt_key, ':' ) ) {
729
730 continue;
731
732 /*
733 * Ignore localized options with an empty string value and no default.
734 */
735 } elseif ( strpos( $opt_key, '#' ) && ! isset( $defs[ $opt_key ] ) && '' === $opt_val ) {
736
737 unset( $opts[ $opt_key ] );
738
739 continue;
740 }
741
742 /*
743 * Match the base option name without option numbers and localization.
744 */
745 $base_key = preg_replace( '/(_[0-9]+)?([#].*)?$/', '', $opt_key );
746
747 /*
748 * Multi-options and localized options default to an empty string.
749 */
750 $def_val = isset( $defs[ $opt_key ] ) ? $defs[ $opt_key ] : '';
751
752 $opts[ $opt_key ] = $this->check_value( $opt_key, $base_key, $opt_val, $def_val, $network, $mod );
753 }
754
755 /*
756 * Adjust Dependent Options
757 *
758 * All options (site and meta as well) are sanitized here, so always use isset() or array_key_exists() on
759 * all tests to make sure additional / unnecessary options are not created in post meta.
760 */
761 $opt_prefixes = SucomUtil::preg_grep_keys( '/^(.*)_img_width$/', $opts, $invert = false, $replace = '$1' );
762
763 foreach ( $opt_prefixes as $opt_pre => $img_width ) {
764
765 if ( ! isset( $opts[ $opt_pre . '_img_height' ] ) ) { // Just in case;
766
767 continue;
768 }
769
770 $img_height = $opts[ $opt_pre . '_img_height' ];
771 $img_crop = isset( $opts[ $opt_pre . '_img_crop' ] ) ? $opts[ $opt_pre . '_img_crop' ] : 0;
772
773 /*
774 * If sanitizing for a module, load any missing width / height values.
775 */
776 if ( false !== $mod ) {
777
778 if ( empty( $img_width ) && isset( $this->p->options[ $opt_pre . '_img_width' ] ) ) {
779
780 $img_width = $this->p->options[ $opt_pre . '_img_width' ];
781 }
782
783 if ( empty( $img_height ) && isset( $this->p->options[ $opt_pre . '_img_height' ] ) ) {
784
785 $img_height = $this->p->options[ $opt_pre . '_img_height' ];
786 }
787 }
788
789 /*
790 * Both width and height are required to calculate and check the aspect ratio.
791 */
792 if ( empty( $img_width ) || empty( $img_height ) ) {
793
794 continue;
795 }
796
797 $img_ratio = $img_width >= $img_height ? $img_width / $img_height : $img_height / $img_width;
798 $img_ratio = number_format( $img_ratio, 3, '.', '' );
799
800 foreach ( array( 'limit', 'limit_max' ) as $limit_type ) {
801
802 if ( ! isset( $this->p->cf[ 'head' ][ $limit_type ][ $opt_pre . '_img_ratio' ] ) ) {
803
804 continue;
805 }
806
807 $notice_msg = false;
808 $limit_ratio = number_format( $this->p->cf[ 'head' ][ $limit_type ][ $opt_pre . '_img_ratio' ], 3, '.', '' );
809
810 switch ( $limit_type ) {
811
812 case 'limit':
813
814 $opts[ $opt_pre . '_img_crop' ] = 1;
815 $opts[ $opt_pre . '_img_crop:disabled' ] = true; // Prevent changes in settings page.
816
817 if ( $img_ratio !== $limit_ratio ) {
818
819 $notice_msg = sprintf( __( 'Option keys "%1$s" (%2$d) and "%3$s" (%4$d) have an aspect ratio of %5$s:1, which not equal to the required image ratio of %6$s:1.', 'wpsso' ), $opt_pre . '_img_width', $img_width, $opt_pre . '_img_height', $img_height, $img_ratio, $limit_ratio );
820 }
821
822 break;
823
824 case 'limit_max':
825
826 if ( $img_crop && $img_ratio >= $limit_ratio ) {
827
828 $notice_msg = sprintf( __( 'Option keys "%1$s" (%2$d) and "%3$s" (%4$d) have an aspect ratio of %5$s:1, which is equal to / or greater than the maximum image ratio of %6$s:1.', 'wpsso' ), $opt_pre . '_img_width', $img_width, $opt_pre . '_img_height', $img_height, $img_ratio, $limit_ratio );
829 }
830
831 break;
832 }
833
834 if ( $notice_msg ) {
835
836 $notice_msg .= ' ' . __( 'These options have been reset to their default values.', 'wpsso' );
837
838 $this->p->notice->err( $notice_msg );
839
840 $opts[ $opt_pre . '_img_width' ] = $defs[ $opt_pre . '_img_width' ];
841 $opts[ $opt_pre . '_img_height' ] = $defs[ $opt_pre . '_img_height' ];
842 $opts[ $opt_pre . '_img_crop' ] = $defs[ $opt_pre . '_img_crop' ];
843 }
844 }
845 }
846
847 if ( false === $mod ) {
848
849 /*
850 * Check the Facebook App ID value.
851 */
852 if ( ! empty( $opts[ 'fb_app_id' ] ) && ( ! is_numeric( $opts[ 'fb_app_id' ] ) || strlen( $opts[ 'fb_app_id' ] ) > 32 ) ) {
853
854 $this->p->notice->err( sprintf( __( 'The Facebook App ID must be numeric and 32 characters or less in length - the value of "%s" is not valid.', 'wpsso' ), $opts[ 'fb_app_id' ] ) );
855 }
856
857 /*
858 * If the plugin_check_head option is disabled, then delete the check counter.
859 */
860 if ( ! $network ) {
861
862 if ( empty( $this->p->options[ 'plugin_check_head' ] ) ) {
863
864 delete_option( WPSSO_POST_CHECK_COUNT_NAME );
865 }
866 }
867 }
868
869 /*
870 * Skip refreshing the image URL dimensions if saving network options.
871 */
872 if ( ! $network ) {
873
874 $this->refresh_image_url_sizes( $opts ); // $opts passed by reference.
875
876 if ( empty( $mod[ 'name' ] ) ) { // Only check when saving the plugin settings.
877
878 $this->check_site_org_image_sizes( $opts );
879 }
880 }
881
882 /*
883 * The options array should not contain any numeric keys.
884 */
885 SucomUtil::unset_numeric_keys( $opts );
886
887 return $opts;
888 }
889
890 /*
891 * Save both options and site options.
892 *
893 * Called by WpssoAdmin->load_settings_page() for the 'reload_default_image_sizes' action.
894 * Called by WpssoAdmin->import_plugin_settings_json().
895 */
896 public function save_options( $options_name, array $opts, $network = false ) {
897
898 if ( $this->p->debug->enabled ) {
899
900 $this->p->debug->mark();
901 }
902
903 /*
904 * Make sure we have something to work with.
905 */
906 if ( empty( $opts ) || ! is_array( $opts ) ) {
907
908 if ( $this->p->debug->enabled ) {
909
910 $this->p->debug->log( 'exiting early: options variable is empty and/or not array' );
911 }
912
913 return false;
914 }
915
916 $is_option_upg = $this->is_upgrade_required( $opts ); // Existing option versions have changed.
917
918 /*
919 * $opts is the new options to be saved. Wpsso->options and Wpsso->site_options are still the old options.
920 *
921 * $network is true if we're saving the multisite network settings.
922 *
923 * $is_option_upg is true when the options versions, not the plugin versions, have changed.
924 *
925 * Also applied by WpssoAdmin->settings_sanitation().
926 * Also applied by WpssoAdmin->save_site_settings().
927 *
928 * See WpssoRrssbFiltersOptions->filter_save_settings_options().
929 * See WpssoUmFiltersOptions->filter_save_settings_options().
930 */
931 if ( $this->p->debug->enabled ) {
932
933 $this->p->debug->log( 'applying filters "wpsso_save_settings_options"' );
934 }
935
936 $opts = apply_filters( 'wpsso_save_settings_options', $opts, $network, $is_option_upg );
937
938 /*
939 * Add plugin and add-on versions (ie. 'checksum', 'opt_checksum', and 'opt_versions').
940 */
941 $this->p->opt->add_versions_checksum( $opts ); // $opts must be an array.
942
943 /*
944 * Don't save the disabled option status.
945 *
946 * Example: add_meta_name_robots:disabled = true
947 */
948 foreach ( preg_grep( '/:disabled$/', array_keys( $opts ) ) as $key ) {
949
950 unset( $opts[ $key ] );
951 }
952
953 if ( $network && $saved = update_site_option( $options_name, $opts ) ) { // Auto-creates options with autoload no.
954
955 $this->p->site_options = $opts; // Update the current plugin options array.
956
957 } elseif ( $saved = update_option( $options_name, $opts ) ) { // Auto-creates options with autoload yes.
958
959 $this->p->options = $opts; // Update the current plugin options array.
960 }
961
962 if ( $saved ) {
963
964 if ( $is_option_upg ) {
965
966 if ( $this->p->debug->enabled ) {
967
968 $this->p->debug->log( $options_name . ' settings have been upgraded and saved' );
969 }
970
971 /*
972 * Refresh the Schema types transient cache and the minimized notice stylesheet immediately.
973 */
974 $this->p->schema->refresh_schema_types();
975
976 if ( is_admin() ) {
977
978 $this->p->notice->refresh_notice_style();
979
980 $user_id = get_current_user_id();
981 $notice_msg = '<strong>' . __( 'Plugin settings have been upgraded and saved.', 'wpsso' ) . '</strong> ';
982 $notice_key = 'settings-upgraded-and-saved';
983
984 $this->p->notice->upd( $notice_msg, $user_id, $notice_key );
985
986 /*
987 * Schedule a cache refresh.
988 */
989 if ( $this->p->debug->enabled ) {
990
991 $this->p->debug->log( 'scheduling cache refresh' );
992 }
993
994 $this->p->util->cache->schedule_refresh( $user_id );
995 }
996
997 } elseif ( $this->p->debug->enabled ) {
998
999 $this->p->debug->log( $options_name . ' settings have been saved silently' );
1000 }
1001
1002 } elseif ( $this->p->debug->enabled ) {
1003
1004 $this->p->debug->log( 'wordpress failed to save the ' . $options_name . ' settings' );
1005 }
1006
1007 return $saved;
1008 }
1009
1010 public function get_version( array $opts, $ext ) {
1011
1012 if ( isset( $opts[ 'opt_versions' ][ $ext ] ) ) { // Check for current version key first.
1013
1014 return (int) $opts[ 'opt_versions' ][ $ext ];
1015
1016 } elseif ( isset( $opts[ 'plugin_' . $ext . '_opt_version' ] ) ) { // Deprecated options version key.
1017
1018 return (int) $opts[ 'plugin_' . $ext . '_opt_version' ];
1019 }
1020
1021 return 0;
1022 }
1023
1024 /*
1025 * Returns true or false.
1026 */
1027 public function set_version( array &$opts, $ext, $version = 0 ) {
1028
1029 if ( $ext ) {
1030
1031 if ( $version > 0 ) {
1032
1033 if ( ! isset( $opts[ 'opt_versions' ] ) || ! is_array( $opts[ 'opt_versions' ] ) ) {
1034
1035 $opts[ 'opt_versions' ] = array();
1036 }
1037
1038 $opts[ 'opt_versions' ][ $ext ] = $version;
1039
1040 } else {
1041
1042 unset( $opts[ 'opt_versions' ][ $ext ] );
1043 }
1044
1045 if ( isset( $opts[ 'plugin_' . $ext . '_opt_version' ] ) ) { // Deprecated options version key.
1046
1047 unset( $opts[ 'plugin_' . $ext . '_opt_version' ] );
1048 }
1049
1050 return true;
1051 }
1052
1053 return false;
1054 }
1055
1056 /*
1057 * Returns true or false.
1058 */
1059 public function is_new_options( array $opts ) {
1060
1061 return empty( $opts[ 'opt_checksum' ] ) && empty( $opts[ 'options_version' ] ) ? true : false;
1062 }
1063
1064 /*
1065 * Returns true or false, false for a new options array ('checksum' is an empty string by default).
1066 */
1067 public function is_plugin_upgrading( array $opts ) {
1068
1069 $cf_checksum = md5( $this->p->cf[ '*' ][ 'version' ] );
1070
1071 $prev_checksum = '';
1072
1073 if ( isset( $opts[ 'checksum' ] ) ) { // Empty string by default.
1074
1075 $prev_checksum = $opts[ 'checksum' ];
1076 }
1077
1078 return $prev_checksum && $prev_checksum !== $cf_checksum ? true : false;
1079 }
1080
1081 /*
1082 * Returns true or false, false for a new options array ('opt_checksum' is an empty string by default).
1083 */
1084 public function is_upgrade_required( array $opts ) {
1085
1086 $cf_checksum = md5( $this->p->cf[ 'opt' ][ 'version' ] );
1087
1088 $prev_checksum = '';
1089
1090 if ( isset( $opts[ 'opt_checksum' ] ) ) { // Empty string by default.
1091
1092 $prev_checksum = $opts[ 'opt_checksum' ];
1093
1094 } elseif ( isset( $opts[ 'options_version' ] ) ) { // Deprecated options checksum key.
1095
1096 $prev_checksum = md5( $opts[ 'options_version' ] );
1097 }
1098
1099 return $prev_checksum && $prev_checksum !== $cf_checksum ? true : false;
1100 }
1101
1102 /*
1103 * Add plugin and add-on versions (ie. 'checksum', 'opt_checksum', and 'opt_versions').
1104 */
1105 public function add_versions_checksum( array &$opts ) { // Pass by reference is OK.
1106
1107 if ( isset( $opts[ 'options_version' ] ) ) { // Deprecated options checksum key.
1108
1109 unset( $opts[ 'options_version' ] );
1110 }
1111
1112 $opts[ 'checksum' ] = md5( $this->p->cf[ '*' ][ 'version' ] );
1113
1114 $opts[ 'opt_checksum' ] = md5( $this->p->cf[ 'opt' ][ 'version' ] );
1115
1116 if ( ! isset( $opts[ 'opt_versions' ] ) || ! is_array( $opts[ 'opt_versions' ] ) ) {
1117
1118 $opts[ 'opt_versions' ] = array();
1119 }
1120
1121 foreach ( $this->p->cf[ 'plugin' ] as $ext => $info ) {
1122
1123 if ( isset( $opts[ 'plugin_' . $ext . '_opt_version' ] ) ) { // Deprecated options version key.
1124
1125 unset( $opts[ 'plugin_' . $ext . '_opt_version' ] );
1126 }
1127
1128 if ( isset( $info[ 'opt_version' ] ) ) { // Just in case.
1129
1130 $opts[ 'opt_versions' ][ $ext ] = $info[ 'opt_version' ];
1131 }
1132 }
1133 }
1134
1135 /*
1136 * Since WPSSO Core v17.0.0.
1137 *
1138 * Remove plugin and add-on versions (ie. 'checksum', 'opt_checksum', and 'opt_versions').
1139 */
1140 public function remove_versions_checksum( array &$opts ) { // Pass by reference is OK.
1141
1142 unset( $opts[ 'checksum' ] );
1143
1144 unset( $opts[ 'opt_checksum' ] );
1145
1146 unset( $opts[ 'opt_versions' ] );
1147 }
1148
1149 /*
1150 * Complete the options array for any custom post types and/or custom taxonomies.
1151 *
1152 * This method should be called after themes and plugins have registered their custom post types and taxonomies.
1153 *
1154 * Called by WpssoOptions->get_defaults().
1155 */
1156 private function add_custom_post_tax_options( array &$opts ) { // Pass by reference is OK.
1157
1158 if ( $this->p->debug->enabled ) {
1159
1160 $this->p->debug->mark();
1161 }
1162
1163 $col_headers = WpssoAbstractWpMeta::get_column_headers();
1164
1165 /*
1166 * Add options using a key prefix array and post type names.
1167 */
1168 $opt_prefixes = array(
1169 'og_type_for' => 'article', // Advanced Settings > Document Types > Open Graph > Type by Post Type.
1170 'plugin_add_to' => 1, // Advanced Settings > Plugin Settings > Interface > Show Document SSO Metabox.
1171 'plugin_ratings_reviews_for' => 0, // Advanced Settings > Service APIs > Ratings and Reviews > Get Reviews for Post Type.
1172 'schema_type_for' => 'webpage', // Advanced Settings > Document Types > Schema > Type by Post Type.
1173 );
1174
1175 foreach ( $col_headers as $col_key => $col_header ) {
1176
1177 $opt_prefix = 'plugin_' . $col_key . '_col';
1178
1179 /*
1180 * Show the Open Graph Image column for post types by default.
1181 */
1182 $def_val = 'og_img' === $col_key ? 1 : 0;
1183
1184 $opt_prefixes[ $opt_prefix ] = $def_val;
1185 }
1186
1187 /*
1188 * See WpssoBcFiltersOptions->filter_custom_post_type_options().
1189 * See WpssoRarFiltersOptions->filter_custom_post_type_options().
1190 * See WpssoWpsmFiltersOptions->filter_custom_post_type_options().
1191 */
1192 $opt_prefixes = apply_filters( 'wpsso_custom_post_type_options', $opt_prefixes );
1193
1194 $this->p->util->add_post_type_names( $opts, $opt_prefixes );
1195
1196 /*
1197 * Add options using a key prefix array and post type archive names.
1198 */
1199 $opt_prefixes = array(
1200 'og_type_for_pta' => 'website', // Advanced Settings > Document Types > Open Graph > Type by Post Type Archive.
1201 'schema_type_for_pta' => 'item.list', // Advanced Settings > Document Types > Schema > Type by Post Type Archive.
1202 );
1203
1204 $opt_prefixes = apply_filters( 'wpsso_custom_post_type_archive_options', $opt_prefixes );
1205
1206 $this->p->util->add_post_type_archive_names( $opts, $opt_prefixes );
1207
1208 /*
1209 * Add options using a key prefix array and term names.
1210 */
1211 $opt_prefixes = array(
1212 'og_type_for_tax' => 'website', // Advanced Settings > Document Types > Open Graph > Type by Taxonomy.
1213 'plugin_add_to_tax' => 1, // Advanced Settings > Plugin Settings > Interface > Show Document SSO Metabox.
1214 'schema_type_for_tax' => 'item.list', // Advanced Settings > Document Types > Schema > Type by Taxonomy.
1215 );
1216
1217 foreach ( $col_headers as $col_key => $col_header ) {
1218
1219 $opt_prefix = 'plugin_' . $col_key . '_col_tax';
1220
1221 /*
1222 * Show the Open Graph Image and Description columns for taxonomies by default.
1223 */
1224 $def_val = 'og_img' === $col_key || 'og_desc' === $col_key ? 1 : 0;
1225
1226 $opt_prefixes[ $opt_prefix ] = $def_val;
1227 }
1228
1229 /*
1230 * See WpssoBcFiltersOptions->filter_custom_taxonomy_options().
1231 * See WpssoRarFiltersOptions->filter_custom_taxonomy_options().
1232 * See WpssoWpsmFiltersOptions->filter_custom_taxonomy_options().
1233 */
1234 $opt_prefixes = apply_filters( 'wpsso_custom_taxonomy_options', $opt_prefixes );
1235
1236 $this->p->util->add_taxonomy_names( $opts, $opt_prefixes );
1237 }
1238
1239 /*
1240 * Update the width / height of remote image URLs.
1241 */
1242 private function refresh_image_url_sizes( array &$opts ) { // Pass by reference is OK.
1243
1244 if ( $this->p->debug->enabled ) {
1245
1246 $this->p->debug->mark();
1247 }
1248
1249 /*
1250 * Remove custom field names to exclude 'plugin_cf_img_url' and 'plugin_cf_vid_url'.
1251 */
1252 $img_url_keys = preg_grep( '/^plugin_cf_/', array_keys( $opts ), PREG_GREP_INVERT );
1253
1254 /*
1255 * Allow for multi-option keys, like 'place_img_url_1'.
1256 */
1257 $img_url_keys = preg_grep( '/_(img|logo|banner)_url(_[0-9]+)?(#[a-zA-Z_]+)?$/', $img_url_keys );
1258
1259 /*
1260 * Add correct image sizes for the image URL using getimagesize().
1261 *
1262 * Note that PHP v7.1 or better is required to get the image size of WebP images.
1263 */
1264 $this->p->util->add_image_url_size( $opts, $img_url_keys );
1265 }
1266
1267 private function check_site_org_image_sizes( array $opts ) {
1268
1269 /*
1270 * Skip if notices have already been shown.
1271 */
1272 if ( ! $this->p->notice->is_admin_pre_notices() ) {
1273
1274 return;
1275 }
1276
1277 /*
1278 * Skip if the "Site Publisher Type" option is not an organization.
1279 */
1280 if ( empty( $opts[ 'site_pub_schema_type' ] ) || 'organization' !== $opts[ 'site_pub_schema_type' ] ) {
1281
1282 return;
1283 }
1284
1285 /*
1286 * Returns an image array:
1287 *
1288 * array(
1289 * 'og:image:url' => null,
1290 * 'og:image:width' => null,
1291 * 'og:image:height' => null,
1292 * 'og:image:cropped' => null,
1293 * 'og:image:id' => null,
1294 * 'og:image:alt' => null,
1295 * 'og:image:size_name' => null,
1296 * );
1297 */
1298 foreach ( array ( 'site_org_logo', 'site_org_banner' ) as $img_prefix ) {
1299
1300 $mt_single_image = $this->p->media->get_mt_img_pre_url( $opts, $img_prefix );
1301 $first_image_url = SucomUtil::get_first_mt_media_url( $mt_single_image );
1302
1303 if ( 'site_org_logo' === $img_prefix ) {
1304
1305 $option_label = _x( 'Organization Logo URL', 'option label', 'wpsso' );
1306 $option_link = $this->p->util->get_admin_url( 'essential', $option_label );
1307
1308 } elseif ( 'site_org_banner' === $img_prefix ) {
1309
1310 $option_label = _x( 'Organization Banner URL', 'option label', 'wpsso' );
1311 $option_link = $this->p->util->get_admin_url( 'essential', $option_label );
1312 }
1313
1314 if ( empty( $first_image_url ) ) {
1315
1316 // translators: %s is a link to the option label.
1317 $notice_msg = sprintf( __( 'The %s image is missing and required.', 'wpsso' ), $option_link ) . ' ';
1318
1319 $this->p->notice->err( $notice_msg );
1320
1321 } else {
1322
1323 $image_href = '<a href="' . $first_image_url . '">' . $first_image_url . '</a>';
1324 $image_width = $mt_single_image[ 'og:image:width' ];
1325 $image_height = $mt_single_image[ 'og:image:height' ];
1326 $image_dims = $image_width . 'x' . $image_height . 'px';
1327 $notice_key = 'invalid-image-dimensions-' . $image_dims . '-' . $first_image_url;
1328
1329 if ( '-1x-1px' === $image_dims ) {
1330
1331 // translators: %s is a link to the option label.
1332 $notice_msg = sprintf( __( 'The %s image dimensions cannot be determined.', 'wpsso' ), $option_link ) . ' ';
1333
1334 // translators: %s is the image URL.
1335 $notice_msg .= sprintf( __( 'Please make sure this site can access %s using the PHP getimagesize() function.',
1336 'wpsso' ), $image_href );
1337
1338 $this->p->notice->err( $notice_msg, null, $notice_key );
1339
1340 } elseif ( 'site_org_logo' === $img_prefix ) {
1341
1342 $min_width = $this->p->cf[ 'head' ][ 'limit_min' ][ 'org_logo_width' ];
1343 $min_height = $this->p->cf[ 'head' ][ 'limit_min' ][ 'org_logo_height' ];
1344 $minimum_dims = $min_width . 'x' . $min_height . 'px';
1345
1346 if ( $image_width < $min_width || $image_height < $min_height ) {
1347
1348 // translators: %1$s is a link to the option label.
1349 $notice_msg = sprintf( __( 'The %1$s image dimensions are %2$s and must be greater than %3$s.',
1350 'wpsso' ), $option_link, $image_dims, $minimum_dims ) . ' ';
1351
1352 // translators: %s is the image URL.
1353 $notice_msg .= sprintf( __( 'Please correct the %s logo image or select a different logo image.',
1354 'wpsso' ), $image_href );
1355
1356 $this->p->notice->err( $notice_msg, null, $notice_key );
1357 }
1358
1359 } elseif ( 'site_org_banner' === $img_prefix ) {
1360
1361 $min_width = $this->p->cf[ 'head' ][ 'limit' ][ 'org_banner_width' ];
1362 $min_height = $this->p->cf[ 'head' ][ 'limit' ][ 'org_banner_height' ];
1363 $required_dims = $min_width . 'x' . $min_height . 'px';
1364
1365 if ( $image_dims !== $required_dims ) {
1366
1367 // translators: %1$s is a link to the option label.
1368 $notice_msg = sprintf( __( 'The %1$s image dimensions are %2$s and must be exactly %3$s.',
1369 'wpsso' ), $option_link, $image_dims, $required_dims ) . ' ';
1370
1371 // translators: %s is the image URL.
1372 $notice_msg .= sprintf( __( 'Please correct the %s banner image or select a different banner image.',
1373 'wpsso' ), $image_href );
1374
1375 $this->p->notice->err( $notice_msg, null, $notice_key );
1376 }
1377 }
1378 }
1379 }
1380 }
1381
1382 private function check_value( $opt_key, $base_key, $opt_val, $def_val, $network, $mod ) {
1383
1384 if ( is_array( $opt_val ) ) { // Just in case.
1385
1386 return $opt_val;
1387 }
1388
1389 /*
1390 * Translate error messages only once.
1391 */
1392 static $errors_transl = null;
1393
1394 if ( null === $errors_transl ) {
1395
1396 $errors_transl = array(
1397 'array' => __( 'The value of option "%s" must be an array - resetting this option to its default value.', 'wpsso' ),
1398 'api_key' => __( 'The value of option "%s" must be alpha-numeric - resetting this option to its default value.', 'wpsso' ),
1399 'blank_num' => __( 'The value of option "%s" must be blank or numeric - resetting this option to its default value.', 'wpsso' ),
1400 'color' => __( 'The value of option "%s" must be a CSS color code - resetting this option to its default value.', 'wpsso' ),
1401 'csv_urls' => __( 'The value of option "%s" must be a comma-delimited list of URL(s) - resetting this option to its default value.', 'wpsso' ),
1402 'date' => __( 'The value of option "%s" must be a yyyy-mm-dd date - resetting this option to its default value.', 'wpsso' ),
1403 'html' => __( 'The value of option "%s" must be HTML code - resetting this option to its default value.', 'wpsso' ),
1404 'img_id' => __( 'The value of option "%s" must be an image ID - resetting this option to its default value.', 'wpsso' ),
1405 'img_url' => __( 'The value of option "%s" must be a valid image URL - resetting this option to its default value.', 'wpsso' ),
1406 'not_blank' => __( 'The value of option "%s" cannot be an empty string - resetting this option to its default value.', 'wpsso' ),
1407 'numeric' => __( 'The value of option "%s" must be numeric - resetting this option to its default value.', 'wpsso' ),
1408 'pos_num' => __( 'The value of option "%1$s" must be equal to or greater than %2$s - resetting this option to its default value.', 'wpsso' ),
1409 'pos_num_gt' => __( 'The value of option "%1$s" must be greater than %2$s - resetting this option to its default value.', 'wpsso' ),
1410 'time' => __( 'The value of option "%s" must be a hh:mm time - resetting this option to its default value.', 'wpsso' ),
1411 'url' => __( 'The value of option "%s" must be a valid URL - resetting this option to its default value.', 'wpsso' ),
1412 );
1413 }
1414
1415 /*
1416 * Return the sanitation type for a given option key.
1417 *
1418 * Hooked by WpssoOptions->filter_option_type() and several add-ons.
1419 */
1420 $option_type = apply_filters( 'wpsso_option_type', $option_type = '', $base_key, $network, $mod );
1421
1422 /*
1423 * Apply a second more specific filter to customize the option type for a single base key.
1424 */
1425 $filter_name = SucomUtil::sanitize_hookname( 'wpsso_option_type_' . $base_key );
1426
1427 $option_type = apply_filters( $filter_name, $option_type, $network, $mod );
1428
1429 /*
1430 * Pre-filter most values to remove html.
1431 */
1432 switch ( $option_type ) {
1433
1434 case 'ignore':
1435
1436 return $opt_val; // Stop here.
1437
1438 break;
1439
1440 case 'html': // Leave html, css, and javascript code blocks as-is.
1441 case 'code': // Code values cannot be blank.
1442 case 'preg': // A regular expression.
1443
1444 $opt_val = preg_replace( '/[\r]+/', '', $opt_val );
1445
1446 break;
1447
1448 default:
1449
1450 $opt_val = wp_filter_nohtml_kses( $opt_val ); // Strips all the HTML in the content.
1451
1452 $opt_val = stripslashes( $opt_val ); // Strip slashes added by wp_filter_nohtml_kses().
1453
1454 break;
1455 }
1456
1457 /*
1458 * Optional cast on return.
1459 */
1460 $ret_int = null;
1461 $ret_fnum = null;
1462 $limit_min = null;
1463 $fnum_prec = null; // Floating point number precision.
1464
1465 if ( false !== ( $pos = strpos( $option_type, 'fnum' ) ) ) {
1466
1467 $fnum_prec = substr( $option_type, $pos + 4 );
1468 $option_type = substr( $option_type, 0, $pos + 4 );
1469
1470 if ( ! is_numeric( $fnum_prec ) ) $fnum_prec = 1; // Just in case.
1471 }
1472
1473 switch ( $option_type ) {
1474
1475 case 'array':
1476
1477 if ( ! is_array( $opt_val ) ) {
1478
1479 $this->p->notice->err( sprintf( $errors_transl[ 'array' ], $opt_key ) );
1480
1481 $opt_val = is_array( $def_val ) ? $def_val : array();
1482 }
1483
1484 break;
1485
1486 /*
1487 * Empty or alpha-numeric (upper or lower case), plus underscores and hypens.
1488 */
1489 case 'api_key':
1490
1491 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1492
1493 if ( '' !== $opt_val && preg_match( '/[^a-zA-Z0-9_\-]/', $opt_val ) ) {
1494
1495 $this->p->notice->err( sprintf( $errors_transl[ 'api_key' ], $opt_key ) );
1496
1497 $opt_val = $def_val;
1498 }
1499
1500 break;
1501
1502 /*
1503 * X (Twitter) usernames (prepend with an @ character).
1504 */
1505 case 'at_name':
1506
1507 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1508
1509 if ( '' !== $opt_val ) {
1510
1511 $opt_val = SucomUtil::sanitize_twitter_name( $opt_val, $add_at = true );
1512 }
1513
1514 break;
1515
1516 /*
1517 * Empty or alpha-numeric uppercase (hyphens are allowed as well). Silently convert illegal
1518 * characters to single hyphens and trim excess.
1519 */
1520 case 'auth_id':
1521
1522 $opt_val = trim( preg_replace( '/[^A-Z0-9\-]+/', '-', $opt_val ), '-' );
1523 $opt_val = preg_replace( '/^ID-/', '', $opt_val ); // Just in case.
1524
1525 break;
1526
1527 case 'css_class':
1528
1529 $opt_val = SucomUtil::sanitize_css_class( $opt_val );
1530
1531 break;
1532
1533 case 'css_id':
1534
1535 $opt_val = SucomUtil::sanitize_css_id( $opt_val );
1536
1537 break;
1538
1539 case 'dashed':
1540
1541 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1542 $opt_val = sanitize_title_with_dashes( $opt_val );
1543
1544 break;
1545
1546 /*
1547 * Empty string or integer.
1548 */
1549 case 'blank_int':
1550
1551 $ret_int = true;
1552
1553 // No break.
1554
1555 /*
1556 * Empty string or numeric.
1557 */
1558 case 'blank_num':
1559
1560 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1561
1562 if ( '' === $opt_val ) {
1563
1564 $ret_int = false;
1565
1566 } elseif ( ! is_numeric( $opt_val ) ) {
1567
1568 $this->p->notice->err( sprintf( $errors_transl[ 'blank_num' ], $opt_key ) );
1569
1570 $opt_val = $def_val;
1571
1572 if ( '' === $opt_val ) $ret_int = false; // Default value is blank.
1573 }
1574
1575 break;
1576
1577 /*
1578 * Options that cannot be blank (aka empty string).
1579 */
1580 case 'code':
1581 case 'not_blank':
1582 case 'not_blank_quiet':
1583
1584 if ( '' === $opt_val && '' !== $def_val ) {
1585
1586 if ( false === strpos( $option_type, '_quiet' ) ) {
1587
1588 $this->p->notice->err( sprintf( $errors_transl[ 'not_blank' ], $opt_key ) );
1589 }
1590
1591 $opt_val = $def_val;
1592 }
1593
1594 break;
1595
1596 case 'csv_blank':
1597
1598 if ( '' !== $opt_val ) {
1599
1600 $opt_val = implode( $glue = ', ', SucomUtil::explode_csv( $opt_val ) );
1601 }
1602
1603 break;
1604
1605 case 'csv_urls':
1606
1607 if ( '' !== $opt_val ) {
1608
1609 $parts = array();
1610
1611 foreach ( SucomUtil::explode_csv( $opt_val ) as $part ) {
1612
1613 $part = SucomUtil::decode_html( $part ); // Just in case.
1614
1615 if ( false === filter_var( $part, FILTER_VALIDATE_URL ) ) {
1616
1617 $this->p->notice->err( sprintf( $errors_transl[ 'csv_urls' ], $opt_key ) );
1618
1619 $opt_val = $def_val;
1620
1621 break;
1622
1623 } else {
1624
1625 $parts[] = $part;
1626 }
1627 }
1628
1629 $opt_val = implode( $glue = ', ', $parts );
1630 }
1631
1632 break;
1633
1634 /*
1635 * Text strings that can be blank (line breaks are removed).
1636 */
1637 case 'desc':
1638 case 'description':
1639 case 'one_line':
1640 case 'preg': // A regular expression.
1641
1642 if ( '' !== $opt_val ) {
1643
1644 $opt_val = trim( preg_replace( '/[\s\n\r]+/s', ' ', $opt_val ) );
1645 }
1646
1647 break;
1648
1649 /*
1650 * Floating-point number.
1651 *
1652 * The decimal precision is defined before the switch() statement.
1653 */
1654 case 'fnum':
1655
1656 $ret_fnum = true;
1657
1658 if ( ! is_numeric( $opt_val ) ) {
1659
1660 $this->p->notice->err( sprintf( $errors_transl[ 'numeric' ], $opt_key ) );
1661
1662 $opt_val = $def_val;
1663 }
1664
1665 break;
1666
1667 /*
1668 * Empty string or must include at least one HTML tag.
1669 */
1670 case 'html':
1671
1672 if ( '' !== $opt_val ) {
1673
1674 $opt_val = trim( $opt_val );
1675
1676 if ( ! preg_match( '/<.*>/', $opt_val ) ) {
1677
1678 $this->p->notice->err( sprintf( $errors_transl[ 'html' ], $opt_key ) );
1679
1680 $opt_val = $def_val;
1681 }
1682 }
1683
1684 break;
1685
1686 /*
1687 * Empty string or an image ID.
1688 */
1689 case 'img_id':
1690
1691 if ( '' !== $opt_val ) {
1692
1693 if ( ! preg_match( '/^[0-9]+$/', $opt_val ) ) {
1694
1695 $this->p->notice->err( sprintf( $errors_transl[ 'img_id' ], $opt_key ) );
1696
1697 $opt_val = $def_val;
1698 }
1699 }
1700
1701 break;
1702
1703 /*
1704 * Integer.
1705 */
1706 case 'int':
1707 case 'integer':
1708
1709 $ret_int = true;
1710
1711 // No break.
1712
1713 /*
1714 * Numeric.
1715 */
1716 case 'numeric':
1717
1718 if ( ! is_numeric( $opt_val ) ) {
1719
1720 $this->p->notice->err( sprintf( $errors_transl[ 'numeric' ], $opt_key ) );
1721
1722 $opt_val = $def_val;
1723
1724 if ( '' === $opt_val ) $ret_int = false; // Default value is blank.
1725 }
1726
1727 break;
1728
1729 /*
1730 * Integer options that must be 0 or more.
1731 */
1732 case 'zero_pos_int':
1733
1734 $limit_min = 0;
1735
1736 // No break.
1737
1738 /*
1739 * Integer options that must be 1 or more.
1740 */
1741 case 'img_height': // Image height, subject to minimum value (typically, at least 200px).
1742 case 'img_width': // Image height, subject to minimum value (typically, at least 200px).
1743 case 'pos_int':
1744
1745 $ret_int = true;
1746
1747 /*
1748 * If $limit_min has not been defined above, check for a hard-coded minimum value (for
1749 * example, 200 for "og_img_width").
1750 */
1751 if ( null === $limit_min ) {
1752
1753 if ( isset( $this->p->cf[ 'head' ][ 'limit_min' ][ $base_key ] ) ) {
1754
1755 $limit_min = $this->p->cf[ 'head' ][ 'limit_min' ][ $base_key ];
1756
1757 } else $limit_min = 1;
1758 }
1759
1760 // No break.
1761
1762 /*
1763 * Zero or floating-point number.
1764 *
1765 * The decimal precision is defined before the switch() statement.
1766 */
1767 case 'zero_pos_fnum':
1768
1769 if ( null === $limit_min ) {
1770
1771 $limit_min = 0;
1772 }
1773
1774 // No break.
1775
1776 /*
1777 * Positive floating-point number.
1778 *
1779 * The decimal precision is defined before the switch() statement.
1780 */
1781 case 'pos_fnum':
1782
1783 if ( null === $ret_int ) {
1784
1785 $ret_fnum = true;
1786 }
1787
1788 // No break.
1789
1790 /*
1791 * Integer or numeric options that must be zero or larger than $limit_min.
1792 */
1793 case 'pos_num':
1794
1795 if ( ! empty( $mod[ 'name' ] ) && '' === trim( $opt_val ) ) { // Custom meta options can be empty.
1796
1797 $opt_val = '';
1798
1799 } elseif ( null !== $limit_min ) {
1800
1801 if ( $opt_val < $limit_min || ! is_numeric( $opt_val ) ) {
1802
1803 $this->p->notice->err( sprintf( $errors_transl[ 'pos_num' ], $opt_key, $limit_min ) );
1804
1805 $opt_val = $def_val;
1806
1807 }
1808
1809 } else { // $limit_min is null.
1810
1811 if ( $opt_val <= 0 || ! is_numeric( $opt_val ) ) {
1812
1813 $this->p->notice->err( sprintf( $errors_transl[ 'pos_num_gt' ], $opt_key, 0 ) );
1814
1815 $opt_val = $def_val;
1816 }
1817 }
1818
1819 if ( '' === $opt_val ) { // Default value is blank.
1820
1821 $ret_int = false;
1822 $ret_fnum = false;
1823 }
1824
1825 break;
1826
1827 case 'color':
1828 case 'date': // Empty or 'none' string, or date as yyyy-mm-dd.
1829 case 'time': // Empty or 'none' string, or time as hh:mm or hh:mm:ss.
1830
1831 $fmt = false;
1832
1833 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1834
1835 if ( 'color' === $option_type ) {
1836
1837 $fmt = '/^#[a-fA-f0-9]{6,6}$/'; // Color as #000000.
1838
1839 } elseif ( 'date' === $option_type ) {
1840
1841 $fmt = '/^[0-9]{4,4}-[0-9]{2,2}-[0-9]{2,2}$/'; // Date as yyyy-mm-dd.
1842
1843 } elseif ( 'time' === $option_type ) {
1844
1845 $fmt = '/^[0-9]{2,2}:[0-9]{2,2}(:[0-9]{2,2})?$/'; // Time as hh:mm or hh:mm:ss.
1846 }
1847
1848 if ( '' !== $opt_val && 'none' !== $opt_val && $fmt && ! preg_match( $fmt, $opt_val ) ) {
1849
1850 $this->p->notice->err( sprintf( $errors_transl[ $option_type ], $opt_key ) );
1851
1852 $opt_val = $def_val;
1853 }
1854
1855 break;
1856
1857 /*
1858 * Text strings that can be blank.
1859 */
1860 case 'ok_blank':
1861
1862 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1863
1864 break;
1865
1866 /*
1867 * Empty or texturized string.
1868 */
1869 case 'textured':
1870
1871 if ( '' !== $opt_val ) {
1872
1873 $opt_val = trim( wptexturize( ' ' . $opt_val . ' ' ) );
1874 }
1875
1876 break;
1877
1878 /*
1879 * Empty string or a URL.
1880 *
1881 * Note that WebP is only supported since PHP v7.1.
1882 */
1883 case 'img_url':
1884
1885 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1886
1887 if ( '' !== $opt_val ) {
1888
1889 $opt_val = SucomUtil::decode_html( $opt_val ); // Just in case.
1890
1891 if ( ! $this->p->util->is_image_url( $opt_val ) ) {
1892
1893 $this->p->notice->err( sprintf( $errors_transl[ 'img_url' ], $opt_key ) );
1894
1895 $opt_val = $def_val;
1896 }
1897 }
1898
1899 case 'url':
1900
1901 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1902
1903 if ( '' !== $opt_val ) {
1904
1905 $opt_val = SucomUtil::decode_html( $opt_val ); // Just in case.
1906
1907 if ( false === filter_var( $opt_val, FILTER_VALIDATE_URL ) ) {
1908
1909 $this->p->notice->err( sprintf( $errors_transl[ 'url' ], $opt_key ) );
1910
1911 $opt_val = $def_val;
1912 }
1913 }
1914
1915 break;
1916
1917 /*
1918 * Strip leading URLs off facebook usernames.
1919 */
1920 case 'url_base':
1921
1922 $opt_val = trim( $opt_val ); // Remove extra spaces from copy-paste.
1923
1924 if ( '' !== $opt_val ) {
1925
1926 $opt_val = preg_replace( '/(http|https):\/\/[^\/]*?\//', '', $opt_val );
1927 }
1928
1929 break;
1930
1931 /*
1932 * Everything else is a 1 or 0 checkbox option.
1933 */
1934 case 'checkbox':
1935 default:
1936
1937 if ( $def_val === 0 || $def_val === 1 ) { // Make sure the default option is also a 1 or 0, just in case.
1938
1939 $opt_val = empty( $opt_val ) ? 0 : 1;
1940 }
1941
1942 break;
1943 }
1944
1945 if ( $ret_int ) {
1946
1947 $opt_val = intval( $opt_val );
1948
1949 } elseif ( $ret_fnum && null !== $fnum_prec ) {
1950
1951 $opt_val = sprintf( '%.' . $fnum_prec . 'f', $opt_val );
1952 }
1953
1954 return $opt_val;
1955 }
1956
1957 public function set_default_text( array &$defs, $opt_key ) {
1958
1959 if ( $opt_key && is_string( $opt_key ) ) { // Just in case.
1960
1961 $text = $this->get_text( $opt_key, $use_opts = false );
1962
1963 $opt_key_locale = SucomUtilOptions::get_key_locale( $opt_key, $defs, 'current' );
1964
1965 $defs[ $opt_key_locale ] = $text;
1966
1967 if ( ! isset( $this->p->options[ $opt_key_locale ] ) ) { // Just in case.
1968
1969 $this->p->options[ $opt_key_locale ] = $text;
1970 }
1971 }
1972 }
1973
1974 /*
1975 * Returns an option value or null.
1976 *
1977 * $mixed = 'default' | 'current' | post ID | $mod array
1978 */
1979 public function get_text( $opt_key, $use_opts = true, $mixed = 'current' ) {
1980
1981 $text = null;
1982
1983 if ( $use_opts && ! empty( $this->p->options ) ) {
1984
1985 $text = SucomUtilOptions::get_key_value( $opt_key, $this->p->options, $mixed ); // Returns null if option key does not exist.
1986 }
1987
1988 if ( null === $text ) { // Fallback to default text from current locale.
1989
1990 switch ( $opt_key ) {
1991
1992 case 'plugin_title_part_site': // Title Tag Site Prefix / Suffix.
1993
1994 return _x( '%%sitename%%', 'option value', 'wpsso' );
1995
1996 case 'plugin_title_part_tagline': // Title Tag Tagline Prefix / Suffix.
1997
1998 return _x( '%%sitedesc%%', 'option value', 'wpsso' );
1999
2000 case 'plugin_img_alt_prefix': // Content Image Alt Prefix.
2001
2002 return _x( 'Image:', 'option value', 'wpsso' );
2003
2004 case 'plugin_p_cap_prefix': // WP Caption Text Prefix.
2005
2006 return _x( 'Caption:', 'option value', 'wpsso' );
2007
2008 case 'plugin_comment_title': // Comment Title.
2009
2010 /*
2011 * %%comment_date%% is formatted based on the WordPress Settings > General > Date Format value.
2012 */
2013 return _x( 'Comment by %%comment_author%% on %%comment_date%%', 'option value', 'wpsso' );
2014
2015 case 'plugin_comment_reply_title': // Reply Comment Title.
2016
2017 /*
2018 * %%comment_date%% is formatted based on the WordPress Settings > General > Date Format value.
2019 */
2020 return _x( 'Reply by %%comment_author%% on %%comment_date%%', 'option value', 'wpsso' );
2021
2022 case 'plugin_comment_review_title': // Review Comment Title.
2023
2024 return _x( 'Review by %%comment_author%%', 'option value', 'wpsso' );
2025
2026 case 'plugin_product_var_title': // Product Variation Title.
2027
2028 return _x( '%%var_title%% %%sep%% %%var_attrs%%', 'option value', 'wpsso' );
2029
2030 case 'plugin_feed_title': // RSS Feed Title.
2031
2032 return _x( '%%sitename%%', 'option value', 'wpsso' );
2033
2034 case 'plugin_404_page_title': // 404 Page Title.
2035
2036 return _x( 'Page Not Found', 'option value', 'wpsso' );
2037
2038 case 'plugin_404_page_desc': // 404 Page Description.
2039
2040 return _x( 'Page "%%pagename%%" not found.', 'option value', 'wpsso' );
2041
2042 case 'plugin_no_title_text': // No Title Text.
2043
2044 return _x( 'No Title', 'option value', 'wpsso' );
2045
2046 case 'plugin_no_desc_text': // No Description Text.
2047
2048 return _x( 'No description.', 'option value', 'wpsso' );
2049
2050 case 'plugin_term_page_title': // Term Archive Title.
2051
2052 return _x( '%%term_hierarchy%%', 'option value', 'wpsso' );
2053
2054 case 'plugin_term_page_desc': // Term Archive Description.
2055
2056 return _x( '%%term_tax_single%% archive page for %%term_name%%.', 'option value', 'wpsso' );
2057
2058 case 'plugin_author_page_title': // Author Archive Title.
2059
2060 return _x( '%%author_name%%, Author at %%sitename%%', 'option value', 'wpsso' );
2061
2062 case 'plugin_author_page_desc': // Author Archive Description.
2063
2064 return _x( 'Author archive page for %%author_name%%.', 'option value', 'wpsso' );
2065
2066 case 'plugin_search_page_title': // Search Results Title.
2067
2068 return _x( 'Search Results %%sep%% %%query_search%%', 'option value', 'wpsso' );
2069
2070 case 'plugin_search_page_desc': // Search Results Description.
2071
2072 return _x( 'Search results for &#8220;%%query_search%%&#8221;.', 'option value', 'wpsso' );
2073
2074 case 'plugin_year_page_title': // Year Archive Title.
2075
2076 return _x( '%%query_year%%', 'option value', 'wpsso' );
2077
2078 case 'plugin_year_page_desc': // Year Archive Description.
2079
2080 return _x( 'Yearly archive for %%query_year%%.', 'option value', 'wpsso' );
2081
2082 case 'plugin_month_page_title': // Month Archive Title.
2083
2084 return _x( '%%query_month%% %%query_year%%', 'option value', 'wpsso' );
2085
2086 case 'plugin_month_page_desc': // Month Archive Description.
2087
2088 return _x( 'Monthly archive for %%query_month%%, %%query_year%%.', 'option value', 'wpsso' );
2089
2090 case 'plugin_day_page_title': // Day Archive Title.
2091
2092 return _x( '%%query_month%% %%query_day%%, %%query_year%%', 'option value', 'wpsso' );
2093
2094 case 'plugin_day_page_desc': // Day Archive Description.
2095
2096 return _x( 'Daily archive for %%query_month%% %%query_day%%, %%query_year%%.', 'option value', 'wpsso' );
2097
2098 default:
2099
2100 return apply_filters( 'wpsso_get_text_default_options_key', null, $opt_key );
2101 }
2102 }
2103
2104 return $text;
2105 }
2106 }
2107 }
2108