The SEO Framework - Version 4.0.5

Version Description

In WordPress, we found various query endpoints that can be malformed to create broken pages. Backlinks to these pages can harm your site's ranking. In this update, we added advanced query protection, which you can enable via the robots meta settings.

The "Connected Social Pages" input fields will now disappear when you empty them. They have never proven to work, and Google has deprecated them. We also removed the transient caching for JSON-LD scripts, as it wasn't helping anyone.

On the other hand, we added a new feed indexing option, Discord sharing options (oEmbed, theme color), and the aforementioned advanced query protection option. Support for EDD and Polylang has been expanded, and we reintroduced the hyphen option for titles (which is the new default).

In this update, we bring a few other quality-of-life changes, as well. We added a dozen new filters, touched up the interface, streamlined the query handler, and fixed known corner-case issues and bugs.

Download this release

Release Info

Developer Cybr
Plugin Icon 128x128 The SEO Framework
Version 4.0.5
Comparing to
See all releases

Code changes from version 4.0.4 to 4.0.5

Files changed (100) hide show
  1. autodescription.php +4 -4
  2. bootstrap/activation.php +1 -1
  3. bootstrap/deactivation.php +1 -1
  4. bootstrap/define.php +1 -1
  5. bootstrap/envtest.php +4 -3
  6. bootstrap/load.php +5 -5
  7. bootstrap/upgrade.php +36 -8
  8. inc/classes/admin-init.class.php +7 -5
  9. inc/classes/admin-pages.class.php +22 -15
  10. inc/classes/bridges/listedit.class.php +66 -20
  11. inc/classes/bridges/listtable.class.php +18 -1
  12. inc/classes/bridges/ping.class.php +1 -1
  13. inc/classes/bridges/postsettings.class.php +27 -2
  14. inc/classes/bridges/scripts.class.php +7 -4
  15. inc/classes/bridges/seobar.class.php +3 -18
  16. inc/classes/bridges/seosettings.class.php +13 -2
  17. inc/classes/bridges/sitemap.class.php +1 -1
  18. inc/classes/bridges/termsettings.class.php +1 -1
  19. inc/classes/builders/images.class.php +25 -4
  20. inc/classes/builders/scripts.class.php +3 -2
  21. inc/classes/builders/seobar-page.class.php +36 -4
  22. inc/classes/builders/seobar-term.class.php +41 -9
  23. inc/classes/builders/seobar.class.php +1 -1
  24. inc/classes/builders/sitemap-base.class.php +3 -3
  25. inc/classes/builders/sitemap.class.php +1 -1
  26. inc/classes/cache.class.php +4 -69
  27. inc/classes/core.class.php +24 -20
  28. inc/classes/debug.class.php +53 -67
  29. inc/classes/deprecated.class.php +11 -11
  30. inc/classes/detect.class.php +186 -9
  31. inc/classes/feed.class.php +2 -2
  32. inc/classes/generate-description.class.php +13 -9
  33. inc/classes/generate-image.class.php +27 -2
  34. inc/classes/generate-ldjson.class.php +19 -33
  35. inc/classes/generate-title.class.php +30 -12
  36. inc/classes/generate-url.class.php +3 -2
  37. inc/classes/generate.class.php +72 -57
  38. inc/classes/init.class.php +187 -116
  39. inc/classes/interpreters/seobar.class.php +1 -1
  40. inc/classes/load.class.php +4 -1
  41. inc/classes/post-data.class.php +20 -5
  42. inc/classes/profile.class.php +1 -1
  43. inc/classes/query.class.php +146 -34
  44. inc/classes/render.class.php +55 -6
  45. inc/classes/sanitize.class.php +93 -23
  46. inc/classes/silencer.class.php +35 -1
  47. inc/classes/site-options.class.php +19 -8
  48. inc/classes/term-data.class.php +36 -22
  49. inc/classes/user-data.class.php +6 -3
  50. inc/compat/php-mbstring.php +2 -0
  51. inc/compat/plugin-edd.php +56 -0
  52. inc/compat/plugin-polylang.php +42 -0
  53. inc/compat/plugin-woocommerce.php +82 -3
  54. inc/compat/plugin-wpforo.php +29 -15
  55. inc/compat/theme-genesis.php +1 -1
  56. inc/functions/api.php +5 -4
  57. inc/functions/deprecated.php +3 -2
  58. inc/functions/upgrade-suggestion.php +1 -1
  59. inc/index.php +7 -0
  60. inc/traits/core/overload.trait.php +1 -1
  61. inc/views/admin/metaboxes/feed-metabox.php +4 -0
  62. inc/views/admin/metaboxes/general-metabox.php +10 -17
  63. inc/views/admin/metaboxes/homepage-metabox.php +1 -1
  64. inc/views/admin/metaboxes/robots-metabox.php +18 -12
  65. inc/views/admin/metaboxes/schema-metabox.php +56 -25
  66. inc/views/admin/metaboxes/sitemaps-metabox.php +2 -2
  67. inc/views/admin/metaboxes/social-metabox.php +51 -4
  68. inc/views/admin/metaboxes/title-metabox.php +1 -1
  69. inc/views/admin/metaboxes/webmaster-metabox.php +73 -59
  70. inc/views/debug/output.php +2 -2
  71. inc/views/edit/seo-settings-singular.php +3 -3
  72. inc/views/edit/seo-settings-tt.php +1 -1
  73. inc/views/list/bulk-post.php +28 -0
  74. inc/views/list/quick-post.php +28 -0
  75. inc/views/list/quick-term.php +28 -0
  76. inc/views/templates/settings/index.php +6 -0
  77. inc/views/templates/settings/settings.php +19 -0
  78. language/autodescription.pot +592 -505
  79. lib/css/post.css +50 -25
  80. lib/css/post.min.css +1 -1
  81. lib/css/settings.css +32 -0
  82. lib/css/settings.min.css +1 -1
  83. lib/js/ays.js +1 -1
  84. lib/js/c.js +3 -6
  85. lib/js/c.min.js +1 -1
  86. lib/js/description.js +1 -1
  87. lib/js/gbc.js +1 -1
  88. lib/js/le.js +30 -26
  89. lib/js/le.min.js +1 -1
  90. lib/js/post.js +1 -1
  91. lib/js/pt-gb.js +1 -1
  92. lib/js/pt.js +1 -1
  93. lib/js/settings.js +83 -13
  94. lib/js/settings.min.js +1 -1
  95. lib/js/social.js +1 -1
  96. lib/js/term.js +1 -1
  97. lib/js/title.js +1 -1
  98. lib/js/tsf.js +5 -5
  99. lib/js/tt.js +1 -1
  100. readme.txt +18 -11
autodescription.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: The SEO Framework
4
  * Plugin URI: https://theseoframework.com/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for your WordPress website.
6
- * Version: 4.0.4
7
  * Author: The SEO Framework Team
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
@@ -17,7 +17,7 @@ defined( 'ABSPATH' ) or die;
17
 
18
  /**
19
  * The SEO Framework plugin
20
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
21
  *
22
  * This program is free software: you can redistribute it and/or modify
23
  * it under the terms of the GNU General Public License version 3 as published
@@ -64,7 +64,7 @@ defined( 'ABSPATH' ) or die;
64
  *
65
  * @since 2.3.5
66
  */
67
- define( 'THE_SEO_FRAMEWORK_VERSION', '4.0.4' );
68
 
69
  /**
70
  * The plugin Database version.
@@ -73,7 +73,7 @@ define( 'THE_SEO_FRAMEWORK_VERSION', '4.0.4' );
73
  *
74
  * @since 2.7.0
75
  */
76
- define( 'THE_SEO_FRAMEWORK_DB_VERSION', '4000' );
77
 
78
  /**
79
  * The plugin file, absolute unix path.
3
  * Plugin Name: The SEO Framework
4
  * Plugin URI: https://theseoframework.com/
5
  * Description: An automated, advanced, accessible, unbranded and extremely fast SEO solution for your WordPress website.
6
+ * Version: 4.0.5
7
  * Author: The SEO Framework Team
8
  * Author URI: https://theseoframework.com/
9
  * License: GPLv3
17
 
18
  /**
19
  * The SEO Framework plugin
20
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
21
  *
22
  * This program is free software: you can redistribute it and/or modify
23
  * it under the terms of the GNU General Public License version 3 as published
64
  *
65
  * @since 2.3.5
66
  */
67
+ define( 'THE_SEO_FRAMEWORK_VERSION', '4.0.5' );
68
 
69
  /**
70
  * The plugin Database version.
73
  *
74
  * @since 2.7.0
75
  */
76
+ define( 'THE_SEO_FRAMEWORK_DB_VERSION', '4051' );
77
 
78
  /**
79
  * The plugin file, absolute unix path.
bootstrap/activation.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
bootstrap/deactivation.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
bootstrap/define.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
bootstrap/envtest.php CHANGED
@@ -12,7 +12,7 @@ defined( 'THE_SEO_FRAMEWORK_DB_VERSION' ) or die;
12
 
13
  /**
14
  * The SEO Framework plugin
15
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
16
  *
17
  * This program is free software: you can redistribute it and/or modify
18
  * it under the terms of the GNU General Public License version 3 as published
@@ -41,6 +41,7 @@ the_seo_framework_pre_boot_test();
41
  * Tests plugin upgrade.
42
  *
43
  * @since 3.1.0
 
44
  * @access private
45
  * @link http://php.net/eol.php
46
  * @link https://codex.wordpress.org/WordPress_Versions
@@ -60,7 +61,7 @@ function the_seo_framework_pre_boot_test() {
60
 
61
  $nw = get_network();
62
  if ( $nw instanceof WP_Network ) {
63
- if ( get_blog_option( $nw->site_id, 'the_seo_framework_tested_upgrade_version' ) ) {
64
  update_option( 'the_seo_framework_tested_upgrade_version', THE_SEO_FRAMEWORK_DB_VERSION );
65
  return;
66
  }
@@ -109,7 +110,7 @@ function the_seo_framework_pre_boot_test() {
109
  switch ( $test ) :
110
  case 1:
111
  //* PHP requirements not met, always count up to encourage best standards.
112
- $requirement = 'PHP 5.5.0 or later';
113
  $issue = 'PHP version';
114
  $version = PHP_VERSION;
115
  $subtitle = 'Server Requirements';
12
 
13
  /**
14
  * The SEO Framework plugin
15
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
16
  *
17
  * This program is free software: you can redistribute it and/or modify
18
  * it under the terms of the GNU General Public License version 3 as published
41
  * Tests plugin upgrade.
42
  *
43
  * @since 3.1.0
44
+ * @since 4.0.5 No longer assumes the main blog (WP Multisite) has been tested, although that's very likely when updated via the interface.
45
  * @access private
46
  * @link http://php.net/eol.php
47
  * @link https://codex.wordpress.org/WordPress_Versions
61
 
62
  $nw = get_network();
63
  if ( $nw instanceof WP_Network ) {
64
+ if ( get_blog_option( $nw->site_id, 'the_seo_framework_tested_upgrade_version' ) >= THE_SEO_FRAMEWORK_DB_VERSION ) {
65
  update_option( 'the_seo_framework_tested_upgrade_version', THE_SEO_FRAMEWORK_DB_VERSION );
66
  return;
67
  }
110
  switch ( $test ) :
111
  case 1:
112
  //* PHP requirements not met, always count up to encourage best standards.
113
+ $requirement = 'PHP 5.6.0 or later';
114
  $issue = 'PHP version';
115
  $version = PHP_VERSION;
116
  $subtitle = 'Server Requirements';
bootstrap/load.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
@@ -78,10 +78,10 @@ function _init_tsf() {
78
  /**
79
  * @package The_SEO_Framework
80
  */
81
- if ( \The_SEO_Framework\_can_load() ) {
82
  if ( \is_admin() ) {
83
  //! TODO: admin-only loader?
84
- $tsf = new \The_SEO_Framework\Load();
85
  $tsf->loaded = true;
86
 
87
  $tsf->_load_early_compat_files();
@@ -92,7 +92,7 @@ function _init_tsf() {
92
  */
93
  \do_action( 'the_seo_framework_admin_loaded' );
94
  } else {
95
- $tsf = new \The_SEO_Framework\Load();
96
  $tsf->loaded = true;
97
 
98
  $tsf->_load_early_compat_files();
@@ -104,7 +104,7 @@ function _init_tsf() {
104
  */
105
  \do_action( 'the_seo_framework_loaded' );
106
  } else {
107
- $tsf = new \The_SEO_Framework\Silencer();
108
  $tsf->loaded = false;
109
  }
110
 
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
78
  /**
79
  * @package The_SEO_Framework
80
  */
81
+ if ( _can_load() ) {
82
  if ( \is_admin() ) {
83
  //! TODO: admin-only loader?
84
+ $tsf = new Load();
85
  $tsf->loaded = true;
86
 
87
  $tsf->_load_early_compat_files();
92
  */
93
  \do_action( 'the_seo_framework_admin_loaded' );
94
  } else {
95
+ $tsf = new Load();
96
  $tsf->loaded = true;
97
 
98
  $tsf->_load_early_compat_files();
104
  */
105
  \do_action( 'the_seo_framework_loaded' );
106
  } else {
107
+ $tsf = new Silencer();
108
  $tsf->loaded = false;
109
  }
110
 
bootstrap/upgrade.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
@@ -107,15 +107,15 @@ function _do_upgrade() {
107
 
108
  // Check if upgrade is locked. Otherwise, lock it.
109
  if ( \get_transient( 'tsf_upgrade_lock' ) ) return;
110
- \set_transient( 'tsf_upgrade_lock', true, 300 );
 
 
111
 
112
  // Register this AFTER the transient is set. Otherwise, it may clear the transient in another thread.
113
  register_shutdown_function( __NAMESPACE__ . '\\_release_upgrade_lock' );
114
 
115
  \wp_raise_memory_limit( 'tsf_upgrade' );
116
-
117
- // phpcs:ignore, WordPress.PHP.NoSilencedErrors -- Feature may be disabled.
118
- @set_time_limit( 300 );
119
 
120
  /**
121
  * Clear the cache to prevent an update_option() from saving a stale database version to the cache.
@@ -177,6 +177,11 @@ function _do_upgrade() {
177
  $version = '3300';
178
  }
179
 
 
 
 
 
 
180
  /**
181
  * @since 2.7.0
182
  */
@@ -258,7 +263,7 @@ function _do_upgrade_notice() {
258
  );
259
  } else {
260
  $tsf->do_dismissible_notice(
261
- \esc_html__( 'Thank you for installing The SEO Framework! Your website is now optimized for SEO, automatically. We hope you enjoy our free plugin. Good luck with your site!', 'autodescription' ),
262
  'updated',
263
  false,
264
  false
@@ -539,6 +544,7 @@ function _do_upgrade_3103() {
539
  * refactored the whole API.
540
  *
541
  * @since 4.0.0
 
542
  */
543
  function _do_upgrade_3300() {
544
 
@@ -554,9 +560,9 @@ function _do_upgrade_3300() {
554
 
555
  $defaults = _upgrade_default_site_options();
556
 
557
- // Convert 'dash' title option to 'ndash', silently. Nothing really changes for the user.
558
  if ( 'dash' === $tsf->get_option( 'title_separator', false ) )
559
- $tsf->update_option( 'title_separator', 'ndash' );
560
 
561
  // Add default cron pinging option.
562
  if ( isset( $defaults['ping_use_cron'] ) ) {
@@ -586,3 +592,25 @@ function _do_upgrade_3300() {
586
 
587
  \update_option( 'the_seo_framework_upgraded_db_version', '3300' );
588
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
107
 
108
  // Check if upgrade is locked. Otherwise, lock it.
109
  if ( \get_transient( 'tsf_upgrade_lock' ) ) return;
110
+
111
+ $timeout = 5 * MINUTE_IN_SECONDS;
112
+ \set_transient( 'tsf_upgrade_lock', true, $timeout );
113
 
114
  // Register this AFTER the transient is set. Otherwise, it may clear the transient in another thread.
115
  register_shutdown_function( __NAMESPACE__ . '\\_release_upgrade_lock' );
116
 
117
  \wp_raise_memory_limit( 'tsf_upgrade' );
118
+ set_time_limit( $timeout );
 
 
119
 
120
  /**
121
  * Clear the cache to prevent an update_option() from saving a stale database version to the cache.
177
  $version = '3300';
178
  }
179
 
180
+ if ( $version < '4051' ) {
181
+ _do_upgrade_4051();
182
+ $version = '4051';
183
+ }
184
+
185
  /**
186
  * @since 2.7.0
187
  */
263
  );
264
  } else {
265
  $tsf->do_dismissible_notice(
266
+ \esc_html__( 'Thank you for installing The SEO Framework! Your website is now optimized for search and social sharing, automatically. We hope you enjoy our free plugin. Good luck with your site!', 'autodescription' ),
267
  'updated',
268
  false,
269
  false
544
  * refactored the whole API.
545
  *
546
  * @since 4.0.0
547
+ * @since 4.0.5 The upgrader now updates "dash" to "hyphen".
548
  */
549
  function _do_upgrade_3300() {
550
 
560
 
561
  $defaults = _upgrade_default_site_options();
562
 
563
+ // Convert 'dash' title option to 'hyphen', silently. Nothing really changes for the user.
564
  if ( 'dash' === $tsf->get_option( 'title_separator', false ) )
565
+ $tsf->update_option( 'title_separator', 'hyphen' );
566
 
567
  // Add default cron pinging option.
568
  if ( isset( $defaults['ping_use_cron'] ) ) {
592
 
593
  \update_option( 'the_seo_framework_upgraded_db_version', '3300' );
594
  }
595
+
596
+ /**
597
+ * Registers the advanced_query_protection option. 0 for existing sites. 1 for new sites.
598
+ * Registers the `index_the_feed` and `baidu_verification` options for existing sites. New sites will have it registered already.
599
+ *
600
+ * @since 4.0.5
601
+ */
602
+ function _do_upgrade_4051() {
603
+
604
+ $tsf = \the_seo_framework();
605
+
606
+ if ( \get_option( 'the_seo_framework_initial_db_version' ) < '4051' ) {
607
+ $tsf->update_option( 'advanced_query_protection', 0 );
608
+ $tsf->update_option( 'index_the_feed', 0 );
609
+ $tsf->update_option( 'baidu_verification', '' );
610
+ $tsf->update_option( 'oembed_scripts', 1 );
611
+ $tsf->update_option( 'oembed_remove_author', 0 );
612
+ $tsf->update_option( 'theme_color', '' );
613
+ }
614
+
615
+ \update_option( 'the_seo_framework_upgraded_db_version', '4051' );
616
+ }
inc/classes/admin-init.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -107,7 +107,7 @@ class Admin_Init extends Init {
107
  if ( $this->is_archive_admin() ) {
108
  $prepare_edit_screen = $this->is_taxonomy_supported();
109
  } elseif ( $this->is_singular_admin() ) {
110
- $prepare_edit_screen = $this->is_post_type_supported();
111
  } else {
112
  $prepare_edit_screen = false;
113
  }
@@ -199,7 +199,7 @@ class Admin_Init extends Init {
199
  'ml_IN' => 100 / 160, // Malayalam (മലയാളം)
200
  'ja' => 70 / 160, // Japanese (日本語)
201
  'ko_KR' => 82 / 160, // Korean (한국어)
202
- 'ta_IN' => 120 / 160, // Talim (தமிழ்)
203
  'zh_TW' => 70 / 160, // Taiwanese Mandarin (Traditional Chinese) (繁體中文)
204
  'zh_HK' => 70 / 160, // Hong Kong (Chinese version) (香港中文版)
205
  'zh_CN' => 70 / 160, // Mandarin (Simplified Chinese) (简体中文)
@@ -473,6 +473,7 @@ class Admin_Init extends Init {
473
  if ( isset( $_POST['val'] ) ) {
474
  $value = (int) $_POST['val'];
475
  } else {
 
476
  $value = $this->get_user_option( 0, 'counter_type', 3 ) + 1;
477
  }
478
  $value = \absint( $value );
@@ -505,7 +506,7 @@ class Admin_Init extends Init {
505
  // phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
506
  $this->_check_tsf_ajax_referer( 'edit_posts' );
507
 
508
- // CLear output buffer.
509
  $this->clean_response_header();
510
 
511
  $post_id = \absint( $_POST['post_id'] );
@@ -600,6 +601,8 @@ class Admin_Init extends Init {
600
  'data' => $data,
601
  'processed' => $get,
602
  ] );
 
 
603
  }
604
 
605
  /**
@@ -620,7 +623,6 @@ class Admin_Init extends Init {
620
  */
621
  public function _wp_ajax_crop_image() {
622
 
623
- // This checks the nonce, re:to all 'WordPress.Security.NonceVerification' below
624
  // phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer does this.
625
  $this->_check_tsf_ajax_referer( 'upload_files' );
626
 
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
107
  if ( $this->is_archive_admin() ) {
108
  $prepare_edit_screen = $this->is_taxonomy_supported();
109
  } elseif ( $this->is_singular_admin() ) {
110
+ $prepare_edit_screen = $this->is_post_type_supported( $this->get_admin_post_type() );
111
  } else {
112
  $prepare_edit_screen = false;
113
  }
199
  'ml_IN' => 100 / 160, // Malayalam (മലയാളം)
200
  'ja' => 70 / 160, // Japanese (日本語)
201
  'ko_KR' => 82 / 160, // Korean (한국어)
202
+ 'ta_IN' => 120 / 160, // Tamil (தமிழ்)
203
  'zh_TW' => 70 / 160, // Taiwanese Mandarin (Traditional Chinese) (繁體中文)
204
  'zh_HK' => 70 / 160, // Hong Kong (Chinese version) (香港中文版)
205
  'zh_CN' => 70 / 160, // Mandarin (Simplified Chinese) (简体中文)
473
  if ( isset( $_POST['val'] ) ) {
474
  $value = (int) $_POST['val'];
475
  } else {
476
+ // TODO use get_default_user_data() value instead.
477
  $value = $this->get_user_option( 0, 'counter_type', 3 ) + 1;
478
  }
479
  $value = \absint( $value );
506
  // phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer() does this.
507
  $this->_check_tsf_ajax_referer( 'edit_posts' );
508
 
509
+ // Clear output buffer.
510
  $this->clean_response_header();
511
 
512
  $post_id = \absint( $_POST['post_id'] );
601
  'data' => $data,
602
  'processed' => $get,
603
  ] );
604
+
605
+ // phpcs:enable, WordPress.Security.NonceVerification
606
  }
607
 
608
  /**
623
  */
624
  public function _wp_ajax_crop_image() {
625
 
 
626
  // phpcs:disable, WordPress.Security.NonceVerification -- _check_tsf_ajax_referer does this.
627
  $this->_check_tsf_ajax_referer( 'upload_files' );
628
 
inc/classes/admin-pages.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -181,13 +181,12 @@ class Admin_Pages extends Profile {
181
  * Outputs notices on SEO setting changes.
182
  *
183
  * @since 4.0.0
 
184
  * @access private
185
  */
186
- public static function _do_settings_page_notices() {
187
 
188
- $tsf = \the_seo_framework();
189
-
190
- $notice = $tsf->get_static_cache( 'settings_notice' );
191
 
192
  if ( ! $notice ) return;
193
 
@@ -216,9 +215,9 @@ class Admin_Pages extends Profile {
216
  break;
217
  }
218
 
219
- $tsf->update_static_cache( 'settings_notice', '' );
220
 
221
- $message and $tsf->do_dismissible_notice( $message, $type ?: 'updated' );
222
  }
223
 
224
  /**
@@ -270,8 +269,8 @@ class Admin_Pages extends Profile {
270
  * Outputs in-post flex navigational wrapper and its content.
271
  *
272
  * @since 2.9.0
273
- * @since 3.0.0: Converted to view.
274
- * @since 4.0.0: Deprecated third parameter, silently.
275
  *
276
  * @param string $id The nav-tab ID
277
  * @param array $tabs The tab content {
@@ -659,9 +658,11 @@ class Admin_Pages extends Profile {
659
  * Returns a chechbox wrapper.
660
  *
661
  * @since 3.1.0
 
662
  *
663
  * @param array $args : {
664
  * string $id The option name, used as field ID.
 
665
  * string $index The option index, used when the option is an array.
666
  * string $label The checkbox label description, placed inline of the checkbox.
667
  * string $description The checkbox additional description, placed underneat.
@@ -677,6 +678,7 @@ class Admin_Pages extends Profile {
677
  $args = array_merge(
678
  [
679
  'id' => '',
 
680
  'index' => '',
681
  'label' => '',
682
  'description' => '',
@@ -706,17 +708,22 @@ class Admin_Pages extends Profile {
706
  $value = isset( $value[ $index ] ) ? $value[ $index ] : '';
707
  }
708
 
709
- $cb_class = '';
 
 
 
 
 
710
  if ( $args['disabled'] ) {
711
- $cb_class = 'tsf-disabled';
712
  } elseif ( ! $args['index'] ) {
713
  // Can't fetch conditionals in index.
714
- $cb_class = $this->get_is_conditional_checked( $args['id'], false );
715
  } else {
716
  if ( $args['default'] ) {
717
- $cb_class = 'tsf-default-selected';
718
  } elseif ( $args['warned'] ) {
719
- $cb_class = 'tsf-warning-selected';
720
  }
721
  }
722
 
@@ -730,7 +737,7 @@ class Admin_Pages extends Profile {
730
  vsprintf(
731
  '<input type=checkbox class="%s" name="%s" id="%s" value="1" %s %s /> %s',
732
  [
733
- $cb_class,
734
  $field_name,
735
  $field_id,
736
  \checked( $value, true, false ),
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
181
  * Outputs notices on SEO setting changes.
182
  *
183
  * @since 4.0.0
184
+ * @since 4.0.5 This is no longer a static function.
185
  * @access private
186
  */
187
+ public function _do_settings_page_notices() {
188
 
189
+ $notice = $this->get_static_cache( 'settings_notice' );
 
 
190
 
191
  if ( ! $notice ) return;
192
 
215
  break;
216
  }
217
 
218
+ $this->update_static_cache( 'settings_notice', '' );
219
 
220
+ $message and $this->do_dismissible_notice( $message, $type ?: 'updated' );
221
  }
222
 
223
  /**
269
  * Outputs in-post flex navigational wrapper and its content.
270
  *
271
  * @since 2.9.0
272
+ * @since 3.0.0 Converted to view.
273
+ * @since 4.0.0 Deprecated third parameter, silently.
274
  *
275
  * @param string $id The nav-tab ID
276
  * @param array $tabs The tab content {
658
  * Returns a chechbox wrapper.
659
  *
660
  * @since 3.1.0
661
+ * @since 4.0.5 You can now supply an extra class for the checkbox.
662
  *
663
  * @param array $args : {
664
  * string $id The option name, used as field ID.
665
+ * string $class The checkbox class.
666
  * string $index The option index, used when the option is an array.
667
  * string $label The checkbox label description, placed inline of the checkbox.
668
  * string $description The checkbox additional description, placed underneat.
678
  $args = array_merge(
679
  [
680
  'id' => '',
681
+ 'class' => '',
682
  'index' => '',
683
  'label' => '',
684
  'description' => '',
708
  $value = isset( $value[ $index ] ) ? $value[ $index ] : '';
709
  }
710
 
711
+ $cb_classes = [];
712
+
713
+ if ( $args['class'] ) {
714
+ $cb_classes[] = $args['class'];
715
+ }
716
+
717
  if ( $args['disabled'] ) {
718
+ $cb_classes[] = 'tsf-disabled';
719
  } elseif ( ! $args['index'] ) {
720
  // Can't fetch conditionals in index.
721
+ $cb_classes[] = $this->get_is_conditional_checked( $args['id'], false );
722
  } else {
723
  if ( $args['default'] ) {
724
+ $cb_classes[] = 'tsf-default-selected';
725
  } elseif ( $args['warned'] ) {
726
+ $cb_classes[] = 'tsf-warning-selected';
727
  }
728
  }
729
 
737
  vsprintf(
738
  '<input type=checkbox class="%s" name="%s" id="%s" value="1" %s %s /> %s',
739
  [
740
+ esc_attr( implode( ' ', $cb_classes ) ),
741
  $field_name,
742
  $field_id,
743
  \checked( $value, true, false ),
inc/classes/bridges/listedit.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -123,7 +123,7 @@ final class ListEdit extends ListTable {
123
  if ( $taxonomy ) {
124
  // Not yet.
125
  } else {
126
- \the_seo_framework()->get_view( 'list/bulk-post' );
127
  }
128
  }
129
 
@@ -142,9 +142,9 @@ final class ListEdit extends ListTable {
142
  if ( $this->column_name !== $column_name ) return;
143
 
144
  if ( $taxonomy ) {
145
- \the_seo_framework()->get_view( 'list/quick-term' );
146
  } else {
147
- \the_seo_framework()->get_view( 'list/quick-post' );
148
  }
149
  }
150
 
@@ -180,28 +180,50 @@ final class ListEdit extends ListTable {
180
  'value' => $meta['_genesis_canonical_uri'],
181
  ],
182
  'noindex' => [
183
- 'default' => empty( $r_defaults['noindex'] ) ? 'index' : 'noindex',
184
- 'value' => $meta['_genesis_noindex'],
 
185
  ],
186
  'nofollow' => [
187
- 'default' => empty( $r_defaults['nofollow'] ) ? 'follow' : 'nofollow',
188
- 'value' => $meta['_genesis_nofollow'],
 
189
  ],
190
  'noarchive' => [
191
- 'default' => empty( $r_defaults['noarchive'] ) ? 'archive' : 'noarchive',
192
- 'value' => $meta['_genesis_noarchive'],
 
193
  ],
194
  'redirect' => [
195
  'value' => $meta['redirect'],
196
  ],
197
  ];
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  printf(
200
  '<span class=hidden id=%s data-le="%s"></span>',
201
  sprintf( 'tsfLeData[%s]', (int) $post_id ),
202
  // phpcs:ignore, WordPress.Security.EscapeOutput -- esc_attr is too aggressive.
203
  htmlspecialchars( json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT ), ENT_QUOTES, 'UTF-8' )
204
  );
 
 
 
205
  }
206
 
207
  /**
@@ -226,11 +248,13 @@ final class ListEdit extends ListTable {
226
 
227
  $tsf = \the_seo_framework();
228
 
 
 
 
 
 
229
  $r_defaults = $tsf->robots_meta(
230
- [
231
- 'id' => $term_id,
232
- 'taxonomy' => $this->taxonomy,
233
- ],
234
  \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS | \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION
235
  );
236
 
@@ -242,28 +266,50 @@ final class ListEdit extends ListTable {
242
  'value' => $meta['canonical'],
243
  ],
244
  'noindex' => [
245
- 'default' => empty( $r_defaults['noindex'] ) ? 'index' : 'noindex',
246
- 'value' => $meta['noindex'],
 
247
  ],
248
  'nofollow' => [
249
- 'default' => empty( $r_defaults['nofollow'] ) ? 'follow' : 'nofollow',
250
- 'value' => $meta['nofollow'],
 
251
  ],
252
  'noarchive' => [
253
- 'default' => empty( $r_defaults['noarchive'] ) ? 'archive' : 'noarchive',
254
- 'value' => $meta['noarchive'],
 
255
  ],
256
  'redirect' => [
257
  'value' => $meta['redirect'],
258
  ],
259
  ];
260
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  $container = sprintf(
262
  '<span class=hidden id=%s data-le="%s"></span>',
263
  sprintf( 'tsfLeData[%s]', (int) $term_id ),
264
  htmlspecialchars( json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT ), ENT_QUOTES, 'UTF-8' )
265
  );
266
 
 
 
 
267
  return $string . $container;
268
  }
269
  }
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
123
  if ( $taxonomy ) {
124
  // Not yet.
125
  } else {
126
+ \the_seo_framework()->get_view( 'list/bulk-post', get_defined_vars() );
127
  }
128
  }
129
 
142
  if ( $this->column_name !== $column_name ) return;
143
 
144
  if ( $taxonomy ) {
145
+ \the_seo_framework()->get_view( 'list/quick-term', get_defined_vars() );
146
  } else {
147
+ \the_seo_framework()->get_view( 'list/quick-post', get_defined_vars() );
148
  }
149
  }
150
 
180
  'value' => $meta['_genesis_canonical_uri'],
181
  ],
182
  'noindex' => [
183
+ 'value' => $meta['_genesis_noindex'],
184
+ 'isSelect' => true,
185
+ 'default' => empty( $r_defaults['noindex'] ) ? 'index' : 'noindex',
186
  ],
187
  'nofollow' => [
188
+ 'value' => $meta['_genesis_nofollow'],
189
+ 'isSelect' => true,
190
+ 'default' => empty( $r_defaults['nofollow'] ) ? 'follow' : 'nofollow',
191
  ],
192
  'noarchive' => [
193
+ 'value' => $meta['_genesis_noarchive'],
194
+ 'isSelect' => true,
195
+ 'default' => empty( $r_defaults['noarchive'] ) ? 'archive' : 'noarchive',
196
  ],
197
  'redirect' => [
198
  'value' => $meta['redirect'],
199
  ],
200
  ];
201
 
202
+ /**
203
+ * Tip: Prefix the indexes with your (plugin) name to prevent collisions.
204
+ * The index corresponds to field with the ID `autodescription-quick[%s]`, where %s is the index.
205
+ *
206
+ * @since 4.0.5
207
+ * @param array $data The current data : {
208
+ * string Index => @param array : {
209
+ * @param mixed $value The current value.
210
+ * @param bool $isSelect Optional. Whether the field is a select field.
211
+ * @param string $default Optional. Only works when $isSelect is true. The default value to be set in select index 0.
212
+ * }
213
+ * }
214
+ * @param array $query The query data. Contains 'id' and 'taxonomy'.
215
+ */
216
+ $data = \apply_filters_ref_array( 'the_seo_framework_list_table_data', [ $data, $query ] );
217
+
218
  printf(
219
  '<span class=hidden id=%s data-le="%s"></span>',
220
  sprintf( 'tsfLeData[%s]', (int) $post_id ),
221
  // phpcs:ignore, WordPress.Security.EscapeOutput -- esc_attr is too aggressive.
222
  htmlspecialchars( json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT ), ENT_QUOTES, 'UTF-8' )
223
  );
224
+
225
+ if ( $this->doing_ajax )
226
+ echo $this->get_ajax_dispatch_updated_event(); // phpcs:ignore, WordPress.Security.EscapeOutput
227
  }
228
 
229
  /**
248
 
249
  $tsf = \the_seo_framework();
250
 
251
+ $query = [
252
+ 'id' => $term_id,
253
+ 'taxonomy' => $this->taxonomy,
254
+ ];
255
+
256
  $r_defaults = $tsf->robots_meta(
257
+ $query,
 
 
 
258
  \The_SEO_Framework\ROBOTS_IGNORE_SETTINGS | \The_SEO_Framework\ROBOTS_IGNORE_PROTECTION
259
  );
260
 
266
  'value' => $meta['canonical'],
267
  ],
268
  'noindex' => [
269
+ 'value' => $meta['noindex'],
270
+ 'isSelect' => true,
271
+ 'default' => empty( $r_defaults['noindex'] ) ? 'index' : 'noindex',
272
  ],
273
  'nofollow' => [
274
+ 'value' => $meta['nofollow'],
275
+ 'isSelect' => true,
276
+ 'default' => empty( $r_defaults['nofollow'] ) ? 'follow' : 'nofollow',
277
  ],
278
  'noarchive' => [
279
+ 'value' => $meta['noarchive'],
280
+ 'isSelect' => true,
281
+ 'default' => empty( $r_defaults['noarchive'] ) ? 'archive' : 'noarchive',
282
  ],
283
  'redirect' => [
284
  'value' => $meta['redirect'],
285
  ],
286
  ];
287
 
288
+ /**
289
+ * Tip: Prefix the indexes with your (plugin) name to prevent collisions.
290
+ * The index corresponds to field with the ID `autodescription-quick[%s]`, where %s is the index.
291
+ *
292
+ * @since 4.0.5
293
+ * @param array $data The current data : {
294
+ * string Index => @param array : {
295
+ * @param mixed $value The current value.
296
+ * @param bool $isSelect Optional. Whether the field is a select field.
297
+ * @param string $default Optional. Only works when $isSelect is true. The default value to be set in select index 0.
298
+ * }
299
+ * }
300
+ * @param array $query The query data. Contains 'id' and 'taxonomy'.
301
+ */
302
+ $data = \apply_filters_ref_array( 'the_seo_framework_list_table_data', [ $data, $query ] );
303
+
304
  $container = sprintf(
305
  '<span class=hidden id=%s data-le="%s"></span>',
306
  sprintf( 'tsfLeData[%s]', (int) $term_id ),
307
  htmlspecialchars( json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT ), ENT_QUOTES, 'UTF-8' )
308
  );
309
 
310
+ if ( $this->doing_ajax )
311
+ $container .= $this->get_ajax_dispatch_updated_event();
312
+
313
  return $string . $container;
314
  }
315
  }
inc/classes/bridges/listtable.class.php CHANGED
@@ -7,7 +7,7 @@ namespace The_SEO_Framework\Bridges;
7
 
8
  /**
9
  * The SEO Framework plugin
10
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
11
  *
12
  * This program is free software: you can redistribute it and/or modify
13
  * it under the terms of the GNU General Public License version 3 as published
@@ -246,6 +246,23 @@ abstract class ListTable {
246
  // phpcs:enable, WordPress.Security.NonceVerification
247
  }
248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  /**
250
  * Add column on edit(-tags).php
251
  *
7
 
8
  /**
9
  * The SEO Framework plugin
10
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
11
  *
12
  * This program is free software: you can redistribute it and/or modify
13
  * it under the terms of the GNU General Public License version 3 as published
246
  // phpcs:enable, WordPress.Security.NonceVerification
247
  }
248
 
249
+ /**
250
+ * Returns a JS script that triggers list updates.
251
+ * This is a necessity as WordPress doesn't trigger actions on update.
252
+ *
253
+ * TODO bind to WordPress' function instead? Didn't we already do that?!
254
+ * See: `tsfLe._hijackListeners()`; Although, that doesn't cover "adding" new items.
255
+ *
256
+ * @since 4.0.5
257
+ * @NOTE: Do not bind to `tsfLeDispatchUpdate`, it's a private action.
258
+ * Bind to `tsfLeUpdated` instead, which is debounced and should only run once.
259
+ *
260
+ * @return string The triggering script.
261
+ */
262
+ protected function get_ajax_dispatch_updated_event() {
263
+ return "<script>'use strict';(()=>document.dispatchEvent(new Event('tsfLeDispatchUpdate')))();</script>";
264
+ }
265
+
266
  /**
267
  * Add column on edit(-tags).php
268
  *
inc/classes/bridges/ping.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/bridges/postsettings.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -42,6 +42,8 @@ final class PostSettings {
42
  * Registers the meta box for the Post edit screens.
43
  *
44
  * @since 4.0.0
 
 
45
  *
46
  * @param string $post_type The current Post Type.
47
  */
@@ -84,7 +86,12 @@ final class PostSettings {
84
  $title = sprintf( \esc_html__( '%s SEO Settings', 'autodescription' ), $label );
85
  }
86
 
87
- \add_meta_box( 'tsf-inpost-box', $title, __CLASS__ . '::_meta_box', $post_type, $context, $priority, [] );
 
 
 
 
 
88
  }
89
 
90
  /**
@@ -136,6 +143,24 @@ final class PostSettings {
136
  \do_action( 'the_seo_framework_pro_page_inpost_box' );
137
  }
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  /**
140
  * Outputs nonce fields for the post settings.
141
  * Redundant, but added for sanity.
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
42
  * Registers the meta box for the Post edit screens.
43
  *
44
  * @since 4.0.0
45
+ * @since 4.0.5 Now registers custom postbox classes.
46
+ * @access private
47
  *
48
  * @param string $post_type The current Post Type.
49
  */
86
  $title = sprintf( \esc_html__( '%s SEO Settings', 'autodescription' ), $label );
87
  }
88
 
89
+ $box_id = 'tsf-inpost-box';
90
+ // Implies `\get_current_screen()->id`. Is always 'post'.
91
+ $screen_id = 'post';
92
+
93
+ \add_meta_box( $box_id, $title, __CLASS__ . '::_meta_box', $post_type, $context, $priority, [] );
94
+ \add_filter( "postbox_classes_{$screen_id}_{$box_id}", __CLASS__ . '::_add_postbox_class' );
95
  }
96
 
97
  /**
143
  \do_action( 'the_seo_framework_pro_page_inpost_box' );
144
  }
145
 
146
+ /**
147
+ * Adds a Gutenberg/Block-editor box class.
148
+ *
149
+ * @since 4.0.5
150
+ * @access private
151
+ *
152
+ * @param array $classes The registered postbox classes.
153
+ * @return array
154
+ */
155
+ public static function _add_postbox_class( $classes = [] ) {
156
+
157
+ if ( \the_seo_framework()->is_gutenberg_page() ) {
158
+ $classes[] = 'tsf-is-block-editor';
159
+ }
160
+
161
+ return $classes;
162
+ }
163
+
164
  /**
165
  * Outputs nonce fields for the post settings.
166
  * Redundant, but added for sanity.
inc/classes/bridges/scripts.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -404,7 +404,7 @@ final class Scripts {
404
  [
405
  'id' => 'tsf-settings',
406
  'type' => 'js',
407
- 'deps' => [ 'jquery', 'tsf-ays', 'tsf-title', 'tsf-description', 'tsf', 'tsf-tt', 'wp-color-picker' ],
408
  'autoload' => true,
409
  'name' => 'settings',
410
  'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
@@ -425,6 +425,9 @@ final class Scripts {
425
  ],
426
  ],
427
  ],
 
 
 
428
  ],
429
  [
430
  'id' => 'tsf-settings',
@@ -923,13 +926,13 @@ final class Scripts {
923
  'id' => 'tsf-pt-gb',
924
  'name' => 'pt-gb',
925
  ];
926
- $deps = [ 'jquery', 'tsf', 'tsf-post', 'wp-hooks', 'wp-element', 'wp-components', 'wp-url', 'wp-api-fetch', 'lodash', 'react' ];
927
  } else {
928
  $vars = [
929
  'id' => 'tsf-pt',
930
  'name' => 'pt',
931
  ];
932
- $deps = [ 'jquery', 'tsf', 'tsf-post', 'tsf-tt' ];
933
  }
934
 
935
  return [
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
404
  [
405
  'id' => 'tsf-settings',
406
  'type' => 'js',
407
+ 'deps' => [ 'jquery', 'tsf-ays', 'tsf-title', 'tsf-description', 'tsf', 'tsf-tt', 'wp-color-picker', 'wp-util' ],
408
  'autoload' => true,
409
  'name' => 'settings',
410
  'base' => THE_SEO_FRAMEWORK_DIR_URL . 'lib/js/',
425
  ],
426
  ],
427
  ],
428
+ 'tmpl' => [
429
+ 'file' => $tsf->get_view_location( 'templates/settings/settings' ),
430
+ ],
431
  ],
432
  [
433
  'id' => 'tsf-settings',
926
  'id' => 'tsf-pt-gb',
927
  'name' => 'pt-gb',
928
  ];
929
+ $deps = [ 'jquery', 'tsf', 'tsf-post', 'wp-hooks', 'wp-element', 'wp-components', 'wp-url', 'wp-api-fetch', 'lodash', 'react', 'wp-util' ];
930
  } else {
931
  $vars = [
932
  'id' => 'tsf-pt',
933
  'name' => 'pt',
934
  ];
935
+ $deps = [ 'jquery', 'tsf', 'tsf-post', 'tsf-tt', 'wp-util' ];
936
  }
937
 
938
  return [
inc/classes/bridges/seobar.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -124,7 +124,7 @@ final class SeoBar extends ListTable {
124
  ] );
125
 
126
  if ( $this->doing_ajax )
127
- echo $this->get_seo_bar_ajax_script(); // phpcs:ignore, WordPress.Security.EscapeOutput
128
  }
129
 
130
  /**
@@ -148,26 +148,11 @@ final class SeoBar extends ListTable {
148
  if ( $this->column_name !== $column_name ) return $string;
149
 
150
  if ( $this->doing_ajax )
151
- $string .= $this->get_seo_bar_ajax_script();
152
 
153
  return \The_SEO_Framework\Interpreters\SeoBar::generate_bar( [
154
  'id' => $term_id,
155
  'taxonomy' => $this->taxonomy,
156
  ] ) . $string;
157
  }
158
-
159
- /**
160
- * Outputs a JS script that triggers SEO Bar updates.
161
- * This is a necessity as WordPress doesn't trigger actions on update.
162
- *
163
- * TODO bind to WordPress' function instead? Didn't we already do that?!
164
- * See: `tsfLe._hijackListeners()`; Although, that doesn't cover "adding" new items.
165
- *
166
- * @since 4.0.0
167
- *
168
- * @return string The triggering script.
169
- */
170
- private function get_seo_bar_ajax_script() {
171
- return "<script>'use strict';(()=>document.dispatchEvent(new Event('tsfLeUpdated')))();</script>";
172
- }
173
  }
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
124
  ] );
125
 
126
  if ( $this->doing_ajax )
127
+ echo $this->get_ajax_dispatch_updated_event(); // phpcs:ignore, WordPress.Security.EscapeOutput
128
  }
129
 
130
  /**
148
  if ( $this->column_name !== $column_name ) return $string;
149
 
150
  if ( $this->doing_ajax )
151
+ $string .= $this->get_ajax_dispatch_updated_event();
152
 
153
  return \The_SEO_Framework\Interpreters\SeoBar::generate_bar( [
154
  'id' => $term_id,
155
  'taxonomy' => $this->taxonomy,
156
  ] ) . $string;
157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
inc/classes/bridges/seosettings.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -51,7 +51,7 @@ final class SeoSettings {
51
  * Set any to false if you wish the meta box to be removed.
52
  *
53
  * @since 2.2.4
54
- * @since 2.8.0: Added `the_seo_framework_general_metabox` filter.
55
  */
56
  $general = (bool) \apply_filters( 'the_seo_framework_general_metabox', true );
57
  $title = (bool) \apply_filters( 'the_seo_framework_title_metabox', true );
@@ -571,6 +571,17 @@ final class SeoSettings {
571
  \the_seo_framework()->get_view( 'admin/metaboxes/social-metabox', [], 'twitter' );
572
  }
573
 
 
 
 
 
 
 
 
 
 
 
 
574
  /**
575
  * Social Metabox PostDates Tab output.
576
  *
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
51
  * Set any to false if you wish the meta box to be removed.
52
  *
53
  * @since 2.2.4
54
+ * @since 2.8.0 Added `the_seo_framework_general_metabox` filter.
55
  */
56
  $general = (bool) \apply_filters( 'the_seo_framework_general_metabox', true );
57
  $title = (bool) \apply_filters( 'the_seo_framework_title_metabox', true );
571
  \the_seo_framework()->get_view( 'admin/metaboxes/social-metabox', [], 'twitter' );
572
  }
573
 
574
+ /**
575
+ * Social Metabox oEmbed Tab output.
576
+ *
577
+ * @since 4.0.5
578
+ * @access private
579
+ * @see static::social_metabox() Callback for Social Settings box.
580
+ */
581
+ public static function _social_metabox_oembed_tab() {
582
+ \the_seo_framework()->get_view( 'admin/metaboxes/social-metabox', [], 'oembed' );
583
+ }
584
+
585
  /**
586
  * Social Metabox PostDates Tab output.
587
  *
inc/classes/bridges/sitemap.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/bridges/termsettings.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Bridges;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/builders/images.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -107,9 +107,11 @@ final class Images {
107
  * Generates image URLs and IDs from the content.
108
  *
109
  * @since 4.0.0
 
 
110
  * @generator
111
- * TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
112
- * Combine query, instead of using WP API? Only do that for the first image, instead?
113
  *
114
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
115
  * Leave null to autodetermine query.
@@ -139,6 +141,15 @@ final class Images {
139
 
140
  // strlen( '<img src=a>' ) === 11; yes, that's a valid self-closing tag with a relative source.
141
  if ( strlen( $content ) > 10 && false !== stripos( $content, '<img' ) ) {
 
 
 
 
 
 
 
 
 
142
  preg_match_all(
143
  '/<img[^>]+src=(\"|\')?([^\"\'>\s]+)\1?.*?>/mi',
144
  $content,
@@ -148,12 +159,22 @@ final class Images {
148
  }
149
 
150
  if ( $matches ) {
 
151
  foreach ( $matches as $match ) {
152
  // Assume every URL to be correct? Yes. WordPress assumes that too.
 
 
 
 
 
 
153
  yield [
154
- 'url' => $match[2] ?: '',
155
  'id' => 0,
156
  ];
 
 
 
157
  }
158
  } else {
159
  yield [
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
107
  * Generates image URLs and IDs from the content.
108
  *
109
  * @since 4.0.0
110
+ * @since 4.0.5 1. Now strips tags before looking for images.
111
+ * 2. Now only yields at most 5 images.
112
  * @generator
113
+ * @TODO consider matching these images with wp-content/uploads items via database calls, which is heavy...
114
+ * Combine query, instead of using WP API? Only do that for the first image, instead?
115
  *
116
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
117
  * Leave null to autodetermine query.
141
 
142
  // strlen( '<img src=a>' ) === 11; yes, that's a valid self-closing tag with a relative source.
143
  if ( strlen( $content ) > 10 && false !== stripos( $content, '<img' ) ) {
144
+ $content = $tsf->strip_tags_cs(
145
+ $content,
146
+ [
147
+ 'space' => [],
148
+ 'clear' =>
149
+ [ 'address', 'aside', 'blockquote', 'dd', 'dl', 'dt', 'fieldset', 'figcaption', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'nav', 'ol', 'pre', 'table', 'tfoot', 'ul', 'bdo', 'br', 'button', 'canvas', 'code', 'hr', 'iframe', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
150
+ 'strip' => false,
151
+ ]
152
+ );
153
  preg_match_all(
154
  '/<img[^>]+src=(\"|\')?([^\"\'>\s]+)\1?.*?>/mi',
155
  $content,
159
  }
160
 
161
  if ( $matches ) {
162
+ $i = 0;
163
  foreach ( $matches as $match ) {
164
  // Assume every URL to be correct? Yes. WordPress assumes that too.
165
+ $the_match = $match[2] ?: '';
166
+
167
+ // false-esque matches, like '0', are so uncommon it's not worth dealing with them.
168
+ if ( ! $the_match )
169
+ continue;
170
+
171
  yield [
172
+ 'url' => $the_match,
173
  'id' => 0,
174
  ];
175
+
176
+ // Get no more than 5 images.
177
+ if ( ++$i > 4 ) break;
178
  }
179
  } else {
180
  yield [
inc/classes/builders/scripts.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -151,11 +151,12 @@ final class Scripts {
151
  * Prints the TSF no-js transform script, using ES2015 (ECMA-262).
152
  *
153
  * @since 4.0.0
 
154
  * @access private
155
  * @internal
156
  */
157
  public function _print_tsfjs_script() {
158
- echo "<script>(()=>{document.body.classList.replace('tsf-no-js','tsf-js');const a=0;})()</script>";
159
  }
160
 
161
  /**
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
151
  * Prints the TSF no-js transform script, using ES2015 (ECMA-262).
152
  *
153
  * @since 4.0.0
154
+ * @since 4.0.5 Put the const assignment on front, so it's prone to fail earlier.
155
  * @access private
156
  * @internal
157
  */
158
  public function _print_tsfjs_script() {
159
+ echo "<script>(()=>{const a=0;document.body.classList.replace('tsf-no-js','tsf-js')})()</script>";
160
  }
161
 
162
  /**
inc/classes/builders/seobar-page.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -51,6 +51,7 @@ final class SeoBar_Page extends SeoBar {
51
  * @abstract
52
  */
53
  protected function prime_cache() {
 
54
  static::get_cache( 'general/i18n/inputguidelines' )
55
  or static::set_cache(
56
  'general/i18n/inputguidelines',
@@ -75,6 +76,7 @@ final class SeoBar_Page extends SeoBar {
75
  ],
76
  ]
77
  );
 
78
  }
79
 
80
  /**
@@ -124,6 +126,7 @@ final class SeoBar_Page extends SeoBar {
124
  * Runs title tests.
125
  *
126
  * @since 4.0.0
 
127
  *
128
  * @return array $item : {
129
  * string $symbol : The displayed symbol that identifies your bar.
@@ -148,7 +151,11 @@ final class SeoBar_Page extends SeoBar {
148
  ],
149
  'assess' => [
150
  'empty' => \__( 'No title could be fetched.', 'autodescription' ),
151
- 'untitled' => \__( 'No title could be fetched, "Untitled" is used instead.', 'autodescription' ), // TODO use [params][untitled]?
 
 
 
 
152
  'protected' => \__( 'A page protection state is added which increases the length.', 'autodescription' ),
153
  'branding' => [
154
  'not' => \__( "It's not branded. Search engines may ignore your title.", 'autodescription' ),
@@ -156,11 +163,13 @@ final class SeoBar_Page extends SeoBar {
156
  'automatic' => \__( "It's automatically branded.", 'autodescription' ),
157
  ],
158
  'duplicated' => \__( 'The blog name is found multiple times.', 'autodescription' ),
 
159
  ],
160
  'reason' => [
161
  'incomplete' => \__( 'Incomplete.', 'autodescription' ),
162
  'duplicated' => \__( 'The branding is duplicated.', 'autodescription' ),
163
  'notbranded' => \__( 'Not branded.', 'autodescription' ),
 
164
  ],
165
  'defaults' => [
166
  'generated' => [
@@ -204,6 +213,15 @@ final class SeoBar_Page extends SeoBar {
204
  $item['assess']['homepage'] = \__( 'The title inputted at the Edit Page screen is used.', 'autodescription' );
205
  }
206
  }
 
 
 
 
 
 
 
 
 
207
  } else {
208
  $item = $cache['defaults']['generated'];
209
 
@@ -262,6 +280,7 @@ final class SeoBar_Page extends SeoBar {
262
  }
263
  }
264
 
 
265
  $brand_count =
266
  strlen( $cache['params']['blogname_quoted'] )
267
  ? preg_match_all(
@@ -270,6 +289,7 @@ final class SeoBar_Page extends SeoBar {
270
  $matches
271
  )
272
  : 0;
 
273
 
274
  if ( ! $brand_count ) {
275
  // Override branding state.
@@ -326,9 +346,10 @@ final class SeoBar_Page extends SeoBar {
326
  }
327
 
328
  /**
329
- * Runs title tests.
330
  *
331
  * @since 4.0.0
 
332
  * @see test_title() for return value.
333
  *
334
  * @return array $item
@@ -355,11 +376,13 @@ final class SeoBar_Page extends SeoBar {
355
  'excerpt' => \__( "It's built using the excerpt field.", 'autodescription' ),
356
  /* translators: %s = list of duplicated words */
357
  'dupes' => \__( 'Found duplicated words: %s', 'autodescription' ),
 
358
  ],
359
  'reason' => [
360
  'empty' => \__( 'Empty.', 'autodescription' ),
361
  'founddupe' => \__( 'Found duplicated words.', 'autodescription' ),
362
  'foundmanydupe' => \__( 'Found too many duplicated words.', 'autodescription' ),
 
363
  ],
364
  'defaults' => [
365
  'generated' => [
@@ -412,6 +435,15 @@ final class SeoBar_Page extends SeoBar {
412
  $item['assess']['homepage'] = \__( 'The description inputted at the Edit Page screen is used.', 'autodescription' );
413
  }
414
  }
 
 
 
 
 
 
 
 
 
415
  } elseif ( ! static::$tsf->is_auto_description_enabled( $desc_args ) ) {
416
  $item = $cache['defaults']['emptynoauto'];
417
 
@@ -521,7 +553,7 @@ final class SeoBar_Page extends SeoBar {
521
  }
522
 
523
  /**
524
- * Runs description tests.
525
  *
526
  * @since 4.0.0
527
  * @see test_title() for return value.
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
51
  * @abstract
52
  */
53
  protected function prime_cache() {
54
+ // phpcs:disable, PEAR.Functions.FunctionCallSignature.Indent -- False negative.
55
  static::get_cache( 'general/i18n/inputguidelines' )
56
  or static::set_cache(
57
  'general/i18n/inputguidelines',
76
  ],
77
  ]
78
  );
79
+ // phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent -- False negative.
80
  }
81
 
82
  /**
126
  * Runs title tests.
127
  *
128
  * @since 4.0.0
129
+ * @since 4.0.5 Added syntax test.
130
  *
131
  * @return array $item : {
132
  * string $symbol : The displayed symbol that identifies your bar.
151
  ],
152
  'assess' => [
153
  'empty' => \__( 'No title could be fetched.', 'autodescription' ),
154
+ 'untitled' => sprintf(
155
+ /* translators: %s = "Untitled" */
156
+ \__( 'No title could be fetched, "%s" is used instead.', 'autodescription' ),
157
+ static::$tsf->get_static_untitled_title()
158
+ ),
159
  'protected' => \__( 'A page protection state is added which increases the length.', 'autodescription' ),
160
  'branding' => [
161
  'not' => \__( "It's not branded. Search engines may ignore your title.", 'autodescription' ),
163
  'automatic' => \__( "It's automatically branded.", 'autodescription' ),
164
  ],
165
  'duplicated' => \__( 'The blog name is found multiple times.', 'autodescription' ),
166
+ 'syntax' => \__( "Markup syntax was found that isn't transformed. Consider replacing it with static input.", 'autodescription' ),
167
  ],
168
  'reason' => [
169
  'incomplete' => \__( 'Incomplete.', 'autodescription' ),
170
  'duplicated' => \__( 'The branding is duplicated.', 'autodescription' ),
171
  'notbranded' => \__( 'Not branded.', 'autodescription' ),
172
+ 'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
173
  ],
174
  'defaults' => [
175
  'generated' => [
213
  $item['assess']['homepage'] = \__( 'The title inputted at the Edit Page screen is used.', 'autodescription' );
214
  }
215
  }
216
+
217
+ if ( static::$tsf->has_yoast_syntax( $title_part ) ) {
218
+ $item['status'] = \The_SEO_Framework\Interpreters\SeoBar::STATE_BAD;
219
+ $item['reason'] = $cache['reason']['syntax'];
220
+ $item['assess']['syntax'] = $cache['assess']['syntax'];
221
+
222
+ // Further assessments must be made later. Halt assertion here to prevent confusion.
223
+ return $item;
224
+ }
225
  } else {
226
  $item = $cache['defaults']['generated'];
227
 
280
  }
281
  }
282
 
283
+ // phpcs:disable, PEAR.Functions.FunctionCallSignature.Indent
284
  $brand_count =
285
  strlen( $cache['params']['blogname_quoted'] )
286
  ? preg_match_all(
289
  $matches
290
  )
291
  : 0;
292
+ // phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent
293
 
294
  if ( ! $brand_count ) {
295
  // Override branding state.
346
  }
347
 
348
  /**
349
+ * Runs description tests.
350
  *
351
  * @since 4.0.0
352
+ * @since 4.0.5 Added syntax test.
353
  * @see test_title() for return value.
354
  *
355
  * @return array $item
376
  'excerpt' => \__( "It's built using the excerpt field.", 'autodescription' ),
377
  /* translators: %s = list of duplicated words */
378
  'dupes' => \__( 'Found duplicated words: %s', 'autodescription' ),
379
+ 'syntax' => \__( "Markup syntax was found that isn't transformed. Consider replacing it with static input.", 'autodescription' ),
380
  ],
381
  'reason' => [
382
  'empty' => \__( 'Empty.', 'autodescription' ),
383
  'founddupe' => \__( 'Found duplicated words.', 'autodescription' ),
384
  'foundmanydupe' => \__( 'Found too many duplicated words.', 'autodescription' ),
385
+ 'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
386
  ],
387
  'defaults' => [
388
  'generated' => [
435
  $item['assess']['homepage'] = \__( 'The description inputted at the Edit Page screen is used.', 'autodescription' );
436
  }
437
  }
438
+
439
+ if ( static::$tsf->has_yoast_syntax( $desc ) ) {
440
+ $item['status'] = \The_SEO_Framework\Interpreters\SeoBar::STATE_BAD;
441
+ $item['reason'] = $cache['reason']['syntax'];
442
+ $item['assess']['syntax'] = $cache['assess']['syntax'];
443
+
444
+ // Further assessments must be made later. Halt assertion here to prevent confusion.
445
+ return $item;
446
+ }
447
  } elseif ( ! static::$tsf->is_auto_description_enabled( $desc_args ) ) {
448
  $item = $cache['defaults']['emptynoauto'];
449
 
553
  }
554
 
555
  /**
556
+ * Runs indexing tests.
557
  *
558
  * @since 4.0.0
559
  * @see test_title() for return value.
inc/classes/builders/seobar-term.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -51,6 +51,7 @@ final class SeoBar_Term extends SeoBar {
51
  * @abstract
52
  */
53
  protected function prime_cache() {
 
54
  static::get_cache( 'general/i18n/inputguidelines' )
55
  or static::set_cache(
56
  'general/i18n/inputguidelines',
@@ -85,6 +86,7 @@ final class SeoBar_Term extends SeoBar {
85
  ],
86
  ]
87
  );
 
88
  }
89
 
90
  /**
@@ -137,6 +139,9 @@ final class SeoBar_Term extends SeoBar {
137
  * Runs title tests.
138
  *
139
  * @since 4.0.0
 
 
 
140
  *
141
  * @return array $item : {
142
  * string $symbol : The displayed symbol that identifies your bar.
@@ -155,14 +160,17 @@ final class SeoBar_Term extends SeoBar {
155
  'params' => [
156
  'untitled' => static::$tsf->get_static_untitled_title(),
157
  'blogname_quoted' => preg_quote( static::$tsf->get_blogname(), '/' ),
158
- 'prefixed' => static::$tsf->use_generated_archive_prefix(),
159
  /* translators: 1 = An assessment, 2 = Disclaimer, e.g. "take it with a grain of salt" */
160
  'disclaim' => \__( '%1$s (%2$s)', 'autodescription' ),
161
  'estimated' => \__( 'Estimated from the number of characters found. The pixel counter asserts the true length.', 'autodescription' ),
162
  ],
163
  'assess' => [
164
  'empty' => \__( 'No title could be fetched.', 'autodescription' ),
165
- 'untitled' => \__( 'No title could be fetched, "Untitled" is used instead.', 'autodescription' ), // TODO use [params][untitled]?
 
 
 
 
166
  'prefixed' => \__( 'A term label prefix is automatically added which increases the length.', 'autodescription' ),
167
  'branding' => [
168
  'not' => \__( "It's not branded. Search engines may ignore your title.", 'autodescription' ),
@@ -170,11 +178,13 @@ final class SeoBar_Term extends SeoBar {
170
  'automatic' => \__( "It's automatically branded.", 'autodescription' ),
171
  ],
172
  'duplicated' => \__( 'The blog name is found multiple times.', 'autodescription' ),
 
173
  ],
174
  'reason' => [
175
  'incomplete' => \__( 'Incomplete.', 'autodescription' ),
176
  'duplicated' => \__( 'The branding is duplicated.', 'autodescription' ),
177
  'notbranded' => \__( 'Not branded.', 'autodescription' ),
 
178
  ],
179
  'defaults' => [
180
  'generated' => [
@@ -210,11 +220,19 @@ final class SeoBar_Term extends SeoBar {
210
 
211
  if ( strlen( $title_part ) ) {
212
  $item = $cache['defaults']['custom'];
 
 
 
 
 
 
 
 
 
213
  } else {
214
  $item = $cache['defaults']['generated'];
215
 
216
- // Move this to defaults cache? It'll make the code unreadable, though...
217
- if ( $cache['params']['prefixed'] ) {
218
  $item['assess']['prefixed'] = $cache['assess']['prefixed'];
219
  }
220
 
@@ -253,6 +271,7 @@ final class SeoBar_Term extends SeoBar {
253
  $item['assess']['branding'] = $cache['assess']['branding']['manual'];
254
  }
255
 
 
256
  $brand_count =
257
  strlen( $cache['params']['blogname_quoted'] )
258
  ? preg_match_all(
@@ -261,6 +280,7 @@ final class SeoBar_Term extends SeoBar {
261
  $matches
262
  )
263
  : 0;
 
264
 
265
  if ( ! $brand_count ) {
266
  // Override branding state.
@@ -317,9 +337,10 @@ final class SeoBar_Term extends SeoBar {
317
  }
318
 
319
  /**
320
- * Runs title tests.
321
  *
322
  * @since 4.0.0
 
323
  * @see test_title() for return value.
324
  *
325
  * @return array $item
@@ -340,14 +361,16 @@ final class SeoBar_Term extends SeoBar {
340
  'dupe_short' => (int) \apply_filters( 'the_seo_framework_bother_me_desc_length', 3 ),
341
  ],
342
  'assess' => [
343
- 'empty' => \__( 'No description could be generated.', 'autodescription' ),
344
  /* translators: %s = list of duplicated words */
345
- 'dupes' => \__( 'Found duplicated words: %s', 'autodescription' ),
 
346
  ],
347
  'reason' => [
348
  'empty' => \__( 'Empty.', 'autodescription' ),
349
  'founddupe' => \__( 'Found duplicated words.', 'autodescription' ),
350
  'foundmanydupe' => \__( 'Found too many duplicated words.', 'autodescription' ),
 
351
  ],
352
  'defaults' => [
353
  'generated' => [
@@ -392,6 +415,15 @@ final class SeoBar_Term extends SeoBar {
392
 
393
  if ( strlen( $desc ) ) {
394
  $item = $cache['defaults']['custom'];
 
 
 
 
 
 
 
 
 
395
  } elseif ( ! static::$tsf->is_auto_description_enabled( $desc_args ) ) {
396
  $item = $cache['defaults']['emptynoauto'];
397
 
@@ -491,7 +523,7 @@ final class SeoBar_Term extends SeoBar {
491
  }
492
 
493
  /**
494
- * Runs description tests.
495
  *
496
  * @since 4.0.0
497
  * @see test_title() for return value.
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
51
  * @abstract
52
  */
53
  protected function prime_cache() {
54
+ // phpcs:disable, PEAR.Functions.FunctionCallSignature.Indent -- False negative.
55
  static::get_cache( 'general/i18n/inputguidelines' )
56
  or static::set_cache(
57
  'general/i18n/inputguidelines',
86
  ],
87
  ]
88
  );
89
+ // phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent
90
  }
91
 
92
  /**
139
  * Runs title tests.
140
  *
141
  * @since 4.0.0
142
+ * @since 4.0.5 1. Removed `['params']['prefixed'] from cache.
143
+ * 2. Now tests for term title prefix per state.
144
+ * 3. Added syntax test.
145
  *
146
  * @return array $item : {
147
  * string $symbol : The displayed symbol that identifies your bar.
160
  'params' => [
161
  'untitled' => static::$tsf->get_static_untitled_title(),
162
  'blogname_quoted' => preg_quote( static::$tsf->get_blogname(), '/' ),
 
163
  /* translators: 1 = An assessment, 2 = Disclaimer, e.g. "take it with a grain of salt" */
164
  'disclaim' => \__( '%1$s (%2$s)', 'autodescription' ),
165
  'estimated' => \__( 'Estimated from the number of characters found. The pixel counter asserts the true length.', 'autodescription' ),
166
  ],
167
  'assess' => [
168
  'empty' => \__( 'No title could be fetched.', 'autodescription' ),
169
+ 'untitled' => sprintf(
170
+ /* translators: %s = "Untitled" */
171
+ \__( 'No title could be fetched, "%s" is used instead.', 'autodescription' ),
172
+ static::$tsf->get_static_untitled_title()
173
+ ),
174
  'prefixed' => \__( 'A term label prefix is automatically added which increases the length.', 'autodescription' ),
175
  'branding' => [
176
  'not' => \__( "It's not branded. Search engines may ignore your title.", 'autodescription' ),
178
  'automatic' => \__( "It's automatically branded.", 'autodescription' ),
179
  ],
180
  'duplicated' => \__( 'The blog name is found multiple times.', 'autodescription' ),
181
+ 'syntax' => \__( "Markup syntax was found that isn't transformed. Consider replacing it with static input.", 'autodescription' ),
182
  ],
183
  'reason' => [
184
  'incomplete' => \__( 'Incomplete.', 'autodescription' ),
185
  'duplicated' => \__( 'The branding is duplicated.', 'autodescription' ),
186
  'notbranded' => \__( 'Not branded.', 'autodescription' ),
187
+ 'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
188
  ],
189
  'defaults' => [
190
  'generated' => [
220
 
221
  if ( strlen( $title_part ) ) {
222
  $item = $cache['defaults']['custom'];
223
+
224
+ if ( static::$tsf->has_yoast_syntax( $title_part, false ) ) {
225
+ $item['status'] = \The_SEO_Framework\Interpreters\SeoBar::STATE_BAD;
226
+ $item['reason'] = $cache['reason']['syntax'];
227
+ $item['assess']['syntax'] = $cache['assess']['syntax'];
228
+
229
+ // Further assessments must be made later. Halt assertion here to prevent confusion.
230
+ return $item;
231
+ }
232
  } else {
233
  $item = $cache['defaults']['generated'];
234
 
235
+ if ( static::$tsf->use_generated_archive_prefix( $this->query_cache['term'] ) ) {
 
236
  $item['assess']['prefixed'] = $cache['assess']['prefixed'];
237
  }
238
 
271
  $item['assess']['branding'] = $cache['assess']['branding']['manual'];
272
  }
273
 
274
+ // phpcs:disable, PEAR.Functions.FunctionCallSignature.Indent
275
  $brand_count =
276
  strlen( $cache['params']['blogname_quoted'] )
277
  ? preg_match_all(
280
  $matches
281
  )
282
  : 0;
283
+ // phpcs:enable, PEAR.Functions.FunctionCallSignature.Indent
284
 
285
  if ( ! $brand_count ) {
286
  // Override branding state.
337
  }
338
 
339
  /**
340
+ * Runs description tests.
341
  *
342
  * @since 4.0.0
343
+ * @since 4.0.5 Added syntax test.
344
  * @see test_title() for return value.
345
  *
346
  * @return array $item
361
  'dupe_short' => (int) \apply_filters( 'the_seo_framework_bother_me_desc_length', 3 ),
362
  ],
363
  'assess' => [
364
+ 'empty' => \__( 'No description could be generated.', 'autodescription' ),
365
  /* translators: %s = list of duplicated words */
366
+ 'dupes' => \__( 'Found duplicated words: %s', 'autodescription' ),
367
+ 'syntax' => \__( "Markup syntax was found that isn't transformed. Consider replacing it with static input.", 'autodescription' ),
368
  ],
369
  'reason' => [
370
  'empty' => \__( 'Empty.', 'autodescription' ),
371
  'founddupe' => \__( 'Found duplicated words.', 'autodescription' ),
372
  'foundmanydupe' => \__( 'Found too many duplicated words.', 'autodescription' ),
373
+ 'syntax' => \__( 'Found markup syntax.', 'autodescription' ),
374
  ],
375
  'defaults' => [
376
  'generated' => [
415
 
416
  if ( strlen( $desc ) ) {
417
  $item = $cache['defaults']['custom'];
418
+
419
+ if ( static::$tsf->has_yoast_syntax( $desc ) ) {
420
+ $item['status'] = \The_SEO_Framework\Interpreters\SeoBar::STATE_BAD;
421
+ $item['reason'] = $cache['reason']['syntax'];
422
+ $item['assess']['syntax'] = $cache['assess']['syntax'];
423
+
424
+ // Further assessments must be made later. Halt assertion here to prevent confusion.
425
+ return $item;
426
+ }
427
  } elseif ( ! static::$tsf->is_auto_description_enabled( $desc_args ) ) {
428
  $item = $cache['defaults']['emptynoauto'];
429
 
523
  }
524
 
525
  /**
526
+ * Runs indexing tests.
527
  *
528
  * @since 4.0.0
529
  * @see test_title() for return value.
inc/classes/builders/seobar.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/builders/sitemap-base.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -418,8 +418,8 @@ class Sitemap_Base extends Sitemap {
418
  * Retrieves additional URLs and builds items from them.
419
  *
420
  * @since 4.0.0
421
- * @since 4.0.1: 1. Converted to generator and iterator. Therefore, renamed function.
422
- * 2. Now actually does something.
423
  * @generator
424
  * @iterator
425
  *
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
418
  * Retrieves additional URLs and builds items from them.
419
  *
420
  * @since 4.0.0
421
+ * @since 4.0.1 : 1. Converted to generator and iterator. Therefore, renamed function.
422
+ * 2. Now actually does something.
423
  * @generator
424
  * @iterator
425
  *
inc/classes/builders/sitemap.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Builders;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/cache.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -200,6 +200,7 @@ class Cache extends Site_Options {
200
  * @since 2.8.0
201
  * @since 2.9.3 $type = 'front' now also returns true.
202
  * @since 3.1.0 Added action.
 
203
  *
204
  * @param string $type The type
205
  * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
@@ -217,7 +218,6 @@ class Cache extends Site_Options {
217
  $front_id = $this->get_the_front_page_ID();
218
 
219
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
220
- $this->delete_ld_json_transient( $front_id, '', 'frontpage' );
221
  $success = true;
222
  break;
223
 
@@ -238,7 +238,6 @@ class Cache extends Site_Options {
238
  }
239
 
240
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, '', $post_type ) );
241
- $this->delete_ld_json_transient( $id, '', $post_type );
242
  $success = true;
243
  }
244
  break;
@@ -246,13 +245,11 @@ class Cache extends Site_Options {
246
  //* Careful, this can only run on archive pages. For now.
247
  case 'term':
248
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, $args['term'], 'term' ) );
249
- $this->delete_ld_json_transient( $id, $args['term'], 'term' );
250
  $success = true;
251
  break;
252
 
253
  case 'author':
254
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, 'author', 'author' ) );
255
- $this->delete_ld_json_transient( $id, 'author', 'author' );
256
  $success = true;
257
  break;
258
 
@@ -412,7 +409,7 @@ class Cache extends Site_Options {
412
  *
413
  * @param string $key The Object cache key.
414
  * @param string $group The Object cache group.
415
- * @return mixed wp_cache_delete if object caching is allowed. False otherwise.
416
  */
417
  public function object_cache_delete( $key, $group = 'the_seo_framework' ) {
418
 
@@ -448,35 +445,6 @@ class Cache extends Site_Options {
448
  return $this->get_option( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
449
  }
450
 
451
- /**
452
- * Returns ld_json transients for page ID.
453
- *
454
- * @since 3.1.0
455
- * @since 3.1.1 : The first parameter is now optional.
456
- *
457
- * @param int|string|bool $id The Taxonomy or Post ID. If false it will generate for the blog page.
458
- * @param string $taxonomy The taxonomy name.
459
- * @param string|null $type The post type.
460
- * @return string The ld_json cache key.
461
- */
462
- public function get_ld_json_transient_name( $id = 0, $taxonomy = '', $type = null ) {
463
-
464
- if ( ! $this->get_option( 'cache_meta_schema' ) )
465
- return '';
466
-
467
- $cache_key = $this->generate_cache_key( $id, $taxonomy, $type );
468
-
469
- $revision = '7';
470
-
471
- /**
472
- * Change key based on options.
473
- */
474
- $options = $this->enable_ld_json_breadcrumbs() ? '1' : '0';
475
- $options .= $this->enable_ld_json_searchbox() ? '1' : '0';
476
-
477
- return 'tsf_' . $revision . '_' . $options . '_ldjs_' . $cache_key;
478
- }
479
-
480
  /**
481
  * Generate transient key based on query vars or input variables.
482
  *
@@ -577,7 +545,7 @@ class Cache extends Site_Options {
577
 
578
  //* Temporarily disable caches to prevent database spam.
579
  $this->the_seo_framework_use_transients = false;
580
- $this->use_object_cache = false;
581
 
582
  $the_id = 'unix_' . $unix;
583
  }
@@ -679,34 +647,24 @@ class Cache extends Site_Options {
679
  switch ( $type ) :
680
  case 'author':
681
  return $this->add_cache_key_suffix( 'author_' . $page_id );
682
- break;
683
  case 'frontpage':
684
  return $this->add_cache_key_suffix( $this->generate_front_page_cache_key() );
685
- break;
686
  case 'page':
687
  return $this->add_cache_key_suffix( 'page_' . $page_id );
688
- break;
689
  case 'post':
690
  return $this->add_cache_key_suffix( 'post_' . $page_id );
691
- break;
692
  case 'attachment':
693
  return $this->add_cache_key_suffix( 'attach_' . $page_id );
694
- break;
695
  case 'singular':
696
  return $this->add_cache_key_suffix( 'singular_' . $page_id );
697
- break;
698
  case 'term':
699
  return $this->add_cache_key_suffix( $this->generate_taxonomical_cache_key( $page_id, $taxonomy ) );
700
- break;
701
  case 'ping':
702
  return $this->add_cache_key_suffix( 'tsf_throttle_ping' );
703
  default:
704
  $this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
705
  return $this->add_cache_key_suffix( \esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
706
- break;
707
  endswitch;
708
-
709
- return false;
710
  }
711
 
712
  /**
@@ -896,29 +854,6 @@ class Cache extends Site_Options {
896
  return $run = true;
897
  }
898
 
899
- /**
900
- * Deletes transient for the LD+Json scripts on requests.
901
- *
902
- * @since 2.4.2
903
- * @since 2.8.0 Now listens to option 'cache_meta_schema' before deleting transient.
904
- * @since 2.9.1 Now no longer sets object property $this->ld_json_transient.
905
- * @since 2.9.4 Removed cache.
906
- *
907
- * @param mixed $page_id The page ID or identifier.
908
- * @param string $taxonomy The tt name.
909
- * @param string|null $type The post type.
910
- * @return bool true
911
- */
912
- public function delete_ld_json_transient( $page_id, $taxonomy = '', $type = null ) {
913
-
914
- if ( $this->get_option( 'cache_meta_schema' ) ) {
915
- $transient = $this->get_ld_json_transient_name( $page_id, $taxonomy, $type );
916
- $transient and \delete_transient( $transient );
917
- }
918
-
919
- return true;
920
- }
921
-
922
  /**
923
  * Builds and returns the excluded post IDs transient.
924
  * The transients are autoloaded, as no expiration is set.
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
200
  * @since 2.8.0
201
  * @since 2.9.3 $type = 'front' now also returns true.
202
  * @since 3.1.0 Added action.
203
+ * @since 4.0.5 Removed all JSON-LD transient clear calls.
204
  *
205
  * @param string $type The type
206
  * @param int $id The post, page or TT ID. Defaults to $this->get_the_real_ID().
218
  $front_id = $this->get_the_front_page_ID();
219
 
220
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $front_id, '', 'frontpage' ) );
 
221
  $success = true;
222
  break;
223
 
238
  }
239
 
240
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, '', $post_type ) );
 
241
  $success = true;
242
  }
243
  break;
245
  //* Careful, this can only run on archive pages. For now.
246
  case 'term':
247
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, $args['term'], 'term' ) );
 
248
  $success = true;
249
  break;
250
 
251
  case 'author':
252
  $this->object_cache_delete( $this->get_meta_output_cache_key_by_type( $id, 'author', 'author' ) );
 
253
  $success = true;
254
  break;
255
 
409
  *
410
  * @param string $key The Object cache key.
411
  * @param string $group The Object cache group.
412
+ * @return mixed `wp_cache_delete()` if object caching is allowed. False otherwise.
413
  */
414
  public function object_cache_delete( $key, $group = 'the_seo_framework' ) {
415
 
445
  return $this->get_option( 'cache_sitemap' ) ? $this->add_cache_key_suffix( 'tsf_sitemap_' . $sitemap_revision ) : '';
446
  }
447
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
448
  /**
449
  * Generate transient key based on query vars or input variables.
450
  *
545
 
546
  //* Temporarily disable caches to prevent database spam.
547
  $this->the_seo_framework_use_transients = false;
548
+ $this->use_object_cache = false;
549
 
550
  $the_id = 'unix_' . $unix;
551
  }
647
  switch ( $type ) :
648
  case 'author':
649
  return $this->add_cache_key_suffix( 'author_' . $page_id );
 
650
  case 'frontpage':
651
  return $this->add_cache_key_suffix( $this->generate_front_page_cache_key() );
 
652
  case 'page':
653
  return $this->add_cache_key_suffix( 'page_' . $page_id );
 
654
  case 'post':
655
  return $this->add_cache_key_suffix( 'post_' . $page_id );
 
656
  case 'attachment':
657
  return $this->add_cache_key_suffix( 'attach_' . $page_id );
 
658
  case 'singular':
659
  return $this->add_cache_key_suffix( 'singular_' . $page_id );
 
660
  case 'term':
661
  return $this->add_cache_key_suffix( $this->generate_taxonomical_cache_key( $page_id, $taxonomy ) );
 
662
  case 'ping':
663
  return $this->add_cache_key_suffix( 'tsf_throttle_ping' );
664
  default:
665
  $this->_doing_it_wrong( __METHOD__, 'Third parameter must be a known type.', '2.6.5' );
666
  return $this->add_cache_key_suffix( \esc_sql( $type . '_' . $page_id . '_' . $taxonomy ) );
 
667
  endswitch;
 
 
668
  }
669
 
670
  /**
854
  return $run = true;
855
  }
856
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
857
  /**
858
  * Builds and returns the excluded post IDs transient.
859
  * The transients are autoloaded, as no expiration is set.
inc/classes/core.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -213,15 +213,17 @@ class Core {
213
  */
214
  public function _add_plugin_action_links( $links = [] ) {
215
 
216
- if ( $this->load_options )
217
  $tsf_links['settings'] = sprintf(
218
  '<a href="%s">%s</a>',
219
  \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ),
220
  \esc_html__( 'Settings', 'autodescription' )
221
  );
 
222
 
223
  $tsf_links['about'] = sprintf(
224
- '<a href="https://theseoframework.com/about-us/" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
 
225
  \esc_html_x( 'About', 'About us', 'autodescription' )
226
  );
227
  $tsf_links['tsfem'] = sprintf(
@@ -256,25 +258,32 @@ class Core {
256
  return array_merge(
257
  $plugin_meta,
258
  [
259
- 'docs' => vsprintf(
 
 
 
 
 
 
 
260
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
261
  [
262
  'https://tsf.fyi/docs',
263
  \esc_html__( 'View documentation', 'autodescription' ),
264
  ]
265
  ),
266
- 'API' => vsprintf(
267
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
268
  [
269
  'https://tsf.fyi/docs/api',
270
  \esc_html__( 'View API docs', 'autodescription' ),
271
  ]
272
  ),
273
- 'EM' => vsprintf(
274
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
275
  [
276
  'https://tsf.fyi/extension-manager',
277
- $_get_em ? \esc_html_x( 'Get the Extension Manager', 'Extension Manager is a product name; do not translate it.', 'autodescription' ) : 'Extension Manager',
278
  ]
279
  ),
280
  ]
@@ -345,6 +354,7 @@ class Core {
345
  * Checks if blog is public through WordPress core settings.
346
  *
347
  * @since 2.6.0
 
348
  * @staticvar bool $cache
349
  *
350
  * @return bool True is blog is public.
@@ -353,13 +363,7 @@ class Core {
353
 
354
  static $cache = null;
355
 
356
- if ( isset( $cache ) )
357
- return $cache;
358
-
359
- if ( '1' === \get_option( 'blog_public' ) )
360
- return $cache = true;
361
-
362
- return $cache = false;
363
  }
364
 
365
  /**
@@ -497,20 +501,19 @@ class Core {
497
 
498
  static $old_tz = null;
499
 
500
- // phpcs:ignore, WordPress.WP.TimezoneChange
501
  $old_tz = $old_tz ?: date_default_timezone_get() ?: 'UTC';
502
 
503
  if ( $reset ) {
504
  $_revert_tz = $old_tz;
505
  $old_tz = null;
506
- // phpcs:ignore, WordPress.WP.TimezoneChange
507
  return date_default_timezone_set( $_revert_tz );
508
  }
509
 
510
  if ( empty( $tzstring ) )
511
  $tzstring = $this->get_timezone_string( true ) ?: $old_tz;
512
 
513
- // phpcs:ignore, WordPress.WP.TimezoneChange
514
  return date_default_timezone_set( $tzstring );
515
  }
516
 
@@ -674,7 +677,7 @@ class Core {
674
  * @since 2.8.0
675
  * @since 2.9.0 Now adds a little more relative softness based on rel_lum.
676
  * @since 2.9.2 (Typo): Renamed from 'get_relatitve_fontcolor' to 'get_relative_fontcolor'.
677
- * @since 3.0.4 : Now uses WCAG's relative luminance formula
678
  * @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
679
  * @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
680
  *
@@ -740,6 +743,7 @@ class Core {
740
  * Returns sitemap color scheme.
741
  *
742
  * @since 2.8.0
 
743
  *
744
  * @param bool $get_defaults Whether to get the default colors.
745
  * @return array The sitemap colors.
@@ -748,8 +752,8 @@ class Core {
748
 
749
  if ( $get_defaults ) {
750
  $colors = [
751
- 'main' => '#333',
752
- 'accent' => '#00cd98',
753
  ];
754
  } else {
755
  $main = $this->s_color_hex( $this->get_option( 'sitemap_color_main' ) );
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
213
  */
214
  public function _add_plugin_action_links( $links = [] ) {
215
 
216
+ if ( $this->load_options ) {
217
  $tsf_links['settings'] = sprintf(
218
  '<a href="%s">%s</a>',
219
  \esc_url( \admin_url( 'admin.php?page=' . $this->seo_settings_page_slug ) ),
220
  \esc_html__( 'Settings', 'autodescription' )
221
  );
222
+ }
223
 
224
  $tsf_links['about'] = sprintf(
225
+ '<a href="%s" rel="noreferrer noopener" target="_blank">%s</a>',
226
+ 'https://theseoframework.com/about-us/',
227
  \esc_html_x( 'About', 'About us', 'autodescription' )
228
  );
229
  $tsf_links['tsfem'] = sprintf(
258
  return array_merge(
259
  $plugin_meta,
260
  [
261
+ 'support' => vsprintf(
262
+ '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
263
+ [
264
+ 'https://tsf.fyi/support',
265
+ \esc_html__( 'Get support', 'autodescription' ),
266
+ ]
267
+ ),
268
+ 'docs' => vsprintf(
269
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
270
  [
271
  'https://tsf.fyi/docs',
272
  \esc_html__( 'View documentation', 'autodescription' ),
273
  ]
274
  ),
275
+ 'API' => vsprintf(
276
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
277
  [
278
  'https://tsf.fyi/docs/api',
279
  \esc_html__( 'View API docs', 'autodescription' ),
280
  ]
281
  ),
282
+ 'EM' => vsprintf(
283
  '<a href="%s" rel="noreferrer noopener nofollow" target="_blank">%s</a>',
284
  [
285
  'https://tsf.fyi/extension-manager',
286
+ $_get_em ? \esc_html_x( 'Get Extension Manager', 'Extension Manager is a product name; do not translate it.', 'autodescription' ) : 'Extension Manager',
287
  ]
288
  ),
289
  ]
354
  * Checks if blog is public through WordPress core settings.
355
  *
356
  * @since 2.6.0
357
+ * @since 4.0.5 Can now test for non-sanitized 'blog_public' option states.
358
  * @staticvar bool $cache
359
  *
360
  * @return bool True is blog is public.
363
 
364
  static $cache = null;
365
 
366
+ return isset( $cache ) ? $cache : $cache = (bool) \get_option( 'blog_public' );
 
 
 
 
 
 
367
  }
368
 
369
  /**
501
 
502
  static $old_tz = null;
503
 
 
504
  $old_tz = $old_tz ?: date_default_timezone_get() ?: 'UTC';
505
 
506
  if ( $reset ) {
507
  $_revert_tz = $old_tz;
508
  $old_tz = null;
509
+ // phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
510
  return date_default_timezone_set( $_revert_tz );
511
  }
512
 
513
  if ( empty( $tzstring ) )
514
  $tzstring = $this->get_timezone_string( true ) ?: $old_tz;
515
 
516
+ // phpcs:ignore, WordPress.DateTime.RestrictedFunctions.timezone_change_date_default_timezone_set
517
  return date_default_timezone_set( $tzstring );
518
  }
519
 
677
  * @since 2.8.0
678
  * @since 2.9.0 Now adds a little more relative softness based on rel_lum.
679
  * @since 2.9.2 (Typo): Renamed from 'get_relatitve_fontcolor' to 'get_relative_fontcolor'.
680
+ * @since 3.0.4 Now uses WCAG's relative luminance formula
681
  * @link https://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
682
  * @link https://www.w3.org/WAI/GL/wiki/Relative_luminance
683
  *
743
  * Returns sitemap color scheme.
744
  *
745
  * @since 2.8.0
746
+ * @since 4.0.5 Changed default colors to be more in line with WordPress.
747
  *
748
  * @param bool $get_defaults Whether to get the default colors.
749
  * @return array The sitemap colors.
752
 
753
  if ( $get_defaults ) {
754
  $colors = [
755
+ 'main' => '#222222',
756
+ 'accent' => '#00a0d2',
757
  ];
758
  } else {
759
  $main = $this->s_color_hex( $this->get_option( 'sitemap_color_main' ) );
inc/classes/debug.class.php CHANGED
@@ -12,7 +12,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
12
 
13
  /**
14
  * The SEO Framework plugin
15
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
16
  *
17
  * This program is free software: you can redistribute it and/or modify
18
  * it under the terms of the GNU General Public License version 3 as published
@@ -493,6 +493,7 @@ final class Debug {
493
  * This won't consider hiding the output.
494
  *
495
  * @since 2.6.5
 
496
  *
497
  * @return string Wrapped SEO meta tags output.
498
  */
@@ -509,34 +510,7 @@ final class Debug {
509
  //* Start timer.
510
  $this->timer( true );
511
 
512
- $output = $tsf->robots()
513
- . $tsf->the_description()
514
- . $tsf->og_image()
515
- . $tsf->og_locale()
516
- . $tsf->og_type()
517
- . $tsf->og_title()
518
- . $tsf->og_description()
519
- . $tsf->og_url()
520
- . $tsf->og_sitename()
521
- . $tsf->facebook_publisher()
522
- . $tsf->facebook_author()
523
- . $tsf->facebook_app_id()
524
- . $tsf->article_published_time()
525
- . $tsf->article_modified_time()
526
- . $tsf->twitter_card()
527
- . $tsf->twitter_site()
528
- . $tsf->twitter_creator()
529
- . $tsf->twitter_title()
530
- . $tsf->twitter_description()
531
- . $tsf->twitter_image()
532
- . $tsf->shortlink()
533
- . $tsf->canonical()
534
- . $tsf->paged_urls()
535
- . $tsf->ld_json()
536
- . $tsf->google_site_output()
537
- . $tsf->bing_site_output()
538
- . $tsf->yandex_site_output()
539
- . $tsf->pint_site_output();
540
 
541
  $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>';
542
 
@@ -620,45 +594,57 @@ final class Debug {
620
 
621
  $tsf = \the_seo_framework();
622
 
 
623
  //* Only get true/false values.
624
- $page_id = $tsf->get_the_real_ID();
625
- $is_404 = $tsf->is_404();
626
- $is_admin = $tsf->is_admin();
627
- $is_attachment = $tsf->is_attachment();
628
- $is_archive = $tsf->is_archive();
629
- $is_term_edit = $tsf->is_term_edit();
630
- $is_post_edit = $tsf->is_post_edit();
631
- $is_wp_lists_edit = $tsf->is_wp_lists_edit();
632
- $is_author = $tsf->is_author();
633
- $is_blog_page = $tsf->is_blog_page();
634
- $is_category = $tsf->is_category();
635
- $is_date = $tsf->is_date();
636
- $is_year = $tsf->is_year();
637
- $is_month = $tsf->is_month();
638
- $is_day = $tsf->is_day();
639
- $is_feed = $tsf->is_feed();
640
- $is_real_front_page = $tsf->is_real_front_page();
641
- $is_front_page_by_id = $tsf->is_front_page_by_id( $tsf->get_the_real_ID() );
642
- $is_home = $tsf->is_home();
643
- $is_page = $tsf->is_page();
644
- $page = $tsf->page();
645
- $paged = $tsf->paged();
646
- $is_preview = $tsf->is_preview();
647
- $is_customize_preview = $tsf->is_customize_preview();
648
- $is_search = $tsf->is_search();
649
- $is_single = $tsf->is_single();
650
- $is_singular = $tsf->is_singular();
651
- $is_static_frontpage = $tsf->is_static_frontpage();
652
- $is_tag = $tsf->is_tag();
653
- $is_tax = $tsf->is_tax();
654
- $is_wc_shop = $tsf->is_wc_shop();
655
- $is_wc_product = $tsf->is_wc_product();
656
- $is_seo_settings_page = $tsf->is_seo_settings_page( true );
657
- $numpages = $tsf->numpages();
658
- $is_multipage = $tsf->is_multipage();
659
- $is_singular_archive = $tsf->is_singular_archive();
660
- $is_term_meta_capable = $tsf->is_term_meta_capable();
661
- $is_post_type_archive = \is_post_type_archive();
 
 
 
 
 
 
 
 
 
 
 
662
 
663
  //* Don't debug the class object.
664
  unset( $tsf );
12
 
13
  /**
14
  * The SEO Framework plugin
15
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
16
  *
17
  * This program is free software: you can redistribute it and/or modify
18
  * it under the terms of the GNU General Public License version 3 as published
493
  * This won't consider hiding the output.
494
  *
495
  * @since 2.6.5
496
+ * @since 4.0.5 Now obtains the real rendered HTML output, instead of estimated.
497
  *
498
  * @return string Wrapped SEO meta tags output.
499
  */
510
  //* Start timer.
511
  $this->timer( true );
512
 
513
+ $output = $tsf->get_html_output();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
 
515
  $timer = '<div style="display:inline-block;width:100%;padding:20px;border-bottom:1px solid #ccc;">Generated in: ' . number_format( $this->timer(), 5 ) . ' seconds</div>';
516
 
594
 
595
  $tsf = \the_seo_framework();
596
 
597
+ // phpcs:disable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase -- Not this file's issue.
598
  //* Only get true/false values.
599
+ $page_id = $tsf->get_the_real_ID();
600
+ $is_query_exploited = $tsf->is_query_exploited();
601
+ $query_supports_seo = $tsf->query_supports_seo() ? 'yes' : 'no';
602
+ $is_404 = $tsf->is_404();
603
+ $is_admin = $tsf->is_admin();
604
+ $is_attachment = $tsf->is_attachment();
605
+ $is_archive = $tsf->is_archive();
606
+ $is_term_edit = $tsf->is_term_edit();
607
+ $is_post_edit = $tsf->is_post_edit();
608
+ $is_wp_lists_edit = $tsf->is_wp_lists_edit();
609
+ $is_author = $tsf->is_author();
610
+ $is_blog_page = $tsf->is_blog_page();
611
+ $is_category = $tsf->is_category();
612
+ $is_date = $tsf->is_date();
613
+ $is_year = $tsf->is_year();
614
+ $is_month = $tsf->is_month();
615
+ $is_day = $tsf->is_day();
616
+ $is_feed = $tsf->is_feed();
617
+ $is_real_front_page = $tsf->is_real_front_page();
618
+ $is_front_page_by_id = $tsf->is_front_page_by_id( $page_id );
619
+ $is_home = $tsf->is_home();
620
+ $is_page = $tsf->is_page();
621
+ $page = $tsf->page();
622
+ $paged = $tsf->paged();
623
+ $is_preview = $tsf->is_preview();
624
+ $is_customize_preview = $tsf->is_customize_preview();
625
+ $is_search = $tsf->is_search();
626
+ $is_single = $tsf->is_single();
627
+ $is_singular = $tsf->is_singular();
628
+ $is_static_frontpage = $tsf->is_static_frontpage();
629
+ $is_tag = $tsf->is_tag();
630
+ $is_tax = $tsf->is_tax();
631
+ $is_shop = $tsf->is_shop();
632
+ $is_wc_shop = $tsf->is_wc_shop();
633
+ $is_product = $tsf->is_product();
634
+ $is_wc_product = $tsf->is_wc_product();
635
+ $is_seo_settings_page = $tsf->is_seo_settings_page( true );
636
+ $numpages = $tsf->numpages();
637
+ $is_multipage = $tsf->is_multipage();
638
+ $is_singular_archive = $tsf->is_singular_archive();
639
+ $is_term_meta_capable = $tsf->is_term_meta_capable();
640
+ $is_post_type_supported = $tsf->is_post_type_supported();
641
+ $get_post_type = \get_post_type();
642
+ $get_post_type_real_ID = $tsf->get_post_type_real_ID();
643
+ $admin_post_type = $tsf->get_admin_post_type();
644
+ $current_taxonomy = $tsf->get_current_taxonomy();
645
+ $is_post_type_archive = \is_post_type_archive();
646
+ $is_protected = $tsf->is_protected( $page_id );
647
+ // phpcs:enable, WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase -- Not this file's issue.
648
 
649
  //* Don't debug the class object.
650
  unset( $tsf );
inc/classes/deprecated.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -31,8 +31,8 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
31
  * Contains all deprecated functions.
32
  *
33
  * @since 2.8.0
34
- * @since 3.1.0: Removed all methods deprecated in 3.0.0.
35
- * @since 4.0.0: Removed all methods deprecated in 3.1.0.
36
  * @ignore
37
  */
38
  final class Deprecated {
@@ -354,8 +354,8 @@ final class Deprecated {
354
  * Returns the stylesheet XSL location URL.
355
  *
356
  * @since 2.8.0
357
- * @since 3.0.0 1: No longer uses home URL from cache. But now uses `get_home_url()`.
358
- * 2: Now takes query parameters (if any) and restores them correctly.
359
  * @since 4.0.0 Deprecated.
360
  * @deprecated
361
  * @global \WP_Rewrite $wp_rewrite
@@ -371,8 +371,8 @@ final class Deprecated {
371
  * Returns the sitemap XML location URL.
372
  *
373
  * @since 2.9.2
374
- * @since 3.0.0 1: No longer uses home URL from cache. But now uses `get_home_url()`.
375
- * 2: Now takes query parameters (if any) and restores them correctly.
376
  * @since 4.0.0 Deprecated.
377
  * @deprecated
378
  * @global \WP_Rewrite $wp_rewrite
@@ -670,8 +670,8 @@ final class Deprecated {
670
  * Returns unescaped URL from options input.
671
  *
672
  * @since 2.8.2
673
- * @since 2.9.4 1: Now converts URL scheme.
674
- * 2: $set_og_dimensions now works.
675
  * @since 4.0.0 Deprecated
676
  * @deprecated
677
  *
@@ -847,8 +847,8 @@ final class Deprecated {
847
  * Determines if the current theme supports the custom logo addition.
848
  *
849
  * @since 2.8.0
850
- * @since 3.1.0: 1. No longer checks for WP version 4.5+.
851
- * 2. No longer uses caching.
852
  * @since 4.0.0 Deprecated.
853
  * @deprecated
854
  *
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
31
  * Contains all deprecated functions.
32
  *
33
  * @since 2.8.0
34
+ * @since 3.1.0 Removed all methods deprecated in 3.0.0.
35
+ * @since 4.0.0 Removed all methods deprecated in 3.1.0.
36
  * @ignore
37
  */
38
  final class Deprecated {
354
  * Returns the stylesheet XSL location URL.
355
  *
356
  * @since 2.8.0
357
+ * @since 3.0.0 : 1. No longer uses home URL from cache. But now uses `get_home_url()`.
358
+ * 2. Now takes query parameters (if any) and restores them correctly.
359
  * @since 4.0.0 Deprecated.
360
  * @deprecated
361
  * @global \WP_Rewrite $wp_rewrite
371
  * Returns the sitemap XML location URL.
372
  *
373
  * @since 2.9.2
374
+ * @since 3.0.0 : 1. No longer uses home URL from cache. But now uses `get_home_url()`.
375
+ * 2. Now takes query parameters (if any) and restores them correctly.
376
  * @since 4.0.0 Deprecated.
377
  * @deprecated
378
  * @global \WP_Rewrite $wp_rewrite
670
  * Returns unescaped URL from options input.
671
  *
672
  * @since 2.8.2
673
+ * @since 2.9.4 : 1. Now converts URL scheme.
674
+ * 2. $set_og_dimensions now works.
675
  * @since 4.0.0 Deprecated
676
  * @deprecated
677
  *
847
  * Determines if the current theme supports the custom logo addition.
848
  *
849
  * @since 2.8.0
850
+ * @since 3.1.0 : 1. No longer checks for WP version 4.5+.
851
+ * 2. No longer uses caching.
852
  * @since 4.0.0 Deprecated.
853
  * @deprecated
854
  *
inc/classes/detect.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -315,7 +315,7 @@ class Detect extends Render {
315
  *
316
  * @since 1.3.0
317
  * @since 2.6.0 Uses new style detection.
318
- * @since 3.1.0: The filter no longer short-circuits the function when it's false.
319
  *
320
  * @return bool SEO plugin detected.
321
  */
@@ -360,8 +360,8 @@ class Detect extends Render {
360
  * Determines if other Open Graph or SEO plugins are active.
361
  *
362
  * @since 1.3.0
363
- * @since 2.8.0: No longer checks for old style filter.
364
- * @since 3.1.0: The filter no longer short-circuits the function when it's false.
365
  *
366
  * @return bool True if OG or SEO plugin detected.
367
  */
@@ -410,7 +410,7 @@ class Detect extends Render {
410
  * Determines if other Twitter Card plugins are active.
411
  *
412
  * @since 2.6.0
413
- * @since 3.1.0: The filter no longer short-circuits the function when it's false.
414
  * @staticvar bool $detected
415
  *
416
  * @return bool Twitter Card plugin detected.
@@ -476,7 +476,7 @@ class Detect extends Render {
476
  * Determines if other Sitemap plugins are active.
477
  *
478
  * @since 2.1.0
479
- * @since 3.1.0: The filter no longer short-circuits the function when it's false.
480
  * @staticvar bool $detected
481
  *
482
  * @return bool
@@ -740,11 +740,22 @@ class Detect extends Render {
740
  $supported = $this->is_taxonomy_supported() && $this->get_the_real_ID();
741
  break;
742
 
 
743
  default:
744
  $supported = true;
745
  break;
746
  endswitch;
747
 
 
 
 
 
 
 
 
 
 
 
748
  /**
749
  * @since 4.0.0
750
  * @param bool $supported Whether the query supports SEO.
@@ -752,17 +763,151 @@ class Detect extends Render {
752
  return $cache = (bool) \apply_filters( 'the_seo_framework_query_supports_seo', $supported );
753
  }
754
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
755
  /**
756
  * Detects if the current or inputted post type is supported and not disabled.
757
  *
758
  * @since 3.1.0
 
 
759
  *
760
  * @param string $post_type Optional. The post type to check.
761
  * @return bool
762
  */
763
  public function is_post_type_supported( $post_type = '' ) {
764
 
765
- $post_type = $post_type ?: \get_post_type() ?: $this->get_admin_post_type();
766
 
767
  /**
768
  * @since 2.6.2
@@ -817,6 +962,8 @@ class Detect extends Render {
817
  * Checks (current) Post Type for having taxonomical archives.
818
  *
819
  * @since 2.9.3
 
 
820
  * @staticvar array $cache
821
  * @global \WP_Screen $current_screen
822
  *
@@ -830,7 +977,7 @@ class Detect extends Render {
830
  if ( isset( $cache[ $post_type ] ) )
831
  return $cache[ $post_type ];
832
 
833
- $post_type = $post_type ?: \get_post_type() ?: $this->get_admin_post_type();
834
  if ( ! $post_type ) return false;
835
 
836
  if ( \get_object_taxonomies( $post_type, 'names' ) )
@@ -913,13 +1060,15 @@ class Detect extends Render {
913
  *
914
  * @since 3.1.0
915
  * @since 3.1.2 Now is fiterable.
 
 
916
  *
917
  * @param string $post_type Optional. The post type to check.
918
  * @return bool True if disabled, false otherwise.
919
  */
920
  public function is_post_type_disabled( $post_type = '' ) {
921
 
922
- $post_type = $post_type ?: \get_post_type() ?: $this->get_admin_post_type();
923
 
924
  /**
925
  * @since 3.1.2
@@ -1065,4 +1214,32 @@ class Detect extends Render {
1065
 
1066
  return $cache = ! empty( $parsed_url['path'] ) && ltrim( $parsed_url['path'], ' \\/' );
1067
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1068
  }
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
315
  *
316
  * @since 1.3.0
317
  * @since 2.6.0 Uses new style detection.
318
+ * @since 3.1.0 The filter no longer short-circuits the function when it's false.
319
  *
320
  * @return bool SEO plugin detected.
321
  */
360
  * Determines if other Open Graph or SEO plugins are active.
361
  *
362
  * @since 1.3.0
363
+ * @since 2.8.0 No longer checks for old style filter.
364
+ * @since 3.1.0 The filter no longer short-circuits the function when it's false.
365
  *
366
  * @return bool True if OG or SEO plugin detected.
367
  */
410
  * Determines if other Twitter Card plugins are active.
411
  *
412
  * @since 2.6.0
413
+ * @since 3.1.0 The filter no longer short-circuits the function when it's false.
414
  * @staticvar bool $detected
415
  *
416
  * @return bool Twitter Card plugin detected.
476
  * Determines if other Sitemap plugins are active.
477
  *
478
  * @since 2.1.0
479
+ * @since 3.1.0 The filter no longer short-circuits the function when it's false.
480
  * @staticvar bool $detected
481
  *
482
  * @return bool
740
  $supported = $this->is_taxonomy_supported() && $this->get_the_real_ID();
741
  break;
742
 
743
+ // Including 404.
744
  default:
745
  $supported = true;
746
  break;
747
  endswitch;
748
 
749
+ /**
750
+ * Override false negatives on exploit.
751
+ *
752
+ * This protects against (accidental) negative-SEO bombarding.
753
+ * Support broken queries, so we can noindex them.
754
+ */
755
+ if ( ! $supported && $this->is_query_exploited() ) {
756
+ $supported = true;
757
+ }
758
+
759
  /**
760
  * @since 4.0.0
761
  * @param bool $supported Whether the query supports SEO.
763
  return $cache = (bool) \apply_filters( 'the_seo_framework_query_supports_seo', $supported );
764
  }
765
 
766
+ /**
767
+ * Determines when paged/page is exploited.
768
+ *
769
+ * Google is acting "smart" nowadays, and follows everything that remotely resembles a link. Therefore, unintentional
770
+ * queries can occur in WordPress. WordPress deals with this well, alas, the query parser (WP_Query::parse_query)
771
+ * doesn't rectify the mixed signals it receives. Instead, it only sanitizes it, resulting in a combobulated mess.
772
+ * Ultimately, this leads to non-existing blog archives, among other failures.
773
+ *
774
+ * Example 1: `/?p=nonnumeric` will cause an issue. We will see a non-existing blog page. `is_home` is true, but
775
+ * `page_id` leads to 0 while the database expects the blog page to be another page. So, `is_posts_page` is
776
+ * incorrectly false. This is mitigated via the canonical URL, but that MUST output, thus overriding otherwise chosen
777
+ * and expected behavior.
778
+ *
779
+ * Example 2: `/page/2/?p=nonnumeric` will cause a bigger issue. What happens is that `is_home` will again be true,
780
+ * but so will `is_paged`. `paged` will be set to `2` (as per example URL). The page ID will again be set to `0`,
781
+ * which is completely false. The canonical URL will be malformed. Even moreso, Google can ignore the canonical URL,
782
+ * so we MUST output noindex.
783
+ *
784
+ * Example 3: `/page/2/?X=nonnumeric` will also cause the same issues as in example 2. Where X can be:
785
+ * `page_id`, `attachment_id`, `year`, `monthnum`, `day`, `w`, `m`, and of course `p`.
786
+ *
787
+ * Example 4: `/?hour=nonnumeric`, the same issue as Example 1. The canonical URL is malformed, noindex is set, and
788
+ * link relationships will be active. A complete mess. `minute` and `second` are also affected the same way.
789
+ *
790
+ * Example 5: `/page/2/?p=0`, this is the trickiest. It's indicative of a paginated blog, but also the homepage. When
791
+ * the homepage is not a blog, then this query is malformed. Otherwise, however, it's a good query.
792
+ *
793
+ * @since 4.0.5
794
+ * @global \WP_Query $wp_query
795
+ * @staticvar bool $exploited Cached whether the query is exploited.
796
+ *
797
+ * @return bool Whether the query is (accidentally) exploited.
798
+ * Defaults to false when `advanced_query_protection` option is disabled.
799
+ * False when there's a query-ID found.
800
+ * False when no custom query is set (for the homepage).
801
+ * Otherwise, it performs query tests.
802
+ */
803
+ public function is_query_exploited() {
804
+
805
+ static $exploited;
806
+
807
+ if ( isset( $exploited ) ) return $exploited;
808
+
809
+ if ( ! $this->get_option( 'advanced_query_protection' ) )
810
+ return $exploited = false;
811
+
812
+ // When the page ID is not 0, a real page will always be returned.
813
+ if ( $this->get_the_real_ID() )
814
+ return $exploited = false;
815
+
816
+ global $wp_query;
817
+
818
+ // When no special query data is registered, ignore this. Don't set cache.
819
+ if ( ! isset( $wp_query->query ) )
820
+ return false;
821
+
822
+ /**
823
+ * @since 4.0.5
824
+ * @param array $exploitables The exploitable endpoints by type.
825
+ */
826
+ $exploitables = \apply_filters(
827
+ 'the_seo_framework_exploitable_query_endpoints',
828
+ [
829
+ 'numeric' => [
830
+ 'page_id',
831
+ 'attachment_id',
832
+ 'year',
833
+ 'monthnum',
834
+ 'day',
835
+ 'w',
836
+ 'm',
837
+ 'p',
838
+ 'paged', // 'page' is mitigated by WordPress.
839
+ 'hour',
840
+ 'minute',
841
+ 'second',
842
+ 'subpost_id',
843
+ ],
844
+ 'numeric_array' => [
845
+ 'cat',
846
+ 'author',
847
+ ],
848
+ 'requires_s' => [
849
+ 'sentence',
850
+ ],
851
+ ]
852
+ );
853
+
854
+ $query = $wp_query->query;
855
+ $exploited = false;
856
+
857
+ foreach ( $exploitables as $type => $qvs ) :
858
+ foreach ( $qvs as $qv ) :
859
+ // Don't guess "empty", because falsey or empty-array is also empty.
860
+ if ( ! isset( $query[ $qv ] ) ) continue;
861
+
862
+ switch ( $type ) :
863
+ case 'numeric':
864
+ if ( '0' === $query[ $qv ] || ! is_numeric( $query[ $qv ] ) ) {
865
+ $exploited = true;
866
+ break 3;
867
+ }
868
+ break;
869
+
870
+ case 'numeric_array':
871
+ // We can't protect non-pretty permalinks.
872
+ if ( ! $this->pretty_permalinks ) break;
873
+
874
+ // If WordPress didn't canonical_redirect() the user yet, it's exploited.
875
+ // WordPress mitigates this via a 404 query when a numeric value is found.
876
+ if ( ! preg_match( '/[0-9]/', $query[ $qv ] ) ) {
877
+ $exploited = true;
878
+ break 3;
879
+ }
880
+ break;
881
+
882
+ case 'requires_s':
883
+ if ( ! isset( $query['s'] ) ) {
884
+ $exploited = true;
885
+ break 3;
886
+ }
887
+ break;
888
+
889
+ default:
890
+ break;
891
+ endswitch;
892
+ endforeach;
893
+ endforeach;
894
+
895
+ return $exploited;
896
+ }
897
+
898
  /**
899
  * Detects if the current or inputted post type is supported and not disabled.
900
  *
901
  * @since 3.1.0
902
+ * @since 4.0.5 The `$post_type` fallback now uses a real query ID, instead of `$GLOBALS['post']`;
903
+ * mitigating issues with singular-archives pages (blog, shop, etc.).
904
  *
905
  * @param string $post_type Optional. The post type to check.
906
  * @return bool
907
  */
908
  public function is_post_type_supported( $post_type = '' ) {
909
 
910
+ $post_type = $post_type ?: $this->get_post_type_real_ID() ?: $this->get_admin_post_type();
911
 
912
  /**
913
  * @since 2.6.2
962
  * Checks (current) Post Type for having taxonomical archives.
963
  *
964
  * @since 2.9.3
965
+ * @since 4.0.5 The `$post_type` fallback now uses a real query ID, instead of `$GLOBALS['post']`;
966
+ * mitigating issues with singular-archives pages (blog, shop, etc.).
967
  * @staticvar array $cache
968
  * @global \WP_Screen $current_screen
969
  *
977
  if ( isset( $cache[ $post_type ] ) )
978
  return $cache[ $post_type ];
979
 
980
+ $post_type = $post_type ?: $this->get_post_type_real_ID() ?: $this->get_admin_post_type();
981
  if ( ! $post_type ) return false;
982
 
983
  if ( \get_object_taxonomies( $post_type, 'names' ) )
1060
  *
1061
  * @since 3.1.0
1062
  * @since 3.1.2 Now is fiterable.
1063
+ * @since 4.0.5 The `$post_type` fallback now uses a real query ID, instead of `$GLOBALS['post']`;
1064
+ * mitigating issues with singular-archives pages (blog, shop, etc.).
1065
  *
1066
  * @param string $post_type Optional. The post type to check.
1067
  * @return bool True if disabled, false otherwise.
1068
  */
1069
  public function is_post_type_disabled( $post_type = '' ) {
1070
 
1071
+ $post_type = $post_type ?: $this->get_post_type_real_ID() ?: $this->get_admin_post_type();
1072
 
1073
  /**
1074
  * @since 3.1.2
1214
 
1215
  return $cache = ! empty( $parsed_url['path'] ) && ltrim( $parsed_url['path'], ' \\/' );
1216
  }
1217
+
1218
+ /**
1219
+ * Determines if the input text has transformative Yoast SEO syntax.
1220
+ *
1221
+ * @since 4.0.5
1222
+ * @link <https://yoast.com/help/list-available-snippet-variables-yoast-seo/>
1223
+ *
1224
+ * @param string $text The text to evaluate.
1225
+ * @return bool
1226
+ */
1227
+ public function has_yoast_syntax( $text ) {
1228
+
1229
+ if ( false === strpos( $text, '%%' ) ) return false;
1230
+
1231
+ $tags_simple = [ 'date', 'title', 'parent_title', 'archive_title', 'sitename', 'sitedesc', 'excerpt', 'excerpt_only', 'tag', 'category', 'primary_category', 'category_description', 'tag_description', 'term_description', 'term_title', 'searchphrase', 'sep', 'pt_single', 'pt_plural', 'modified', 'id', 'name', 'user_description', 'page', 'pagetotal', 'pagenumber', 'caption', 'focuskw', 'term404', 'ct_product_cat', 'ct_product_tag', 'wc_shortdesc', 'wc_sku', 'wc_brand', 'wc_price' ];
1232
+
1233
+ $_regex = sprintf( '%%%s%%', implode( '|', $tags_simple ) );
1234
+
1235
+ if ( preg_match( "/$_regex/i", $text ) ) return true;
1236
+
1237
+ $tags_wildcard_end = [ 'cs_', 'ct_desc_', 'ct_pa_' ];
1238
+
1239
+ $_regex = sprintf( '%%(%s)[^\s]*?%%', implode( '|', $tags_wildcard_end ) );
1240
+
1241
+ if ( preg_match( "/$_regex/", $text ) ) return true;
1242
+
1243
+ return false;
1244
+ }
1245
  }
inc/classes/feed.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -141,7 +141,7 @@ class Feed extends Cache {
141
  protected function get_feed_entry_source_link() {
142
  /**
143
  * @since 2.6.0
144
- * @since 2.7.2 or 2.7.3: Escaped output.
145
  * @param string $source The source indication string.
146
  */
147
  $source_i18n = (string) \apply_filters(
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
141
  protected function get_feed_entry_source_link() {
142
  /**
143
  * @since 2.6.0
144
+ * @since 2.7.2 or 2.7.3 : Escaped output.
145
  * @param string $source The source indication string.
146
  */
147
  $source_i18n = (string) \apply_filters(
inc/classes/generate-description.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -147,8 +147,8 @@ class Generate_Description extends Generate {
147
  * Falls back to meta description.
148
  *
149
  * @since 3.1.0
150
- * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
151
- * 2. Now obtains custom field data for terms.
152
  * @since 4.0.0 Added term meta item checks.
153
  * @see $this->get_open_graph_description()
154
  * @see $this->get_open_graph_description_from_custom_field()
@@ -235,8 +235,8 @@ class Generate_Description extends Generate {
235
  * Falls back to Open Graph description.
236
  *
237
  * @since 3.1.0
238
- * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
239
- * 2. Now obtains custom field data for terms.
240
  * @since 4.0.0 Added term meta item checks.
241
  * @see $this->get_twitter_description()
242
  * @see $this->get_twitter_description_from_custom_field()
@@ -282,8 +282,8 @@ class Generate_Description extends Generate {
282
  * Falls back to Open Graph description.
283
  *
284
  * @since 3.1.0
285
- * @since 3.2.2: 1. Now tests for the homepage as page prior getting custom field data.
286
- * 2. Now obtains custom field data for terms.
287
  * @since 4.0.0 Added term meta item checks.
288
  * @see $this->get_twitter_description()
289
  * @see $this->get_twitter_description_from_custom_field()
@@ -474,7 +474,7 @@ class Generate_Description extends Generate {
474
  $excerpt = (string) \apply_filters( 'the_seo_framework_fetched_description_excerpt', $excerpt, 0, $args );
475
 
476
  $excerpt = $this->trim_excerpt(
477
- html_entity_decode( $excerpt, ENT_QUOTES | ENT_COMPAT, 'UTF-8' ),
478
  0,
479
  $this->get_input_guidelines()['description'][ $type ]['chars']['goodUpper']
480
  );
@@ -795,6 +795,8 @@ class Generate_Description extends Generate {
795
  * @since 4.0.0 : 1. Now stops parsing earlier on failure.
796
  * 2. Now performs faster queries.
797
  * 3. Now maintains last sentence with closing punctuations.
 
 
798
  * @see https://secure.php.net/manual/en/regexp.reference.unicode.php
799
  *
800
  * We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`, while they don't untexturized.
@@ -807,6 +809,8 @@ class Generate_Description extends Generate {
807
  */
808
  public function trim_excerpt( $excerpt, $depr = 0, $max_char_length = 0 ) {
809
 
 
 
810
  //* Find all words with $max_char_length, and trim when the last word boundary or punctuation is found.
811
  preg_match( sprintf( '/.{0,%d}([^\P{Po}\'\"]|\p{Z}|$){1}/su', $max_char_length ), trim( $excerpt ), $matches );
812
  $excerpt = isset( $matches[0] ) ? ( $matches[0] ?: '' ) : '';
@@ -865,7 +869,7 @@ class Generate_Description extends Generate {
865
  // $excerpt = $matches[1];
866
  // }
867
 
868
- //* Remove leading commas and spaces.
869
  $excerpt = rtrim( $excerpt, ' ,' );
870
 
871
  if ( ';' === substr( $excerpt, -1 ) ) {
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
147
  * Falls back to meta description.
148
  *
149
  * @since 3.1.0
150
+ * @since 3.2.2 : 1. Now tests for the homepage as page prior getting custom field data.
151
+ * 2. Now obtains custom field data for terms.
152
  * @since 4.0.0 Added term meta item checks.
153
  * @see $this->get_open_graph_description()
154
  * @see $this->get_open_graph_description_from_custom_field()
235
  * Falls back to Open Graph description.
236
  *
237
  * @since 3.1.0
238
+ * @since 3.2.2 : 1. Now tests for the homepage as page prior getting custom field data.
239
+ * 2. Now obtains custom field data for terms.
240
  * @since 4.0.0 Added term meta item checks.
241
  * @see $this->get_twitter_description()
242
  * @see $this->get_twitter_description_from_custom_field()
282
  * Falls back to Open Graph description.
283
  *
284
  * @since 3.1.0
285
+ * @since 3.2.2 : 1. Now tests for the homepage as page prior getting custom field data.
286
+ * 2. Now obtains custom field data for terms.
287
  * @since 4.0.0 Added term meta item checks.
288
  * @see $this->get_twitter_description()
289
  * @see $this->get_twitter_description_from_custom_field()
474
  $excerpt = (string) \apply_filters( 'the_seo_framework_fetched_description_excerpt', $excerpt, 0, $args );
475
 
476
  $excerpt = $this->trim_excerpt(
477
+ $excerpt,
478
  0,
479
  $this->get_input_guidelines()['description'][ $type ]['chars']['goodUpper']
480
  );
795
  * @since 4.0.0 : 1. Now stops parsing earlier on failure.
796
  * 2. Now performs faster queries.
797
  * 3. Now maintains last sentence with closing punctuations.
798
+ * @since 4.0.5 : Now decodes the excerpt input, improving accuracy, and so that HTML entities at
799
+ * the end won't be transformed into gibberish.
800
  * @see https://secure.php.net/manual/en/regexp.reference.unicode.php
801
  *
802
  * We use `[^\P{Po}\'\"]` because WordPress texturizes ' and " to fall under `\P{Po}`, while they don't untexturized.
809
  */
810
  public function trim_excerpt( $excerpt, $depr = 0, $max_char_length = 0 ) {
811
 
812
+ $excerpt = html_entity_decode( $excerpt, ENT_QUOTES | ENT_COMPAT, 'UTF-8' );
813
+
814
  //* Find all words with $max_char_length, and trim when the last word boundary or punctuation is found.
815
  preg_match( sprintf( '/.{0,%d}([^\P{Po}\'\"]|\p{Z}|$){1}/su', $max_char_length ), trim( $excerpt ), $matches );
816
  $excerpt = isset( $matches[0] ) ? ( $matches[0] ?: '' ) : '';
869
  // $excerpt = $matches[1];
870
  // }
871
 
872
+ //* Remove trailing commas and spaces.
873
  $excerpt = rtrim( $excerpt, ' ,' );
874
 
875
  if ( ';' === substr( $excerpt, -1 ) ) {
inc/classes/generate-image.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -58,6 +58,7 @@ class Generate_Image extends Generate_Url {
58
  * Returns image details.
59
  *
60
  * @since 4.0.0
 
61
  *
62
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
63
  * Leave null to autodetermine query.
@@ -87,7 +88,31 @@ class Generate_Image extends Generate_Url {
87
  );
88
  }
89
 
90
- return $clean ? $this->s_image_details( $details ) : $details;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  }
92
 
93
  /**
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
58
  * Returns image details.
59
  *
60
  * @since 4.0.0
61
+ * @since 4.0.5 The output is now filterable.
62
  *
63
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
64
  * Leave null to autodetermine query.
88
  );
89
  }
90
 
91
+ /**
92
+ * @since 4.0.5
93
+ * @param array $details The image details array, sequential: int => {
94
+ * string url: The image URL,
95
+ * int id: The image ID,
96
+ * int width: The image width in pixels,
97
+ * int height: The image height in pixels,
98
+ * string alt: The image alt tag,
99
+ * }
100
+ * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
101
+ * Is null when query is autodetermined.
102
+ * @param bool $single Whether to fetch one image, or multiple.
103
+ * @param string $context The filter context. Default 'social'.
104
+ * @param bool $clean Whether to clean the image, like stripping duplicates and erroneous items.
105
+ */
106
+ return \apply_filters_ref_array(
107
+ 'the_seo_framework_image_details',
108
+ [
109
+ $clean ? $this->s_image_details( $details ) : $details,
110
+ $args,
111
+ $single,
112
+ $context,
113
+ $clean,
114
+ ]
115
+ );
116
  }
117
 
118
  /**
inc/classes/generate-ldjson.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -81,7 +81,7 @@ class Generate_Ldjson extends Generate_Image {
81
  if ( \has_filter( 'the_seo_framework_receive_json_data' ) ) {
82
  /**
83
  * @since 2.9.3
84
- * @param array $data The LD-JSON data.
85
  * @param string $key The data key.
86
  */
87
  $data = (array) \apply_filters_ref_array( 'the_seo_framework_receive_json_data', [ $data, $key ] );
@@ -140,37 +140,22 @@ class Generate_Ldjson extends Generate_Image {
140
  *
141
  * @since 2.6.0
142
  * @since 3.1.0 No longer cares for json_ld plugins.
 
143
  *
144
  * @return string The LD+JSON scripts.
145
  */
146
  public function render_ld_json_scripts() {
147
 
148
- $use_cache = (bool) $this->get_option( 'cache_meta_schema' );
149
- $transient_name = $use_cache ? $this->get_ld_json_transient_name( $this->get_the_real_ID() ) : '';
 
150
 
151
- $output = $transient_name ? $this->get_transient( $transient_name ) : false;
152
- if ( false === $output ) :
153
- if ( $this->is_real_front_page() ) {
154
- //= Homepage Schema.
155
- $output = '';
156
-
157
- $output .= $this->get_ld_json_website() ?: '';
158
- $output .= $this->get_ld_json_links() ?: '';
159
- } else {
160
- //= All other pages' Schema.
161
- $output = $this->get_ld_json_breadcrumbs() ?: '';
162
- }
163
-
164
- if ( $use_cache ) {
165
- /**
166
- * Transient expiration: 1 week.
167
- * Keep the script for at most 1 week.
168
- */
169
- $expiration = WEEK_IN_SECONDS;
170
-
171
- $this->set_transient( $transient_name, $output, $expiration );
172
- }
173
- endif;
174
 
175
  return $output;
176
  }
@@ -263,6 +248,7 @@ class Generate_Ldjson extends Generate_Image {
263
 
264
  /**
265
  * @since 2.7 or later.
 
266
  * @param array The SEO Framework's option names used for sitelinks.
267
  */
268
  $sameurls_options = (array) \apply_filters(
@@ -375,6 +361,7 @@ class Generate_Ldjson extends Generate_Image {
375
  $output = '';
376
 
377
  if ( $this->is_singular() && ! $this->is_real_front_page() ) {
 
378
  if ( $this->is_single() ) {
379
  $output = $this->get_ld_json_breadcrumbs_post();
380
  } else {
@@ -437,8 +424,8 @@ class Generate_Ldjson extends Generate_Image {
437
  * Generates LD+JSON Breadcrumbs script for Posts.
438
  *
439
  * @since 2.9.3
440
- * @since 3.0.0 1: Now only returns one crumb.
441
- * 2: Now listens to primary term ID.
442
  *
443
  * @return string LD+JSON breadcrumbs script for Posts on success. Empty string on failure.
444
  */
@@ -682,9 +669,9 @@ class Generate_Ldjson extends Generate_Image {
682
  * Generates homepage LD+JSON breadcrumb.
683
  *
684
  * @since 2.9.3
685
- * @since 3.2.2: 1. The title now works for the homepage as blog.
686
- * 2. The image has been disabled for the homepage as blog.
687
- * - I couldn't fix it without evading the API, which is bad.
688
  * @since 4.0.0 Removed the image input requirement.
689
  * @staticvar array $crumb
690
  *
@@ -847,7 +834,6 @@ class Generate_Ldjson extends Generate_Image {
847
  /**
848
  * @since 2.9.0
849
  * @param bool $use_seo_title Whether to use the SEO title.
850
- * NOTE: Changing this does not affect the transient cache; wait for it to clear.
851
  */
852
  return isset( $cache ) ? $cache : $cache = (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true );
853
  }
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
81
  if ( \has_filter( 'the_seo_framework_receive_json_data' ) ) {
82
  /**
83
  * @since 2.9.3
84
+ * @param array $data The JSON-LD data.
85
  * @param string $key The data key.
86
  */
87
  $data = (array) \apply_filters_ref_array( 'the_seo_framework_receive_json_data', [ $data, $key ] );
140
  *
141
  * @since 2.6.0
142
  * @since 3.1.0 No longer cares for json_ld plugins.
143
+ * @since 4.0.5 Removed caching.
144
  *
145
  * @return string The LD+JSON scripts.
146
  */
147
  public function render_ld_json_scripts() {
148
 
149
+ if ( $this->is_real_front_page() ) {
150
+ //= Homepage Schema.
151
+ $output = '';
152
 
153
+ $output .= $this->get_ld_json_website() ?: '';
154
+ $output .= $this->get_ld_json_links() ?: '';
155
+ } else {
156
+ //= All other pages' Schema.
157
+ $output = $this->get_ld_json_breadcrumbs() ?: '';
158
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  return $output;
161
  }
248
 
249
  /**
250
  * @since 2.7 or later.
251
+ * @TODO deprecate
252
  * @param array The SEO Framework's option names used for sitelinks.
253
  */
254
  $sameurls_options = (array) \apply_filters(
361
  $output = '';
362
 
363
  if ( $this->is_singular() && ! $this->is_real_front_page() ) {
364
+ // TODO Shouldn't this be is_post_type_hierarchical()?
365
  if ( $this->is_single() ) {
366
  $output = $this->get_ld_json_breadcrumbs_post();
367
  } else {
424
  * Generates LD+JSON Breadcrumbs script for Posts.
425
  *
426
  * @since 2.9.3
427
+ * @since 3.0.0 : 1. Now only returns one crumb.
428
+ * 2. Now listens to primary term ID.
429
  *
430
  * @return string LD+JSON breadcrumbs script for Posts on success. Empty string on failure.
431
  */
669
  * Generates homepage LD+JSON breadcrumb.
670
  *
671
  * @since 2.9.3
672
+ * @since 3.2.2 : 1. The title now works for the homepage as blog.
673
+ * 2. The image has been disabled for the homepage as blog.
674
+ * i. I couldn't fix it without evading the API, which is bad.
675
  * @since 4.0.0 Removed the image input requirement.
676
  * @staticvar array $crumb
677
  *
834
  /**
835
  * @since 2.9.0
836
  * @param bool $use_seo_title Whether to use the SEO title.
 
837
  */
838
  return isset( $cache ) ? $cache : $cache = (bool) \apply_filters( 'the_seo_framework_use_breadcrumb_seo_title', true );
839
  }
inc/classes/generate-title.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -717,8 +717,11 @@ class Generate_Title extends Generate_Description {
717
  *
718
  * @since 3.1.0
719
  * @since 4.0.2 Now asserts the correct tag taxonomy condition.
 
 
 
720
  *
721
- * @param \WP_Term|\WP_Error|null $term The Term object or error. Leave null to autodetermine query.
722
  * @return string The generated archive title, not escaped.
723
  */
724
  public function get_generated_archive_title( $term = null ) {
@@ -736,17 +739,16 @@ class Generate_Title extends Generate_Description {
736
  /**
737
  * @since 2.6.0
738
  *
739
- * @param string $title The short circuit title.
740
- * @param \WP_Term $term The Term object.
741
  */
742
  $title = (string) \apply_filters( 'the_seo_framework_the_archive_title', '', $term );
743
 
744
  if ( $title )
745
  return $title;
746
 
747
- $use_prefix = $this->use_generated_archive_prefix();
748
-
749
- $_tax = isset( $term->taxonomy ) ? $term->taxonomy : '';
750
 
751
  if ( ! $_query ) {
752
  if ( $_tax ) {
@@ -767,6 +769,10 @@ class Generate_Title extends Generate_Description {
767
  $title = sprintf( \__( '%1$s: %2$s', 'autodescription' ), $_prefix, $title );
768
  }
769
  }
 
 
 
 
770
  } else {
771
  $title = \__( 'Archives', 'default' );
772
  }
@@ -780,7 +786,7 @@ class Generate_Title extends Generate_Description {
780
  /* translators: Tag archive title. 1: Tag name */
781
  $title = $use_prefix ? sprintf( \__( 'Tag: %s', 'default' ), $title ) : $title;
782
  } elseif ( $this->is_author() ) {
783
- $title = \get_the_author();
784
  /* translators: Author archive title. 1: Author name */
785
  $title = $use_prefix ? sprintf( \__( 'Author: %s', 'default' ), $title ) : $title;
786
  } elseif ( $this->is_date() ) {
@@ -1279,8 +1285,8 @@ class Generate_Title extends Generate_Description {
1279
  * Determines whether to add or remove title branding additions.
1280
  *
1281
  * @since 3.1.0
1282
- * @since 3.1.2: 1. Added filter.
1283
- * 2. Added strict taxonomical check.
1284
  * @since 3.2.2 Now differentiates from query and parameter input.
1285
  * @see $this->merge_title_branding()
1286
  * @uses $this->use_title_branding_from_query()
@@ -1362,11 +1368,23 @@ class Generate_Title extends Generate_Description {
1362
  * Determines whether to use the autogenerated archive title prefix or not.
1363
  *
1364
  * @since 3.1.0
 
 
1365
  *
 
1366
  * @return bool
1367
  */
1368
- public function use_generated_archive_prefix() {
1369
- return ! $this->get_option( 'title_rem_prefixes' );
 
 
 
 
 
 
 
 
 
1370
  }
1371
 
1372
  /**
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
717
  *
718
  * @since 3.1.0
719
  * @since 4.0.2 Now asserts the correct tag taxonomy condition.
720
+ * @since 4.0.5 1: Now no longer uses `get_the_author()` to fetch the author's display name,
721
+ * but uses the provided term object instead.
722
+ * 2: The first parameter now accepts `\WP_User` objects.
723
  *
724
+ * @param \WP_Term|\WP_User|\WP_Error|null $term The Term object or error. Leave null to autodetermine query.
725
  * @return string The generated archive title, not escaped.
726
  */
727
  public function get_generated_archive_title( $term = null ) {
739
  /**
740
  * @since 2.6.0
741
  *
742
+ * @param string $title The short circuit title.
743
+ * @param \WP_Term|\WP_User $term The Term object.
744
  */
745
  $title = (string) \apply_filters( 'the_seo_framework_the_archive_title', '', $term );
746
 
747
  if ( $title )
748
  return $title;
749
 
750
+ $_tax = isset( $term->taxonomy ) ? $term->taxonomy : '';
751
+ $use_prefix = $this->use_generated_archive_prefix( $term );
 
752
 
753
  if ( ! $_query ) {
754
  if ( $_tax ) {
769
  $title = sprintf( \__( '%1$s: %2$s', 'autodescription' ), $_prefix, $title );
770
  }
771
  }
772
+ } elseif ( $term instanceof \WP_User && isset( $term->display_name ) ) {
773
+ $title = $term->display_name;
774
+ /* translators: Author archive title. 1: Author name */
775
+ $title = $use_prefix ? sprintf( \__( 'Author: %s', 'default' ), $title ) : $title;
776
  } else {
777
  $title = \__( 'Archives', 'default' );
778
  }
786
  /* translators: Tag archive title. 1: Tag name */
787
  $title = $use_prefix ? sprintf( \__( 'Tag: %s', 'default' ), $title ) : $title;
788
  } elseif ( $this->is_author() ) {
789
+ $title = isset( $term->display_name ) ? $term->display_name : '';
790
  /* translators: Author archive title. 1: Author name */
791
  $title = $use_prefix ? sprintf( \__( 'Author: %s', 'default' ), $title ) : $title;
792
  } elseif ( $this->is_date() ) {
1285
  * Determines whether to add or remove title branding additions.
1286
  *
1287
  * @since 3.1.0
1288
+ * @since 3.1.2 : 1. Added filter.
1289
+ * 2. Added strict taxonomical check.
1290
  * @since 3.2.2 Now differentiates from query and parameter input.
1291
  * @see $this->merge_title_branding()
1292
  * @uses $this->use_title_branding_from_query()
1368
  * Determines whether to use the autogenerated archive title prefix or not.
1369
  *
1370
  * @since 3.1.0
1371
+ * @since 4.0.5 1: Added first parameter `$term`.
1372
+ * 2: Added filter.
1373
  *
1374
+ * @param \WP_Term|\WP_User|null $term The Term object. Leave null to autodermine query.
1375
  * @return bool
1376
  */
1377
+ public function use_generated_archive_prefix( $term = null ) {
1378
+
1379
+ $term = isset( $term ) ? $term : \get_queried_object();
1380
+ $use = ! $this->get_option( 'title_rem_prefixes' );
1381
+
1382
+ /**
1383
+ * @since 4.0.5
1384
+ * @param string $use Whether to use branding.
1385
+ * @param \WP_Term|\WP_User $term The current term.
1386
+ */
1387
+ return \apply_filters_ref_array( 'the_seo_framework_use_archive_prefix', [ $use, $term ] );
1388
  }
1389
 
1390
  /**
inc/classes/generate-url.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -345,6 +345,7 @@ class Generate_Url extends Generate_Title {
345
  * @since 3.0.0
346
  * @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
347
  * @since 3.2.4 Removed pagination support for singular posts, as the SEO attack is now mitigated via WordPress.
 
348
  *
349
  * @param int|null $id The page ID.
350
  * @return string The custom canonical URL, if any.
@@ -359,7 +360,7 @@ class Generate_Url extends Generate_Title {
359
  $url = $this->remove_pagination_from_url( $url, $_page, false );
360
  }
361
 
362
- if ( $url && $this->is_singular_archive() ) {
363
  // Singular archives, like blog pages and shop pages, use the pagination base with paged.
364
  $url = $this->add_url_pagination( $url, $this->paged(), true );
365
  }
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
345
  * @since 3.0.0
346
  * @since 3.1.0 Added WC Shop and WP Blog (as page) pagination integration via $this->paged().
347
  * @since 3.2.4 Removed pagination support for singular posts, as the SEO attack is now mitigated via WordPress.
348
+ * @since 4.0.5 Now passes the `$id` to `is_singular_archive()`
349
  *
350
  * @param int|null $id The page ID.
351
  * @return string The custom canonical URL, if any.
360
  $url = $this->remove_pagination_from_url( $url, $_page, false );
361
  }
362
 
363
+ if ( $url && $this->is_singular_archive( $id ) ) {
364
  // Singular archives, like blog pages and shop pages, use the pagination base with paged.
365
  $url = $this->add_url_pagination( $url, $this->paged(), true );
366
  }
inc/classes/generate.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -68,18 +68,20 @@ class Generate extends User_Data {
68
  * @since 2.2.4 Added robots SEO settings check.
69
  * @since 2.2.8 Added check for empty archives.
70
  * @since 2.8.0 Added check for protected/private posts.
71
- * @since 3.0.0 1: Removed noodp.
72
- * 2: Improved efficiency by grouping if statements.
73
- * @since 3.1.0 1. Simplified statements, often (not always) speeding things up.
74
- * 2. Now checks for wc_shop and blog types for pagination.
75
- * 3. Removed noydir.
76
- * @since 4.0.0 1. Now tests for qubit metadata.
77
- * 2. Added custom query support.
78
- * 3. Added two parameters.
79
- * @since 4.0.2 1. Added new copyright directive tags.
80
- * 2. Now strictly parses the validity of robots directives via a boolean check.
81
- * @since 4.0.3 1. Changed `max_snippet_length` to `max_snippet`
82
- * 2. Changed the copyright directive's spacer from `=` to `:`.
 
 
83
  * @global \WP_Query $wp_query
84
  *
85
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
@@ -97,6 +99,11 @@ class Generate extends User_Data {
97
 
98
  if ( null === $args ) {
99
  $_meta = $this->get_robots_meta_by_query( $ignore );
 
 
 
 
 
100
  } else {
101
  $this->fix_generation_args( $args );
102
  $_meta = $this->get_robots_meta_by_args( $args, $ignore );
@@ -121,23 +128,6 @@ class Generate extends User_Data {
121
  as $k => $v
122
  ) false !== $v and $meta[ $k ] = str_replace( '_', '-', $k ) . ":$v";
123
 
124
- /**
125
- * Drop-in Google Search bug patch.
126
- * "When you combine "max-image-preview:none" with either "nofollow" or "noarchive", the page is marked as "noindex"!"
127
- *
128
- * (It's probably defined as `<meta name=robots content=none/>` due to a regex bug at Google)
129
- *
130
- * @link <https://twitter.com/SybreWaaijer/status/1192017921553375232>
131
- * @link <https://kb.theseoframework.com/?p=82>
132
- * @since 4.0.3
133
- * @ignore Do not fix me. Do not place after the filter either; that's redundant, because there are more filters trickling down.
134
- * @TEMP
135
- */
136
- if ( 'max-image-preview:none' === $meta['max_image_preview'] ) {
137
- if ( $meta['nofollow'] || $meta['noarchive'] )
138
- $meta['max_image_preview'] = '';
139
- }
140
-
141
  /**
142
  * Filters the front-end robots array, and strips empty indexes thereafter.
143
  *
@@ -174,6 +164,10 @@ class Generate extends User_Data {
174
  * @since 4.0.0
175
  * @since 4.0.2 Added new copyright directive tags.
176
  * @since 4.0.3 Changed `max_snippet_length` to `max_snippet`
 
 
 
 
177
  * @global \WP_Query $wp_query
178
  *
179
  * @param int <bit> $ignore The ignore level. {
@@ -218,15 +212,29 @@ class Generate extends User_Data {
218
  } else {
219
  global $wp_query;
220
 
221
- /**
222
- * Check for 404, or if archive is empty: set noindex for those.
223
- * Don't check this on the homepage. The homepage is sacred in this regard,
224
- * because page builders and templates can and will take over.
225
- *
226
- * Don't use empty(), null is regarded as indexable.
227
- */
228
- if ( isset( $wp_query->post_count ) && ! $wp_query->post_count )
229
- $noindex = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
  if (
232
  ! $noindex
@@ -289,7 +297,7 @@ class Generate extends User_Data {
289
  endif;
290
  } elseif ( $this->is_singular() ) {
291
 
292
- $post_type = \get_post_type() ?: $this->get_admin_post_type();
293
  foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
294
  $$r = $$r || $this->is_post_type_robots_set( $r, $post_type );
295
  }
@@ -323,7 +331,16 @@ class Generate extends User_Data {
323
  * For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
324
  */
325
  if ( (int) \get_query_var( 'cpage', 0 ) > 0 ) {
326
- $noindex = true;
 
 
 
 
 
 
 
 
 
327
  }
328
  }
329
 
@@ -539,6 +556,8 @@ class Generate extends User_Data {
539
  * Determines if the post type has a robots value set.
540
  *
541
  * @since 3.1.0
 
 
542
  *
543
  * @param string $type Accepts 'noindex', 'nofollow', 'noarchive'.
544
  * @param string $post_type The post type, optional. Leave empty to autodetermine type.
@@ -547,7 +566,7 @@ class Generate extends User_Data {
547
  public function is_post_type_robots_set( $type, $post_type = '' ) {
548
  return isset(
549
  $this->get_option( $this->get_robots_post_type_option_id( $type ) )[
550
- $post_type ?: \get_post_type() ?: $this->get_admin_post_type()
551
  ]
552
  );
553
  }
@@ -556,9 +575,11 @@ class Generate extends User_Data {
556
  * Returns cached and parsed separator option.
557
  *
558
  * @since 2.3.9
559
- * @since 3.1.0 : 1. Removed caching.
560
- * 2. Removed escaping parameter.
561
  * @since 4.0.0 No longer converts the `dash` separator option.
 
 
562
  *
563
  * @param string $type The separator type. Used to fetch option.
564
  * @return string The separator.
@@ -566,18 +587,9 @@ class Generate extends User_Data {
566
  public function get_separator( $type = 'title' ) {
567
 
568
  $sep_option = $this->get_option( $type . '_separator' );
 
569
 
570
- if ( 'pipe' === $sep_option ) {
571
- $sep = '|';
572
- } elseif ( '' !== $sep_option ) {
573
- //* Encapsulate within html entities.
574
- $sep = '&' . $sep_option . ';';
575
- } else {
576
- //* Nothing found.
577
- $sep = '|';
578
- }
579
-
580
- return $sep;
581
  }
582
 
583
  /**
@@ -671,7 +683,7 @@ class Generate extends User_Data {
671
  */
672
  public function generate_og_type() {
673
 
674
- if ( $this->is_wc_product() ) {
675
  $type = 'product';
676
  } elseif ( $this->is_single() && $this->get_image_from_cache() ) {
677
  $type = 'article';
@@ -805,13 +817,15 @@ class Generate extends User_Data {
805
  * @since 2.6.0
806
  * @since 3.1.0 Is now filterable.
807
  * @since 4.0.0 Removed the dash key.
 
808
  *
809
  * @return array Title separators.
810
  */
811
  public function get_separator_list() {
812
  /**
813
  * @since 3.1.0
814
- * @since 4.0.0 Removed the dash key.
 
815
  * @param array $list The separator list in { option_name > display_value } format.
816
  * The option name should be translatable within `&...;` tags.
817
  * 'pipe' is excluded from this rule.
@@ -819,6 +833,7 @@ class Generate extends User_Data {
819
  return (array) \apply_filters(
820
  'the_seo_framework_separator_list',
821
  [
 
822
  'pipe' => '|',
823
  'ndash' => '&ndash;',
824
  'mdash' => '&mdash;',
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
68
  * @since 2.2.4 Added robots SEO settings check.
69
  * @since 2.2.8 Added check for empty archives.
70
  * @since 2.8.0 Added check for protected/private posts.
71
+ * @since 3.0.0 : 1. Removed noodp.
72
+ * 2. Improved efficiency by grouping if statements.
73
+ * @since 3.1.0 : 1. Simplified statements, often (not always) speeding things up.
74
+ * 2. Now checks for wc_shop and blog types for pagination.
75
+ * 3. Removed noydir.
76
+ * @since 4.0.0 : 1. Now tests for qubit metadata.
77
+ * 2. Added custom query support.
78
+ * 3. Added two parameters.
79
+ * @since 4.0.2 : 1. Added new copyright directive tags.
80
+ * 2. Now strictly parses the validity of robots directives via a boolean check.
81
+ * @since 4.0.3 : 1. Changed `max_snippet_length` to `max_snippet`
82
+ * 2. Changed the copyright directive's spacer from `=` to `:`.
83
+ * @since 4.0.5 : 1. Removed copyright directive bug workaround. <https://kb.theseoframework.com/kb/why-is-max-image-preview-none-purged/>
84
+ * 2. Now sets noindex and nofollow when queries are exploited (requires option enabled).
85
  * @global \WP_Query $wp_query
86
  *
87
  * @param array|null $args The query arguments. Accepts 'id' and 'taxonomy'.
99
 
100
  if ( null === $args ) {
101
  $_meta = $this->get_robots_meta_by_query( $ignore );
102
+
103
+ if ( $this->is_query_exploited() ) {
104
+ $_meta['noindex'] = true;
105
+ $_meta['nofollow'] = true;
106
+ }
107
  } else {
108
  $this->fix_generation_args( $args );
109
  $_meta = $this->get_robots_meta_by_args( $args, $ignore );
128
  as $k => $v
129
  ) false !== $v and $meta[ $k ] = str_replace( '_', '-', $k ) . ":$v";
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  /**
132
  * Filters the front-end robots array, and strips empty indexes thereafter.
133
  *
164
  * @since 4.0.0
165
  * @since 4.0.2 Added new copyright directive tags.
166
  * @since 4.0.3 Changed `max_snippet_length` to `max_snippet`
167
+ * @since 4.0.5 1. The `$post_type` test now uses a real query ID, instead of `$GLOBALS['post']`;
168
+ * mitigating issues with singular-archives pages (blog, shop, etc.).
169
+ * 2. Now disregards empty blog pages for automatic `noindex`; although this protection is necessary,
170
+ * it can not be reflected in the SEO Bar.
171
  * @global \WP_Query $wp_query
172
  *
173
  * @param int <bit> $ignore The ignore level. {
212
  } else {
213
  global $wp_query;
214
 
215
+ if ( $this->is_singular_archive() ) {
216
+ /**
217
+ * Pagination overflow protection via 404 test.
218
+ *
219
+ * When there are no posts, the first page will NOT relay 404;
220
+ * which is exactly as intended. All other pages will relay 404.
221
+ *
222
+ * We do not test the post_count here, because we want to have
223
+ * the first page indexable via user-intend only.
224
+ */
225
+ $noindex = $noindex || $this->is_404();
226
+ } else {
227
+ /**
228
+ * Check for 404, or if archive is empty: set noindex for those.
229
+ *
230
+ * Don't check this on the homepage. The homepage is sacred in this regard,
231
+ * because page builders and templates can and will take over.
232
+ *
233
+ * Don't use empty(), null is regarded as indexable.
234
+ */
235
+ if ( isset( $wp_query->post_count ) && ! $wp_query->post_count )
236
+ $noindex = true;
237
+ }
238
 
239
  if (
240
  ! $noindex
297
  endif;
298
  } elseif ( $this->is_singular() ) {
299
 
300
+ $post_type = $this->get_post_type_real_ID() ?: $this->get_admin_post_type();
301
  foreach ( [ 'noindex', 'nofollow', 'noarchive' ] as $r ) {
302
  $$r = $$r || $this->is_post_type_robots_set( $r, $post_type );
303
  }
331
  * For reference, it fires `remove_query_arg( 'cpage', $redirect['query'] )`;
332
  */
333
  if ( (int) \get_query_var( 'cpage', 0 ) > 0 ) {
334
+ /**
335
+ * We do not recommend using this filter as it'll likely get those pages flagged as
336
+ * duplicated by Google anyway; unless the theme strips or trims the content.
337
+ *
338
+ * This filter won't run when other conditions for noindex have been met.
339
+ *
340
+ * @since 4.0.5
341
+ * @param bool $noindex Whether to enable comment pagination protection.
342
+ */
343
+ $noindex = $noindex || \apply_filters( 'the_seo_framework_enable_noindex_comment_pagination', true );
344
  }
345
  }
346
 
556
  * Determines if the post type has a robots value set.
557
  *
558
  * @since 3.1.0
559
+ * @since 4.0.5 The `$post_type` fallback now uses a real query ID, instead of `$GLOBALS['post']`;
560
+ * mitigating issues with singular-archives pages (blog, shop, etc.).
561
  *
562
  * @param string $type Accepts 'noindex', 'nofollow', 'noarchive'.
563
  * @param string $post_type The post type, optional. Leave empty to autodetermine type.
566
  public function is_post_type_robots_set( $type, $post_type = '' ) {
567
  return isset(
568
  $this->get_option( $this->get_robots_post_type_option_id( $type ) )[
569
+ $post_type ?: $this->get_post_type_real_ID() ?: $this->get_admin_post_type()
570
  ]
571
  );
572
  }
575
  * Returns cached and parsed separator option.
576
  *
577
  * @since 2.3.9
578
+ * @since 3.1.0 1. Removed caching.
579
+ * 2. Removed escaping parameter.
580
  * @since 4.0.0 No longer converts the `dash` separator option.
581
+ * @since 4.0.5 1. Now utilizes the predefined separator list, instead of guessing the output.
582
+ * 2. The default fallback value is now a hyphen.
583
  *
584
  * @param string $type The separator type. Used to fetch option.
585
  * @return string The separator.
587
  public function get_separator( $type = 'title' ) {
588
 
589
  $sep_option = $this->get_option( $type . '_separator' );
590
+ $sep_list = $this->get_separator_list();
591
 
592
+ return isset( $sep_list[ $sep_option ] ) ? $sep_list[ $sep_option ] : '&#x2d;';
 
 
 
 
 
 
 
 
 
 
593
  }
594
 
595
  /**
683
  */
684
  public function generate_og_type() {
685
 
686
+ if ( $this->is_product() ) {
687
  $type = 'product';
688
  } elseif ( $this->is_single() && $this->get_image_from_cache() ) {
689
  $type = 'article';
817
  * @since 2.6.0
818
  * @since 3.1.0 Is now filterable.
819
  * @since 4.0.0 Removed the dash key.
820
+ * @since 4.0.5 Added back the hyphen.
821
  *
822
  * @return array Title separators.
823
  */
824
  public function get_separator_list() {
825
  /**
826
  * @since 3.1.0
827
+ * @since 4.0.0 Removed the hyphen (then known as 'dash') key.
828
+ * @since 4.0.5 Reintroduced hyphen.
829
  * @param array $list The separator list in { option_name > display_value } format.
830
  * The option name should be translatable within `&...;` tags.
831
  * 'pipe' is excluded from this rule.
833
  return (array) \apply_filters(
834
  'the_seo_framework_separator_list',
835
  [
836
+ 'hyphen' => '&#x2d;',
837
  'pipe' => '|',
838
  'ndash' => '&ndash;',
839
  'mdash' => '&mdash;',
inc/classes/init.class.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
@@ -298,6 +298,23 @@ class Init extends Query {
298
  // Future, maybe. See <https://github.com/Automattic/jetpack/issues/13146#issuecomment-516841698>
299
  // \add_filter( 'jetpack_enable_twitter_cards', '__return_false' );
300
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  }
302
 
303
  /**
@@ -370,111 +387,126 @@ class Init extends Query {
370
  $output = false;
371
  }
372
 
373
- if ( false === $output ) :
 
 
 
374
 
375
- $robots = $this->robots();
 
376
 
377
- /**
378
- * @since 2.6.0
379
- * @param string $before The content before the SEO output. Stored in object cache.
380
- */
381
- $before = (string) \apply_filters( 'the_seo_framework_pre', '' );
382
-
383
- $before_legacy = $this->get_legacy_header_filters_output( 'before' );
384
-
385
- /** @since 4.0.4 : WP 5.3 patch, added. TEMP */
386
- $this->set_timezone( 'UTC' );
387
-
388
- //* Limit processing and redundant tags on 404 and search.
389
- if ( $this->is_search() ) :
390
- $output = $this->og_locale()
391
- . $this->og_type()
392
- . $this->og_title()
393
- . $this->og_url()
394
- . $this->og_sitename()
395
- . $this->shortlink()
396
- . $this->canonical()
397
- . $this->paged_urls()
398
- . $this->google_site_output()
399
- . $this->bing_site_output()
400
- . $this->yandex_site_output()
401
- . $this->pint_site_output();
402
- elseif ( $this->is_404() ) :
403
- $output = $this->google_site_output()
404
- . $this->bing_site_output()
405
- . $this->yandex_site_output()
406
- . $this->pint_site_output();
407
- else :
408
- /** @since 4.0.4 : WP 5.3 patch, commented. TEMP */
409
- // $set_timezone = $this->uses_time_in_timestamp_format() && ( $this->output_published_time() || $this->output_modified_time() );
410
- // $set_timezone and $this->set_timezone();
411
-
412
- $output = $this->the_description()
413
- . $this->og_image()
414
- . $this->og_locale()
415
- . $this->og_type()
416
- . $this->og_title()
417
- . $this->og_description()
418
- . $this->og_url()
419
- . $this->og_sitename()
420
- . $this->facebook_publisher()
421
- . $this->facebook_author()
422
- . $this->facebook_app_id()
423
- . $this->article_published_time()
424
- . $this->article_modified_time()
425
- . $this->twitter_card()
426
- . $this->twitter_site()
427
- . $this->twitter_creator()
428
- . $this->twitter_title()
429
- . $this->twitter_description()
430
- . $this->twitter_image()
431
- . $this->shortlink()
432
- . $this->canonical()
433
- . $this->paged_urls()
434
- . $this->ld_json()
435
- . $this->google_site_output()
436
- . $this->bing_site_output()
437
- . $this->yandex_site_output()
438
- . $this->pint_site_output();
439
-
440
- /** @since 4.0.4 : WP 5.3 patch, commented. TEMP */
441
- // $set_timezone and $this->reset_timezone();
442
- endif;
443
-
444
- /** @since 4.0.4 : WP 5.3 patch, added. TEMP */
445
- $this->reset_timezone();
446
-
447
- $after_legacy = $this->get_legacy_header_filters_output( 'after' );
448
 
449
- /**
450
- * @since 2.6.0
451
- * @param string $after The content after the SEO output. Stored in object cache.
452
- */
453
- $after = (string) \apply_filters( 'the_seo_framework_pro', '' );
 
 
 
 
454
 
455
- $output = $robots . $before . $before_legacy . $output . $after_legacy . $after;
456
 
457
- $this->use_object_cache and $this->object_cache_set( $cache_key, $output, DAY_IN_SECONDS );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
  endif;
459
 
460
- // phpcs:ignore, WordPress.Security.EscapeOutput -- $output is escaped.
461
- echo PHP_EOL, $this->get_plugin_indicator( 'before' ), $output, $this->get_plugin_indicator( 'after', $init_start ), PHP_EOL;
462
 
463
  /**
464
  * @since 2.6.0
 
465
  */
466
- \do_action( 'the_seo_framework_do_after_output' );
 
 
 
 
 
 
 
467
  }
468
 
469
  /**
470
  * Redirects singular page to an alternate URL.
471
  *
472
  * @since 2.9.0
473
- * @since 3.1.0: 1. Now no longer redirects on preview.
474
- * 2. Now listens to post type settings.
475
- * @since 4.0.0: 1. No longer tries to redirect on "search".
476
- * 2. Added term redirect support.
477
- * 3. No longer redirects on Customizer.
478
  * @access private
479
  *
480
  * @return void early on non-singular pages.
@@ -486,14 +518,9 @@ class Init extends Query {
486
  $url = '';
487
 
488
  if ( $this->is_singular() ) {
489
- // TODO exclude is_singular_archive()? Those can create issues...
490
-
491
  $url = $this->get_post_meta_item( 'redirect' ) ?: '';
492
  } elseif ( $this->is_term_meta_capable() ) {
493
- $term_meta = $this->get_current_term_meta();
494
-
495
- if ( isset( $term_meta['redirect'] ) )
496
- $url = $term_meta['redirect'] ?: '';
497
  }
498
 
499
  $url and $this->do_redirect( $url );
@@ -560,29 +587,29 @@ class Init extends Query {
560
 
561
  /**
562
  * Edits the robots.txt output.
563
- * Requires not to have a robots.txt file in the root directory.
564
  *
565
  * This methods completely hijacks default output, intentionally.
 
566
  * The robots.txt file should be left as default, so to improve SEO.
567
  * The Robots Exclusion Protocol encourages you not to use this file for
568
- * non-administrative endpoints.
569
  *
570
  * @since 2.2.9
571
  * @since 2.9.3 Casts $public to string for check.
 
 
 
 
572
  * @uses robots_txt filter located at WP core
 
573
  *
574
- * @param string $robots_txt The current robots_txt output.
575
- * @param string $public The blog_public option value.
576
  * @return string Robots.txt output.
577
  */
578
  public function robots_txt( $robots_txt = '', $public = '' ) {
579
 
580
- /**
581
- * Don't do anything if the blog isn't public.
582
- */
583
- if ( '0' === (string) $public )
584
- return $robots_txt;
585
-
586
  if ( $this->use_object_cache ) {
587
  $cache_key = $this->get_robots_txt_cache_key();
588
  $output = $this->object_cache_get( $cache_key );
@@ -593,12 +620,6 @@ class Init extends Query {
593
  if ( false === $output ) :
594
  $output = '';
595
 
596
- if ( $this->is_subdirectory_installation() ) {
597
- $output .= '# This is an invalid robots.txt location.' . "\r\n";
598
- $output .= '# Please visit: ' . \esc_url( \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) ) . 'robots.txt' ) . "\r\n";
599
- $output .= "\r\n";
600
- }
601
-
602
  $site_path = \esc_attr( parse_url( \site_url(), PHP_URL_PATH ) ) ?: '';
603
 
604
  /**
@@ -642,10 +663,29 @@ class Init extends Query {
642
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
643
  endif;
644
 
645
- // Completely override robots with output.
646
- $robots_txt = $output;
 
 
 
 
 
 
 
 
 
 
 
 
 
647
 
648
- return $robots_txt;
 
 
 
 
 
 
649
  }
650
 
651
  /**
@@ -667,13 +707,19 @@ class Init extends Query {
667
  * Sets the X-Robots-Tag headers on various endpoints.
668
  *
669
  * @since 4.0.0
 
670
  * @access private
671
  */
672
  public function _init_robots_headers() {
673
 
674
- if ( $this->is_feed() || $this->is_robots() ) {
 
 
 
 
 
 
675
  $this->_output_robots_noindex_headers();
676
- }
677
  }
678
 
679
  /**
@@ -885,4 +931,29 @@ class Init extends Query {
885
 
886
  return $blocked;
887
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
888
  }
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
298
  // Future, maybe. See <https://github.com/Automattic/jetpack/issues/13146#issuecomment-516841698>
299
  // \add_filter( 'jetpack_enable_twitter_cards', '__return_false' );
300
  }
301
+
302
+ if ( ! $this->get_option( 'oembed_scripts' ) ) {
303
+ /**
304
+ * Only hide the scripts, don't permeably purge them. That should be enough.
305
+ *
306
+ * This will still allow embedding within WordPress Multisite via WP-REST's proxy, since WP won't look for a script.
307
+ * We'd need to empty 'oembed_response_data' in that case... However, thanks to a bug in WP, this 'works' anyway.
308
+ * The bug: WP_oEmbed_Controller::get_proxy_item_permissions_check() always returns \WP_Error.
309
+ */
310
+ \remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
311
+ }
312
+ /**
313
+ * WordPress also filters this at priority '10', but it's registered before this runs.
314
+ * Careful, WordPress can switch blogs when this filter runs. So, run this always,
315
+ * and assess options (uncached!) therein.
316
+ */
317
+ \add_filter( 'oembed_response_data', [ $this, '_alter_oembed_response_data' ], 10, 4 );
318
  }
319
 
320
  /**
387
  $output = false;
388
  }
389
 
390
+ if ( false === $output ) {
391
+ $output = $this->get_html_output();
392
+ $this->use_object_cache and $this->object_cache_set( $cache_key, $output, DAY_IN_SECONDS );
393
+ }
394
 
395
+ // phpcs:ignore, WordPress.Security.EscapeOutput -- $output is escaped.
396
+ echo PHP_EOL, $this->get_plugin_indicator( 'before' ), $output, $this->get_plugin_indicator( 'after', $init_start ), PHP_EOL;
397
 
398
+ /**
399
+ * @since 2.6.0
400
+ */
401
+ \do_action( 'the_seo_framework_do_after_output' );
402
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
 
404
+ /**
405
+ * Generates front-end HTMl output.
406
+ *
407
+ * @since 4.0.5
408
+ * @todo convert $output to array and allow filtering it.
409
+ *
410
+ * @return string The HTML output.
411
+ */
412
+ public function get_html_output() {
413
 
414
+ $robots = $this->robots();
415
 
416
+ /** @since 4.0.4 : WP 5.3 patch, added. */
417
+ $this->set_timezone( 'UTC' );
418
+
419
+ /**
420
+ * @since 2.6.0
421
+ * @param string $before The content before the SEO output. Stored in object cache.
422
+ */
423
+ $before = (string) \apply_filters( 'the_seo_framework_pre', '' );
424
+
425
+ $before_legacy = $this->get_legacy_header_filters_output( 'before' );
426
+
427
+ //* Limit processing and redundant tags on 404 and search.
428
+ if ( $this->is_search() ) :
429
+ $output = $this->og_locale()
430
+ . $this->og_type()
431
+ . $this->og_title()
432
+ . $this->og_url()
433
+ . $this->og_sitename()
434
+ . $this->theme_color()
435
+ . $this->shortlink()
436
+ . $this->canonical()
437
+ . $this->paged_urls()
438
+ . $this->google_site_output()
439
+ . $this->bing_site_output()
440
+ . $this->yandex_site_output()
441
+ . $this->baidu_site_output()
442
+ . $this->pint_site_output();
443
+ elseif ( $this->is_404() ) :
444
+ $output = $this->theme_color()
445
+ . $this->google_site_output()
446
+ . $this->bing_site_output()
447
+ . $this->yandex_site_output()
448
+ . $this->baidu_site_output()
449
+ . $this->pint_site_output();
450
+ elseif ( $this->is_query_exploited() ) :
451
+ // aqp = advanced query protection
452
+ $output = '<meta name="tsf:aqp" value="1" />' . PHP_EOL;
453
+ else :
454
+ $output = $this->the_description()
455
+ . $this->og_image()
456
+ . $this->og_locale()
457
+ . $this->og_type()
458
+ . $this->og_title()
459
+ . $this->og_description()
460
+ . $this->og_url()
461
+ . $this->og_sitename()
462
+ . $this->facebook_publisher()
463
+ . $this->facebook_author()
464
+ . $this->facebook_app_id()
465
+ . $this->article_published_time()
466
+ . $this->article_modified_time()
467
+ . $this->twitter_card()
468
+ . $this->twitter_site()
469
+ . $this->twitter_creator()
470
+ . $this->twitter_title()
471
+ . $this->twitter_description()
472
+ . $this->twitter_image()
473
+ . $this->theme_color()
474
+ . $this->shortlink()
475
+ . $this->canonical()
476
+ . $this->paged_urls()
477
+ . $this->ld_json()
478
+ . $this->google_site_output()
479
+ . $this->bing_site_output()
480
+ . $this->yandex_site_output()
481
+ . $this->baidu_site_output()
482
+ . $this->pint_site_output();
483
  endif;
484
 
485
+ $after_legacy = $this->get_legacy_header_filters_output( 'after' );
 
486
 
487
  /**
488
  * @since 2.6.0
489
+ * @param string $after The content after the SEO output. Stored in object cache.
490
  */
491
+ $after = (string) \apply_filters( 'the_seo_framework_pro', '' );
492
+
493
+ /** @since 4.0.4 : WP 5.3 patch, added. */
494
+ $this->reset_timezone();
495
+
496
+ $output = $robots . $before . $before_legacy . $output . $after_legacy . $after;
497
+
498
+ return $output;
499
  }
500
 
501
  /**
502
  * Redirects singular page to an alternate URL.
503
  *
504
  * @since 2.9.0
505
+ * @since 3.1.0 : 1. Now no longer redirects on preview.
506
+ * 2. Now listens to post type settings.
507
+ * @since 4.0.0 : 1. No longer tries to redirect on "search".
508
+ * 2. Added term redirect support.
509
+ * 3. No longer redirects on Customizer.
510
  * @access private
511
  *
512
  * @return void early on non-singular pages.
518
  $url = '';
519
 
520
  if ( $this->is_singular() ) {
 
 
521
  $url = $this->get_post_meta_item( 'redirect' ) ?: '';
522
  } elseif ( $this->is_term_meta_capable() ) {
523
+ $url = $this->get_term_meta_item( 'redirect' ) ?: '';
 
 
 
524
  }
525
 
526
  $url and $this->do_redirect( $url );
587
 
588
  /**
589
  * Edits the robots.txt output.
590
+ * Requires the site not to have a robots.txt file in the root directory.
591
  *
592
  * This methods completely hijacks default output, intentionally.
593
+ *
594
  * The robots.txt file should be left as default, so to improve SEO.
595
  * The Robots Exclusion Protocol encourages you not to use this file for
596
+ * non-administrative endpoints. Use the robots meta tags (and headers) instead.
597
  *
598
  * @since 2.2.9
599
  * @since 2.9.3 Casts $public to string for check.
600
+ * @since 4.0.5 : 1. The output is now filterable.
601
+ * 2. Improved invalid location test.
602
+ * 3. No longer shortcircuits on non-public sites.
603
+ * 4. Now marked as private. Will be renamed to `_robots_txt()` in the future.
604
  * @uses robots_txt filter located at WP core
605
+ * @access private
606
  *
607
+ * @param string $robots_txt The current robots_txt output. Not used.
608
+ * @param string $public The blog_public option value. Not used.
609
  * @return string Robots.txt output.
610
  */
611
  public function robots_txt( $robots_txt = '', $public = '' ) {
612
 
 
 
 
 
 
 
613
  if ( $this->use_object_cache ) {
614
  $cache_key = $this->get_robots_txt_cache_key();
615
  $output = $this->object_cache_get( $cache_key );
620
  if ( false === $output ) :
621
  $output = '';
622
 
 
 
 
 
 
 
623
  $site_path = \esc_attr( parse_url( \site_url(), PHP_URL_PATH ) ) ?: '';
624
 
625
  /**
663
  $this->use_object_cache and $this->object_cache_set( $cache_key, $output, 86400 );
664
  endif;
665
 
666
+ $raw_uri = rawurldecode(
667
+ \wp_check_invalid_utf8(
668
+ stripslashes( $_SERVER['REQUEST_URI'] )
669
+ )
670
+ ) ?: '/robots.txt';
671
+
672
+ // Simple test for invalid directory depth. Even //robots.txt is an invalid location.
673
+ if ( strrpos( $raw_uri, '/' ) > 0 ) {
674
+ $error = sprintf(
675
+ "%s\r\n%s\r\n\r\n",
676
+ '# This is an invalid robots.txt location.',
677
+ '# Please visit: ' . \esc_url( \trailingslashit( $this->set_preferred_url_scheme( $this->get_home_host() ) ) . 'robots.txt' )
678
+ );
679
+ $output = $error . $output;
680
+ }
681
 
682
+ /**
683
+ * The robots.txt output. This filter output not cached; however, the $output variable can be via object caching.
684
+ *
685
+ * @since 4.0.5
686
+ * @param string $output The (cached) robots.txt output.
687
+ */
688
+ return (string) \apply_filters( 'the_seo_framework_robots_txt', $output );
689
  }
690
 
691
  /**
707
  * Sets the X-Robots-Tag headers on various endpoints.
708
  *
709
  * @since 4.0.0
710
+ * @since 4.0.5 Added filter.
711
  * @access private
712
  */
713
  public function _init_robots_headers() {
714
 
715
+ $noindex = $this->is_robots() || ( ! $this->get_option( 'index_the_feed' ) && $this->is_feed() );
716
+
717
+ /**
718
+ * @since 4.0.5
719
+ * @param bool $noindex Whether a noindex header must be set.
720
+ */
721
+ if ( \apply_filters( 'the_seo_framework_set_noindex_header', $noindex ) )
722
  $this->_output_robots_noindex_headers();
 
723
  }
724
 
725
  /**
931
 
932
  return $blocked;
933
  }
934
+
935
+ /**
936
+ * Alters the oEmbed response data.
937
+ *
938
+ * @WARNING: WordPress can switch blogs as this filter runs. So, check all options again, without cache!
939
+ * This should only happen at `/oembed/1.0/proxy`.
940
+ * @TODO consider adding the (optional(ly)) thumbnail_url data?
941
+ * @since 4.0.5
942
+ * @access private
943
+ *
944
+ * @param array $data The response data.
945
+ * @param WP_Post $post The post object.
946
+ * @param int $width The requested width.
947
+ * @param int $height The calculated height.
948
+ * @return array Possibly altered $data.
949
+ */
950
+ public function _alter_oembed_response_data( $data = [], $post = null, $width = 0, $height = 0 ) {
951
+
952
+ // Don't use cache. See @WARNING in doc comment.
953
+ if ( $this->get_option( 'oembed_remove_author', false ) ) {
954
+ unset( $data['author_url'], $data['author_name'] );
955
+ }
956
+
957
+ return $data;
958
+ }
959
  }
inc/classes/interpreters/seobar.class.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Interpreters;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/load.class.php CHANGED
@@ -11,7 +11,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
11
 
12
  /**
13
  * The SEO Framework plugin
14
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
15
  *
16
  * This program is free software: you can redistribute it and/or modify
17
  * it under the terms of the GNU General Public License version 3 as published
@@ -181,6 +181,9 @@ final class Load extends Feed {
181
  if ( $this->detect_plugin( [ 'functions' => [ 'wc' ] ] ) ) {
182
  //* WooCommerce.
183
  $this->_include_compat( 'woocommerce', 'plugin' );
 
 
 
184
  }
185
  }
186
 
11
 
12
  /**
13
  * The SEO Framework plugin
14
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
15
  *
16
  * This program is free software: you can redistribute it and/or modify
17
  * it under the terms of the GNU General Public License version 3 as published
181
  if ( $this->detect_plugin( [ 'functions' => [ 'wc' ] ] ) ) {
182
  //* WooCommerce.
183
  $this->_include_compat( 'woocommerce', 'plugin' );
184
+ } elseif ( $this->detect_plugin( [ 'constants' => [ 'EDD_VERSION' ] ] ) ) {
185
+ //* Easy Digital Downloads.
186
+ $this->_include_compat( 'edd', 'plugin' );
187
  }
188
  }
189
 
inc/classes/post-data.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -122,7 +122,22 @@ class Post_Data extends Detect {
122
  $meta[ $key ] = $value[0];
123
  }
124
 
125
- return $cache[ $post_id ] = array_merge( $defaults, $meta );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  }
127
 
128
  /**
@@ -500,7 +515,7 @@ class Post_Data extends Detect {
500
  //* Check that the user is allowed to edit the post. Nonce checks are done in bulk later.
501
  if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
502
 
503
- $post_type = \get_post_type( $post->ID ) ?: false;
504
  // Can this even fail?
505
  if ( ! $post_type ) return;
506
 
@@ -597,8 +612,8 @@ class Post_Data extends Detect {
597
 
598
  /**
599
  * @since 2.6.6
600
- * @since 3.1.0 1: Now defaults to `null`
601
- * 2: Now, when a boolean (either true or false) is defined, it'll short-circuit this function.
602
  * @param boolean|null $detected Whether a builder should be detected.
603
  * @param int $post_id The current Post ID.
604
  * @param array $meta The current post meta.
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
122
  $meta[ $key ] = $value[0];
123
  }
124
 
125
+ /**
126
+ * @since 4.0.5
127
+ * @note Do not delete/unset/add indexes! It'll cause errors.
128
+ * @param array $meta The current post meta.
129
+ * @param int $post_id The post ID.
130
+ */
131
+ $meta = \apply_filters_ref_array(
132
+ 'the_seo_framework_post_meta',
133
+ [
134
+ array_merge( $defaults, $meta ),
135
+ $post->ID,
136
+ ]
137
+ );
138
+
139
+ // Cache using the input ID, otherwise invalid queries can bypass the cache.
140
+ return $cache[ $post_id ] = $meta;
141
  }
142
 
143
  /**
515
  //* Check that the user is allowed to edit the post. Nonce checks are done in bulk later.
516
  if ( ! \current_user_can( 'edit_post', $post->ID ) ) return;
517
 
518
+ $post_type = \get_post_type( $post ) ?: false;
519
  // Can this even fail?
520
  if ( ! $post_type ) return;
521
 
612
 
613
  /**
614
  * @since 2.6.6
615
+ * @since 3.1.0 : 1. Now defaults to `null`
616
+ * 2. Now, when a boolean (either true or false) is defined, it'll short-circuit this function.
617
  * @param boolean|null $detected Whether a builder should be detected.
618
  * @param int $post_id The current Post ID.
619
  * @param array $meta The current post meta.
inc/classes/profile.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
inc/classes/query.class.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
@@ -52,7 +52,7 @@ class Query extends Core {
52
  * 2. Now asks for and passes $method.
53
  * 3. Now returns false on WP CLI.
54
  * @since 3.2.2 No longer spits out errors on production websites.
55
- * @staticvar bool $cache : Always true if set.
56
  * @global \WP_Query $wp_query
57
  * @global \WP_Screen|null $current_screen
58
  *
@@ -108,6 +108,21 @@ class Query extends Core {
108
  }
109
  // phpcs:enable -- Method unused in production.
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  /**
112
  * Returns the post type name from current screen.
113
  *
@@ -206,22 +221,14 @@ class Query extends Core {
206
  * @since 2.5.0
207
  * @since 3.1.0 1. Now checks for the feed.
208
  * 2. No longer caches.
 
 
209
  *
210
  * @return int The admin ID.
211
  */
212
  public function check_the_real_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
213
 
214
- $id = 0;
215
-
216
- if ( $this->is_feed() ) {
217
- $id = \get_the_ID();
218
- } elseif ( $this->is_wc_shop() ) {
219
- //* WooCommerce Shop. TODO set in compat file?
220
- $id = \get_option( 'woocommerce_shop_page_id' );
221
- } elseif ( function_exists( 'get_question_id' ) && \did_action( 'template_redirect' ) ) {
222
- //* AnsPress. TODO set in compat file.
223
- $id = \get_question_id();
224
- }
225
 
226
  /**
227
  * @since 2.5.0
@@ -359,11 +366,46 @@ class Query extends Core {
359
  * Simply put, it detects a blog page and WooCommerce shop page.
360
  *
361
  * @since 3.1.0
 
 
 
362
  *
 
363
  * @return bool
364
  */
365
- public function is_singular_archive() {
366
- return $this->is_blog_page() || $this->is_wc_shop();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
  }
368
 
369
  /**
@@ -690,7 +732,7 @@ class Query extends Core {
690
  *
691
  * @since 2.9.0
692
  * @since 2.9.3 Now tests for archive and 404 before testing homepage as blog.
693
- * @since 3.2.2: Removed SEO settings page check. This now returns false on that page.
694
  *
695
  * @param int $id The page ID, required. Can be 0.
696
  * @return bool True if ID if for the homepage.
@@ -741,7 +783,6 @@ class Query extends Core {
741
  * Determines whether the query is for the blog page.
742
  *
743
  * @since 2.6.0
744
- * @staticvar bool $cache
745
  *
746
  * @return bool
747
  */
@@ -767,7 +808,6 @@ class Query extends Core {
767
  * @since 2.6.0
768
  * @since 4.0.0 Now tests for post type, which is more reliable.
769
  * @ignore not used internally, polar opposite of is_single().
770
- * @staticvar bool $cache
771
  * @uses $this->is_singular()
772
  *
773
  * @param int|string|array $page Optional. Page ID, title, slug, or array of such. Default empty.
@@ -822,7 +862,6 @@ class Query extends Core {
822
  * 2. Added is_singular() check, so get_the_ID() won't cross with blog pages.
823
  * 3. Added current_user_can() check.
824
  * 4. Added wp_verify_nonce() check.
825
- * @staticvar bool $cache
826
  *
827
  * @return bool
828
  */
@@ -861,7 +900,6 @@ class Query extends Core {
861
  *
862
  * @since 2.6.0
863
  * @since 4.0.0 Now tests for post type, which is more reliable.
864
- * @staticvar bool $cache
865
  * @uses The_SEO_Framework_Query::is_single_admin()
866
  *
867
  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
@@ -907,14 +945,12 @@ class Query extends Core {
907
 
908
  /**
909
  * Determines if the current page is singular is holds singular items within the admin screen.
910
- * Replaces and expands default WordPress is_singular().
911
  *
912
  * @since 2.5.2
913
  * @since 3.1.0 Now passes $post_types parameter in admin screens, only when it's an integer.
914
  * @since 4.0.0 No longer processes integers as input.
915
- * @uses The_SEO_Framework_Query::is_singular_admin()
916
- * @uses The_SEO_Framework_Query::is_blog_page()
917
- * @uses The_SEO_Framework_Query::is_wc_shop()
918
  *
919
  * @param string|array $post_types Optional. Post type or array of post types. Default empty string.
920
  * @return bool Post Type is singular
@@ -981,7 +1017,6 @@ class Query extends Core {
981
  /**
982
  * Detects tag archives.
983
  *
984
- * @staticvar bool $cache
985
  * @since 2.6.0
986
  * @uses $this->is_archive()
987
  *
@@ -1047,22 +1082,93 @@ class Query extends Core {
1047
  }
1048
 
1049
  /**
1050
- * Determines if the page is the WooCommerce plugin Shop page.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1051
  *
1052
  * @since 2.5.2
1053
- * @staticvar bool $cache
 
 
 
1054
  *
 
1055
  * @return bool True if on the WooCommerce shop page.
1056
  */
1057
- public function is_wc_shop() {
 
 
 
 
 
 
 
1058
 
1059
  // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
1060
- if ( null !== $cache = $this->get_query_cache( __METHOD__ ) )
1061
  return $cache;
1062
 
 
 
 
 
 
 
1063
  $this->set_query_cache(
1064
  __METHOD__,
1065
- $is_shop = ! \is_admin() && function_exists( 'is_shop' ) && \is_shop()
 
1066
  );
1067
 
1068
  return $is_shop;
@@ -1074,6 +1180,9 @@ class Query extends Core {
1074
  * @since 2.5.2
1075
  * @since 4.0.0 : 1. Added admin support.
1076
  * 2. Added parameter for the Post ID or post to test.
 
 
 
1077
  *
1078
  * @param int|\WP_Post $post When set, checks if the post is of type product.
1079
  * @return bool True if on a WooCommerce Product page.
@@ -1106,7 +1215,10 @@ class Query extends Core {
1106
  * Detects products within the admin area.
1107
  *
1108
  * @since 4.0.0
1109
- * @see The_SEO_Framework_Query::is_wc_product()
 
 
 
1110
  *
1111
  * @return bool
1112
  */
@@ -1401,13 +1513,13 @@ class Query extends Core {
1401
  * Handles object cache for the query class.
1402
  *
1403
  * @since 2.7.0
1404
- * @staticvar null|bool $can_cache_query : True when this function can run.
1405
- * @staticvar mixed $cache : The cached query values.
1406
  * @see $this->set_query_cache(); to set query cache.
1407
  *
1408
  * @param string $method The method that wants to cache, used as the key to set or get.
1409
  * @param mixed $value_to_set The value to set.
1410
- * @param mixed ...$hash Extra arguments, that will are used to differentiaty queries.
1411
  * @return mixed : {
1412
  * mixed The cached value if set and $value_to_set is null.
1413
  * null If the query can't be cached yet, or when no value has been set.
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
52
  * 2. Now asks for and passes $method.
53
  * 3. Now returns false on WP CLI.
54
  * @since 3.2.2 No longer spits out errors on production websites.
55
+ * @staticvar bool $cache Always true once set.
56
  * @global \WP_Query $wp_query
57
  * @global \WP_Screen|null $current_screen
58
  *
108
  }
109
  // phpcs:enable -- Method unused in production.
110
 
111
+ /**
112
+ * Returns the post type name from query input or real ID.
113
+ *
114
+ * @since 4.0.5
115
+ *
116
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
117
+ * @return string|false Post type on success, false on failure.
118
+ */
119
+ public function get_post_type_real_ID( $post = null ) {
120
+
121
+ $post = is_null( $post ) ? $this->get_the_real_ID() : $post;
122
+
123
+ return \get_post_type( $post );
124
+ }
125
+
126
  /**
127
  * Returns the post type name from current screen.
128
  *
221
  * @since 2.5.0
222
  * @since 3.1.0 1. Now checks for the feed.
223
  * 2. No longer caches.
224
+ * @since 4.0.5 1. The shop ID is now handled via the filter.
225
+ * 2. The question ID (AnsPress) is no longer called. This should work out-of-the-box since AnsPress 4.1.
226
  *
227
  * @return int The admin ID.
228
  */
229
  public function check_the_real_ID() { // phpcs:ignore -- ID is capitalized because WordPress does that too: get_the_ID().
230
 
231
+ $id = $this->is_feed() ? \get_the_ID() : 0;
 
 
 
 
 
 
 
 
 
 
232
 
233
  /**
234
  * @since 2.5.0
366
  * Simply put, it detects a blog page and WooCommerce shop page.
367
  *
368
  * @since 3.1.0
369
+ * @since 4.0.5 1. The output is now filterable.
370
+ * 2. Added caching.
371
+ * 3. Now has a first parameter `$post`.
372
  *
373
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
374
  * @return bool
375
  */
376
+ public function is_singular_archive( $post = null ) {
377
+
378
+ if ( isset( $post ) ) {
379
+ $post = \get_post( $post );
380
+ $id = $post ? $post->ID : 0;
381
+ } else {
382
+ $id = $this->get_the_real_ID();
383
+ }
384
+
385
+ // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
386
+ if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $id ) )
387
+ return $cache;
388
+
389
+ /**
390
+ * @since 4.0.5
391
+ * @param bool $is_singular_archive Whether the post ID is a singular archive.
392
+ * @param int $id The current or supplied post ID.
393
+ */
394
+ $is_singular_archive = \apply_filters_ref_array(
395
+ 'the_seo_framework_is_singular_archive',
396
+ [
397
+ $this->is_blog_page_by_id( $id ),
398
+ $id,
399
+ ]
400
+ );
401
+
402
+ $this->set_query_cache(
403
+ __METHOD__,
404
+ $is_singular_archive,
405
+ $id
406
+ );
407
+
408
+ return $is_singular_archive;
409
  }
410
 
411
  /**
732
  *
733
  * @since 2.9.0
734
  * @since 2.9.3 Now tests for archive and 404 before testing homepage as blog.
735
+ * @since 3.2.2 Removed SEO settings page check. This now returns false on that page.
736
  *
737
  * @param int $id The page ID, required. Can be 0.
738
  * @return bool True if ID if for the homepage.
783
  * Determines whether the query is for the blog page.
784
  *
785
  * @since 2.6.0
 
786
  *
787
  * @return bool
788
  */
808
  * @since 2.6.0
809
  * @since 4.0.0 Now tests for post type, which is more reliable.
810
  * @ignore not used internally, polar opposite of is_single().
 
811
  * @uses $this->is_singular()
812
  *
813
  * @param int|string|array $page Optional. Page ID, title, slug, or array of such. Default empty.
862
  * 2. Added is_singular() check, so get_the_ID() won't cross with blog pages.
863
  * 3. Added current_user_can() check.
864
  * 4. Added wp_verify_nonce() check.
 
865
  *
866
  * @return bool
867
  */
900
  *
901
  * @since 2.6.0
902
  * @since 4.0.0 Now tests for post type, which is more reliable.
 
903
  * @uses The_SEO_Framework_Query::is_single_admin()
904
  *
905
  * @param int|string|array $post Optional. Post ID, title, slug, or array of such. Default empty.
945
 
946
  /**
947
  * Determines if the current page is singular is holds singular items within the admin screen.
948
+ * Replaces and expands default WordPress `is_singular()`.
949
  *
950
  * @since 2.5.2
951
  * @since 3.1.0 Now passes $post_types parameter in admin screens, only when it's an integer.
952
  * @since 4.0.0 No longer processes integers as input.
953
+ * @uses $this->is_singular_admin()
 
 
954
  *
955
  * @param string|array $post_types Optional. Post type or array of post types. Default empty string.
956
  * @return bool Post Type is singular
1017
  /**
1018
  * Detects tag archives.
1019
  *
 
1020
  * @since 2.6.0
1021
  * @uses $this->is_archive()
1022
  *
1082
  }
1083
 
1084
  /**
1085
+ * Determines if the $post is a shop page.
1086
+ *
1087
+ * @since 4.0.5
1088
+ *
1089
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
1090
+ * @return bool
1091
+ */
1092
+ public function is_shop( $post = null ) {
1093
+ /**
1094
+ * @since 4.0.5
1095
+ * @param bool $is_shop Whether the post ID is a shop.
1096
+ * @param int $id The current or supplied post ID.
1097
+ */
1098
+ return \apply_filters_ref_array( 'the_seo_framework_is_shop', [ false, $post ] );
1099
+ }
1100
+
1101
+ /**
1102
+ * Determines if the page is a product page.
1103
+ *
1104
+ * @since 4.0.5
1105
+ *
1106
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
1107
+ * @return bool True if on a WooCommerce Product page.
1108
+ */
1109
+ public function is_product( $post = null ) {
1110
+
1111
+ if ( \is_admin() )
1112
+ return $this->is_product_admin();
1113
+
1114
+ /**
1115
+ * @since 4.0.5
1116
+ * @param bool $is_product
1117
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
1118
+ */
1119
+ return (bool) \apply_filters_ref_array( 'the_seo_framework_is_product', [ false, $post ] );
1120
+ }
1121
+
1122
+ /**
1123
+ * Determines if the admin page is for a product page.
1124
+ *
1125
+ * @since 4.0.5
1126
+ *
1127
+ * @return bool
1128
+ */
1129
+ public function is_product_admin() {
1130
+ /**
1131
+ * @since 4.0.5
1132
+ * @param bool $is_product_admin
1133
+ */
1134
+ return (bool) \apply_filters( 'the_seo_framework_is_product_admin', false );
1135
+ }
1136
+
1137
+ /**
1138
+ * Determines if the $post is the WooCommerce plugin shop page.
1139
  *
1140
  * @since 2.5.2
1141
+ * @since 4.0.5 Now has a first parameter `$post`.
1142
+ * @since 4.0.5 Soft deprecated.
1143
+ * @deprecated
1144
+ * @internal
1145
  *
1146
+ * @param int|WP_Post|null $post (Optional) Post ID or post object.
1147
  * @return bool True if on the WooCommerce shop page.
1148
  */
1149
+ public function is_wc_shop( $post = null ) {
1150
+
1151
+ if ( isset( $post ) ) {
1152
+ $post = \get_post( $post );
1153
+ $id = $post ? $post->ID : 0;
1154
+ } else {
1155
+ $id = null;
1156
+ }
1157
 
1158
  // phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition
1159
+ if ( null !== $cache = $this->get_query_cache( __METHOD__, null, $id ) )
1160
  return $cache;
1161
 
1162
+ if ( isset( $id ) ) {
1163
+ $is_shop = (int) \get_option( 'woocommerce_shop_page_id' ) === $id;
1164
+ } else {
1165
+ $is_shop = ! \is_admin() && function_exists( 'is_shop' ) && \is_shop();
1166
+ }
1167
+
1168
  $this->set_query_cache(
1169
  __METHOD__,
1170
+ $is_shop,
1171
+ $id
1172
  );
1173
 
1174
  return $is_shop;
1180
  * @since 2.5.2
1181
  * @since 4.0.0 : 1. Added admin support.
1182
  * 2. Added parameter for the Post ID or post to test.
1183
+ * @since 4.0.5 Soft deprecated.
1184
+ * @deprecated
1185
+ * @internal
1186
  *
1187
  * @param int|\WP_Post $post When set, checks if the post is of type product.
1188
  * @return bool True if on a WooCommerce Product page.
1215
  * Detects products within the admin area.
1216
  *
1217
  * @since 4.0.0
1218
+ * @see $this->is_wc_product()
1219
+ * @since 4.0.5 Soft deprecated.
1220
+ * @deprecated
1221
+ * @internal
1222
  *
1223
  * @return bool
1224
  */
1513
  * Handles object cache for the query class.
1514
  *
1515
  * @since 2.7.0
1516
+ * @staticvar null|bool $can_cache_query True when this function can run.
1517
+ * @staticvar mixed $cache The cached query values.
1518
  * @see $this->set_query_cache(); to set query cache.
1519
  *
1520
  * @param string $method The method that wants to cache, used as the key to set or get.
1521
  * @param mixed $value_to_set The value to set.
1522
+ * @param mixed ...$hash Extra arguments, that are used to differentiaty queries.
1523
  * @return mixed : {
1524
  * mixed The cached value if set and $value_to_set is null.
1525
  * null If the query can't be cached yet, or when no value has been set.
inc/classes/render.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -576,6 +576,25 @@ class Render extends Admin_Init {
576
  return $output;
577
  }
578
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
  /**
580
  * Renders Facebook Author meta tag.
581
  *
@@ -686,9 +705,9 @@ class Render extends Admin_Init {
686
  *
687
  * @since 2.2.2
688
  * @since 2.8.0 Returns empty on product pages.
689
- * @since 3.0.0: 1. Now checks for 0000 timestamps.
690
- * 2. Now uses timestamp formats.
691
- * 3. Now uses GMT time.
692
  *
693
  * @return string The Article Publishing Time meta tag.
694
  */
@@ -732,8 +751,8 @@ class Render extends Admin_Init {
732
  * @since 2.2.2
733
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
734
  * @since 2.8.0 Returns empty on product pages.
735
- * @since 3.0.0: 1. Now checks for 0000 timestamps.
736
- * 2. Now uses timestamp formats.
737
  *
738
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
739
  */
@@ -928,6 +947,34 @@ class Render extends Admin_Init {
928
  return '';
929
  }
930
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
931
  /**
932
  * Renders Pinterest Site Verification code meta tag.
933
  *
@@ -988,7 +1035,9 @@ class Render extends Admin_Init {
988
  * @return array
989
  */
990
  public function get_robots_meta() {
 
991
  static $cache = null;
 
992
  /**
993
  * @since 2.6.0
994
  * @param array $meta The robots meta.
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
576
  return $output;
577
  }
578
 
579
+ /**
580
+ * Renders Theme Color meta tag.
581
+ *
582
+ * @since 4.0.5
583
+ *
584
+ * @return string The Theme Color meta tag.
585
+ */
586
+ public function theme_color() {
587
+
588
+ $theme_color = $this->get_option( 'theme_color' );
589
+
590
+ $output = '';
591
+
592
+ if ( $theme_color )
593
+ $output = '<meta name="theme-color" content="' . \esc_attr( $theme_color ) . '" />' . "\r\n";
594
+
595
+ return $output;
596
+ }
597
+
598
  /**
599
  * Renders Facebook Author meta tag.
600
  *
705
  *
706
  * @since 2.2.2
707
  * @since 2.8.0 Returns empty on product pages.
708
+ * @since 3.0.0 : 1. Now checks for 0000 timestamps.
709
+ * 2. Now uses timestamp formats.
710
+ * 3. Now uses GMT time.
711
  *
712
  * @return string The Article Publishing Time meta tag.
713
  */
751
  * @since 2.2.2
752
  * @since 2.7.0 Listens to $this->get_the_real_ID() instead of WordPress Core ID determination.
753
  * @since 2.8.0 Returns empty on product pages.
754
+ * @since 3.0.0 : 1. Now checks for 0000 timestamps.
755
+ * 2. Now uses timestamp formats.
756
  *
757
  * @return string The Article Modified Time meta tag, and optionally the Open Graph Updated Time.
758
  */
947
  return '';
948
  }
949
 
950
+ /**
951
+ * Renders Baidu Site Verification code meta tag.
952
+ *
953
+ * @since 4.0.5
954
+ *
955
+ * @return string The Baidu Site Verification code meta tag.
956
+ */
957
+ public function baidu_site_output() {
958
+
959
+ /**
960
+ * @since 4.0.5
961
+ * @param string $code The Baidu verification code.
962
+ * @param int $id The current post or term ID.
963
+ */
964
+ $code = (string) \apply_filters_ref_array(
965
+ 'the_seo_framework_baidusite_output',
966
+ [
967
+ $this->get_option( 'baidu_verification' ),
968
+ $this->get_the_real_ID(),
969
+ ]
970
+ );
971
+
972
+ if ( $code )
973
+ return '<meta name="baidu-site-verification" content="' . \esc_attr( $code ) . '" />' . PHP_EOL;
974
+
975
+ return '';
976
+ }
977
+
978
  /**
979
  * Renders Pinterest Site Verification code meta tag.
980
  *
1035
  * @return array
1036
  */
1037
  public function get_robots_meta() {
1038
+
1039
  static $cache = null;
1040
+
1041
  /**
1042
  * @since 2.6.0
1043
  * @param array $meta The robots meta.
inc/classes/sanitize.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -166,12 +166,6 @@ class Sanitize extends Admin_Pages {
166
  ]
167
  );
168
 
169
- $this->add_option_filter(
170
- 's_description',
171
- THE_SEO_FRAMEWORK_SITE_OPTIONS,
172
- []
173
- );
174
-
175
  $this->add_option_filter(
176
  's_description_raw',
177
  THE_SEO_FRAMEWORK_SITE_OPTIONS,
@@ -244,7 +238,6 @@ class Sanitize extends Admin_Pages {
244
  'display_pixel_counter',
245
  'display_character_counter',
246
 
247
- 'cache_meta_schema',
248
  'cache_sitemap',
249
  'cache_object',
250
 
@@ -279,6 +272,8 @@ class Sanitize extends Admin_Pages {
279
  'search_noarchive',
280
  'site_noarchive',
281
 
 
 
282
  'paged_noindex',
283
  'home_paged_noindex',
284
 
@@ -296,9 +291,12 @@ class Sanitize extends Admin_Pages {
296
  'prev_next_archives',
297
  'prev_next_frontpage',
298
 
 
 
299
  'og_tags',
300
  'facebook_tags',
301
  'twitter_tags',
 
302
 
303
  'multi_og_image',
304
 
@@ -315,6 +313,7 @@ class Sanitize extends Admin_Pages {
315
 
316
  'excerpt_the_feed',
317
  'source_the_feed',
 
318
 
319
  'ld_json_searchbox',
320
  'ld_json_breadcrumbs',
@@ -377,6 +376,7 @@ class Sanitize extends Admin_Pages {
377
  'google_verification',
378
  'bing_verification',
379
  'yandex_verification',
 
380
  'pint_verification',
381
  ]
382
  );
@@ -447,6 +447,7 @@ class Sanitize extends Admin_Pages {
447
  [
448
  'sitemap_color_main',
449
  'sitemap_color_accent',
 
450
  ]
451
  );
452
 
@@ -484,7 +485,7 @@ class Sanitize extends Admin_Pages {
484
  * sanitizer at the right time.
485
  *
486
  * @since 2.2.2
487
- * @since 2.7.0: Uses external caching function.
488
  * @since 2.8.0 Renamed.
489
  * @since 4.0.0 Now caches its $option registration.
490
  * @staticvar array $cache
@@ -857,6 +858,7 @@ class Sanitize extends Admin_Pages {
857
  * Also converts back-solidi to their respective HTML entities for non-destructive handling.
858
  *
859
  * @since 2.8.2
 
860
  *
861
  * @param string $new_value The Description.
862
  * @return string One line sanitized description.
@@ -866,6 +868,7 @@ class Sanitize extends Admin_Pages {
866
  $new_value = $this->s_singleline( $new_value );
867
  $new_value = $this->s_nbsp( $new_value );
868
  $new_value = $this->s_tabs( $new_value );
 
869
  $new_value = $this->s_bsol( $new_value );
870
  $new_value = $this->s_dupe_space( $new_value );
871
 
@@ -919,6 +922,7 @@ class Sanitize extends Admin_Pages {
919
  * @since 2.8.0
920
  * @since 2.8.2 : 1. Added $allow_shortcodes parameter.
921
  * 2. Added $escape parameter.
 
922
  * @see `$this->strip_tags_cs()`
923
  *
924
  * @param string $excerpt The excerpt.
@@ -935,7 +939,7 @@ class Sanitize extends Admin_Pages {
935
  'space' =>
936
  [ 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure', 'footer', 'li', 'main', 'ol', 'p', 'section', 'tfoot', 'ul' ],
937
  'clear' =>
938
- [ 'address', 'bdo', 'br', 'button', 'canvas', 'code', 'fieldset', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'input', 'label', 'link', 'meta', 'nav', 'noscript', 'option', 'pre', 'samp', 'script', 'select', 'style', 'svg', 'table', 'textarea', 'var', 'video' ],
939
  ];
940
 
941
  /**
@@ -1011,6 +1015,7 @@ class Sanitize extends Admin_Pages {
1011
  *
1012
  * @since 2.8.2
1013
  * @since 4.0.0 Now normalizes `&` entities.
 
1014
  *
1015
  * @param string $new_value The input Title.
1016
  * @return string Sanitized, beautified and trimmed title.
@@ -1020,6 +1025,7 @@ class Sanitize extends Admin_Pages {
1020
  $new_value = $this->s_singleline( $new_value );
1021
  $new_value = $this->s_nbsp( $new_value );
1022
  $new_value = $this->s_tabs( $new_value );
 
1023
  $new_value = $this->s_bsol( $new_value );
1024
  $new_value = $this->s_dupe_space( $new_value );
1025
 
@@ -1340,10 +1346,10 @@ class Sanitize extends Admin_Pages {
1340
  *
1341
  * @since 2.2.2
1342
  * @since 2.8.0 Method is now public.
1343
- * @since 3.0.0: 1. Now removes '@' from the URL path.
1344
- * 2. Now removes spaces and tabs.
1345
- * @since 4.0.0: 1. Now returns empty on lone `@` entries.
1346
- * 2. Now returns empty when using only spaces and tabs.
1347
  *
1348
  * @param string $new_value String with potentially wrong Twitter username.
1349
  * @return string String with 'correct' Twitter username
@@ -1375,8 +1381,8 @@ class Sanitize extends Admin_Pages {
1375
  * @since 2.2.2
1376
  * @since 2.8.0 Method is now public.
1377
  * @since 3.0.6 Now allows a sole query argument when profile.php is used.
1378
- * @since 4.0.0: 1. No longer returns a plain Facebook URL when the entry path is sanitized to become empty.
1379
- * 2. Now returns empty when using only spaces and tabs.
1380
  *
1381
  * @param string $new_value String with potentially wrong Facebook profile URL.
1382
  * @return string String with 'correct' Facebook profile URL.
@@ -1538,6 +1544,30 @@ class Sanitize extends Admin_Pages {
1538
  return '';
1539
  }
1540
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1541
  /**
1542
  * Replaces non-break spaces with regular spaces.
1543
  *
@@ -1715,7 +1745,12 @@ class Sanitize extends Admin_Pages {
1715
  *
1716
  * @since 3.2.4
1717
  * @since 4.0.0 Now allows emptying the indexes `space` and `clear`.
1718
- * @link: https://www.w3schools.com/html/html_blocks.asp
 
 
 
 
 
1719
  *
1720
  * @param string $input The input text that needs its tags stripped.
1721
  * @param array $args The input arguments: {
@@ -1725,9 +1760,10 @@ class Sanitize extends Admin_Pages {
1725
  * 'clear' : @param array|null HTML elements that should be emptied and replaced with a space.
1726
  * If not set or null, skip check.
1727
  * If empty array, skips stripping; otherwise, use input.
 
1728
  * }
1729
- * NOTE: WARNING The array values are forwarded to a regex without sanitization.
1730
- * NOTE: Unlisted, script, and style tags will be stripped via PHP's `strip_tags()`.
1731
  * Also note that their contents are maintained as-is, without added spaces.
1732
  * It is why you should always list `style` and `script` in the `clear` array.
1733
  * @return string The output string without tags.
@@ -1738,9 +1774,12 @@ class Sanitize extends Admin_Pages {
1738
  'space' =>
1739
  [ 'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'tfoot', 'ul' ],
1740
  'clear' =>
1741
- [ 'bdo', 'br', 'button', 'canvas', 'code', 'hr', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
 
1742
  ];
1743
 
 
 
1744
  if ( ! $args ) {
1745
  $args = $default_args;
1746
  } else {
@@ -1753,20 +1792,34 @@ class Sanitize extends Admin_Pages {
1753
  }
1754
  }
1755
  }
 
1756
  }
1757
 
1758
  // Clear first, so there's less to process; then add spaces.
1759
  foreach ( [ 'clear', 'space' ] as $type ) {
1760
  if ( empty( $args[ $type ] ) ) continue;
1761
 
1762
- $_regex = sprintf( '<(%s)[^>]*?>((.*?)(<\/\1>))?', implode( '|', $args[ $type ] ) );
 
 
 
 
1763
  $_replace = 'space' === $type ? ' $2 ' : ' ';
1764
 
1765
- $input = preg_replace( "/$_regex/si", $_replace, $input );
 
 
 
 
 
 
 
 
 
1766
  }
1767
 
1768
  // phpcs:ignore, WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- $args defines stripping of 'script' and 'style'.
1769
- return strip_tags( $input );
1770
  }
1771
 
1772
  /**
@@ -1774,6 +1827,7 @@ class Sanitize extends Admin_Pages {
1774
  *
1775
  * @since 4.0.0
1776
  * @since 4.0.2 Now finds smaller images when they're over 4K.
 
1777
  * @NOTE If the input details are in an associative array, they'll be converted to sequential.
1778
  *
1779
  * @param array $details The image details, either associative (see $defaults) or sequential.
@@ -1806,6 +1860,22 @@ class Sanitize extends Admin_Pages {
1806
 
1807
  if ( ! $url ) return $defaults;
1808
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1809
  $width = (int) $width;
1810
  $height = (int) $height;
1811
 
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
166
  ]
167
  );
168
 
 
 
 
 
 
 
169
  $this->add_option_filter(
170
  's_description_raw',
171
  THE_SEO_FRAMEWORK_SITE_OPTIONS,
238
  'display_pixel_counter',
239
  'display_character_counter',
240
 
 
241
  'cache_sitemap',
242
  'cache_object',
243
 
272
  'search_noarchive',
273
  'site_noarchive',
274
 
275
+ 'advanced_query_protection',
276
+
277
  'paged_noindex',
278
  'home_paged_noindex',
279
 
291
  'prev_next_archives',
292
  'prev_next_frontpage',
293
 
294
+ 'oembed_remove_author',
295
+
296
  'og_tags',
297
  'facebook_tags',
298
  'twitter_tags',
299
+ 'oembed_scripts',
300
 
301
  'multi_og_image',
302
 
313
 
314
  'excerpt_the_feed',
315
  'source_the_feed',
316
+ 'index_the_feed',
317
 
318
  'ld_json_searchbox',
319
  'ld_json_breadcrumbs',
376
  'google_verification',
377
  'bing_verification',
378
  'yandex_verification',
379
+ 'baidu_verification',
380
  'pint_verification',
381
  ]
382
  );
447
  [
448
  'sitemap_color_main',
449
  'sitemap_color_accent',
450
+ 'theme_color',
451
  ]
452
  );
453
 
485
  * sanitizer at the right time.
486
  *
487
  * @since 2.2.2
488
+ * @since 2.7.0 Uses external caching function.
489
  * @since 2.8.0 Renamed.
490
  * @since 4.0.0 Now caches its $option registration.
491
  * @staticvar array $cache
858
  * Also converts back-solidi to their respective HTML entities for non-destructive handling.
859
  *
860
  * @since 2.8.2
861
+ * @since 4.0.5 Now normalized `-` entities.
862
  *
863
  * @param string $new_value The Description.
864
  * @return string One line sanitized description.
868
  $new_value = $this->s_singleline( $new_value );
869
  $new_value = $this->s_nbsp( $new_value );
870
  $new_value = $this->s_tabs( $new_value );
871
+ $new_value = $this->s_hyphen( $new_value );
872
  $new_value = $this->s_bsol( $new_value );
873
  $new_value = $this->s_dupe_space( $new_value );
874
 
922
  * @since 2.8.0
923
  * @since 2.8.2 : 1. Added $allow_shortcodes parameter.
924
  * 2. Added $escape parameter.
925
+ * @since 3.2.4 Now selectively clears tags.
926
  * @see `$this->strip_tags_cs()`
927
  *
928
  * @param string $excerpt The excerpt.
939
  'space' =>
940
  [ 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure', 'footer', 'li', 'main', 'ol', 'p', 'section', 'tfoot', 'ul' ],
941
  'clear' =>
942
+ [ 'address', 'bdo', 'br', 'button', 'canvas', 'code', 'fieldset', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hr', 'iframe', 'input', 'label', 'link', 'meta', 'nav', 'noscript', 'option', 'pre', 'samp', 'script', 'select', 'style', 'svg', 'table', 'textarea', 'var', 'video' ],
943
  ];
944
 
945
  /**
1015
  *
1016
  * @since 2.8.2
1017
  * @since 4.0.0 Now normalizes `&` entities.
1018
+ * @since 4.0.5 Now normalized `-` entities.
1019
  *
1020
  * @param string $new_value The input Title.
1021
  * @return string Sanitized, beautified and trimmed title.
1025
  $new_value = $this->s_singleline( $new_value );
1026
  $new_value = $this->s_nbsp( $new_value );
1027
  $new_value = $this->s_tabs( $new_value );
1028
+ $new_value = $this->s_hyphen( $new_value );
1029
  $new_value = $this->s_bsol( $new_value );
1030
  $new_value = $this->s_dupe_space( $new_value );
1031
 
1346
  *
1347
  * @since 2.2.2
1348
  * @since 2.8.0 Method is now public.
1349
+ * @since 3.0.0 : 1. Now removes '@' from the URL path.
1350
+ * 2. Now removes spaces and tabs.
1351
+ * @since 4.0.0 : 1. Now returns empty on lone `@` entries.
1352
+ * 2. Now returns empty when using only spaces and tabs.
1353
  *
1354
  * @param string $new_value String with potentially wrong Twitter username.
1355
  * @return string String with 'correct' Twitter username
1381
  * @since 2.2.2
1382
  * @since 2.8.0 Method is now public.
1383
  * @since 3.0.6 Now allows a sole query argument when profile.php is used.
1384
+ * @since 4.0.0 : 1. No longer returns a plain Facebook URL when the entry path is sanitized to become empty.
1385
+ * 2. Now returns empty when using only spaces and tabs.
1386
  *
1387
  * @param string $new_value String with potentially wrong Facebook profile URL.
1388
  * @return string String with 'correct' Facebook profile URL.
1544
  return '';
1545
  }
1546
 
1547
+ /**
1548
+ * Replaces non-transformative hyphens with entity hyphens.
1549
+ * Duplicated simple hyphens are preserved.
1550
+ *
1551
+ * Regex challenge, make the columns without an x light up:
1552
+ * xxx - xx - xxx- - - xxxxxx xxxxxx- xxxxx - -
1553
+ * --- - -- - ---- - - ------ ------- ----- - -
1554
+ *
1555
+ * The answer? `/((-{2,3})(*SKIP)-|-)(?(2)(*FAIL))/`
1556
+ * Sybre-kamisama.
1557
+ *
1558
+ * @since 4.0.5
1559
+ *
1560
+ * @param string $text String with potential hyphens.
1561
+ * @return string A string with safe HTML encoded hyphens.
1562
+ */
1563
+ public function s_hyphen( $text ) {
1564
+
1565
+ $text = preg_replace( '/((-{2,3})(*SKIP)-|-)(?(2)(*FAIL))/', '&#x2d;', $text );
1566
+
1567
+ // This is faster than putting these alternative sequences in the `-|-` regex above.
1568
+ return str_replace( [ '&#45;', "\xe2\x80\x90" ], '&#x2d;', $text );
1569
+ }
1570
+
1571
  /**
1572
  * Replaces non-break spaces with regular spaces.
1573
  *
1745
  *
1746
  * @since 3.2.4
1747
  * @since 4.0.0 Now allows emptying the indexes `space` and `clear`.
1748
+ * @since 4.0.5 1. Added the `strip` argument index to the second parameter for clearing leftover tags.
1749
+ * 2. Now also clears `iframe` tags by default.
1750
+ * 3. Now no longer (for example) accidentally takes `link` tags when only `li` tags are set for stripping.
1751
+ * 4. Now performs a separate query for void elements; to prevent regex recursion.
1752
+ * @link https://www.w3schools.com/html/html_blocks.asp
1753
+ * @link https://html.spec.whatwg.org/multipage/syntax.html#void-elements
1754
  *
1755
  * @param string $input The input text that needs its tags stripped.
1756
  * @param array $args The input arguments: {
1760
  * 'clear' : @param array|null HTML elements that should be emptied and replaced with a space.
1761
  * If not set or null, skip check.
1762
  * If empty array, skips stripping; otherwise, use input.
1763
+ * 'strip' : @param bool If set, strip_tags() is performed before returning the output.
1764
  * }
1765
+ * NOTE: WARNING The array values are forwarded to a regex without sanitization/quoting.
1766
+ * NOTE: Unlisted, script, and style tags will be stripped via PHP's `strip_tags()`. (togglable via `$args['strip']`)
1767
  * Also note that their contents are maintained as-is, without added spaces.
1768
  * It is why you should always list `style` and `script` in the `clear` array.
1769
  * @return string The output string without tags.
1774
  'space' =>
1775
  [ 'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'li', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'tfoot', 'ul' ],
1776
  'clear' =>
1777
+ [ 'bdo', 'br', 'button', 'canvas', 'code', 'hr', 'iframe', 'input', 'label', 'link', 'noscript', 'meta', 'option', 'samp', 'script', 'select', 'style', 'svg', 'textarea', 'var', 'video' ],
1778
+ 'strip' => true,
1779
  ];
1780
 
1781
+ $void = [ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' ];
1782
+
1783
  if ( ! $args ) {
1784
  $args = $default_args;
1785
  } else {
1792
  }
1793
  }
1794
  }
1795
+ $args['strip'] = isset( $args['strip'] ) ? $args['strip'] : $default_args['strip'];
1796
  }
1797
 
1798
  // Clear first, so there's less to process; then add spaces.
1799
  foreach ( [ 'clear', 'space' ] as $type ) {
1800
  if ( empty( $args[ $type ] ) ) continue;
1801
 
1802
+ // void = element without content.
1803
+ $void_query = array_intersect( $args[ $type ], $void );
1804
+ // fill = Normal, template, raw text, escapable text, foreign.
1805
+ $fill_query = array_diff( $args[ $type ], $void );
1806
+
1807
  $_replace = 'space' === $type ? ' $2 ' : ' ';
1808
 
1809
+ $_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $args[ $type ] ) );
1810
+
1811
+ if ( $void_query ) {
1812
+ $_regex = sprintf( '<(%s)\b[^>]*?>', implode( '|', $void_query ) );
1813
+ $input = preg_replace( "/$_regex/si", $_replace, $input );
1814
+ }
1815
+ if ( $fill_query ) {
1816
+ $_regex = sprintf( '<(%s)\b[^>]*?>(.*?<\/\1>)?', implode( '|', $fill_query ) );
1817
+ $input = preg_replace( "/$_regex/si", $_replace, $input );
1818
+ }
1819
  }
1820
 
1821
  // phpcs:ignore, WordPress.WP.AlternativeFunctions.strip_tags_strip_tags -- $args defines stripping of 'script' and 'style'.
1822
+ return $args['strip'] ? strip_tags( $input ) : $input;
1823
  }
1824
 
1825
  /**
1827
  *
1828
  * @since 4.0.0
1829
  * @since 4.0.2 Now finds smaller images when they're over 4K.
1830
+ * @since 4.0.5 Now faults images with filename extensions APNG, BMP, ICO, TIFF, or SVG.
1831
  * @NOTE If the input details are in an associative array, they'll be converted to sequential.
1832
  *
1833
  * @param array $details The image details, either associative (see $defaults) or sequential.
1860
 
1861
  if ( ! $url ) return $defaults;
1862
 
1863
+ /**
1864
+ * Skip APNG, BMP, ICO, TIFF, and SVG.
1865
+ *
1866
+ * @link <https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/markup>
1867
+ * @link <https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types>
1868
+ * jp(e)g, png, webp, and gif are supported. Assume all non-matches to fall in those categories,
1869
+ * since we don't perform a live MIME-test.
1870
+ *
1871
+ * Tested with Facebook; they ignore them too. There's no documentation available.
1872
+ */
1873
+ if ( in_array(
1874
+ strtolower( strtok( pathinfo( $url, PATHINFO_EXTENSION ), '?' ) ),
1875
+ [ 'apng', 'bmp', 'ico', 'cur', 'svg', 'tif', 'tiff' ],
1876
+ true
1877
+ ) ) return $defaults;
1878
+
1879
  $width = (int) $width;
1880
  $height = (int) $height;
1881
 
inc/classes/silencer.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -37,22 +37,56 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
37
  */
38
  final class Silencer {
39
 
 
 
 
 
 
 
 
 
 
 
40
  public $loaded = false;
41
 
 
 
 
42
  public function __construct() {}
43
 
 
 
 
 
 
44
  public function __get( $name ) {
45
  return null;
46
  }
47
 
 
 
 
 
 
 
48
  public function __set( $name, $value ) {
49
  return $value;
50
  }
51
 
 
 
 
 
 
52
  public function __isset( $name ) {
53
  return false;
54
  }
55
 
 
 
 
 
 
56
  public function __call( $name, $arguments ) {
57
  return null;
58
  }
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
37
  */
38
  final class Silencer {
39
 
40
+ /**
41
+ * Tells if this plugin is loaded.
42
+ *
43
+ * @NOTE: Only `\The_SEO_Framework\_init_tsf()` should adjust this.
44
+ *
45
+ * @since 3.1.0
46
+ * @access protected
47
+ * Don't alter this variable!!!
48
+ * @var boolean $loaded
49
+ */
50
  public $loaded = false;
51
 
52
+ /**
53
+ * @since 3.1.0
54
+ */
55
  public function __construct() {}
56
 
57
+ /**
58
+ * @since 3.1.0
59
+ * @param string $name The property name.
60
+ * @return null
61
+ */
62
  public function __get( $name ) {
63
  return null;
64
  }
65
 
66
+ /**
67
+ * @since 3.1.0
68
+ * @param string $name The property name.
69
+ * @param mixed $value The property value to set.
70
+ * @return mixed
71
+ */
72
  public function __set( $name, $value ) {
73
  return $value;
74
  }
75
 
76
+ /**
77
+ * @since 3.1.0
78
+ * @param string $name The property name.
79
+ * @return false
80
+ */
81
  public function __isset( $name ) {
82
  return false;
83
  }
84
 
85
+ /**
86
+ * @since 3.1.0
87
+ * @param string $name The method name.
88
+ * @param array $arguments The method arguments.
89
+ */
90
  public function __call( $name, $arguments ) {
91
  return null;
92
  }
inc/classes/site-options.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -78,7 +78,6 @@ class Site_Options extends Sanitize {
78
  'alter_archive_query_type' => 'in_query', // Archive query type.
79
  'alter_search_query_type' => 'in_query', // Search query type.
80
 
81
- 'cache_meta_schema' => 0, // Schema.org transient cache.
82
  'cache_sitemap' => 1, // Sitemap transient cache.
83
  'cache_object' => 1, // Object caching.
84
 
@@ -100,7 +99,7 @@ class Site_Options extends Sanitize {
100
  'disabled_post_types' => [], // Post Type support.
101
 
102
  // Title.
103
- 'title_separator' => 'pipe', // Title separator, dropdown
104
  'title_location' => $titleloc, // Title separation location
105
  'title_rem_additions' => 0, // Remove title additions
106
  'title_rem_prefixes' => 0, // Remove title prefixes from archives.
@@ -141,6 +140,9 @@ class Site_Options extends Sanitize {
141
 
142
  $this->get_robots_post_type_option_id( 'noarchive' ) => [], // Post Type support.
143
 
 
 
 
144
  // Robots pagination index.
145
  'paged_noindex' => 1, // Every second or later page noindex
146
  'home_paged_noindex' => 0, // Every second or later homepage noindex
@@ -192,22 +194,30 @@ class Site_Options extends Sanitize {
192
  'twitter_site' => '', // Twitter business @username
193
  'twitter_creator' => '', // Twitter user @username
194
 
 
 
 
195
  // Social on/off.
196
  'og_tags' => 1, // Output of Open Graph meta tags
197
  'facebook_tags' => 1, // Output the Facebook meta tags
198
  'twitter_tags' => 1, // Output the Twitter meta tags
 
199
 
200
  // Social image settings.
201
- 'multi_og_image' => 1,
 
 
 
202
 
203
  // Social FallBack images (fb = fallback)
204
- 'social_image_fb_url' => '', // Fallback image URL
205
- 'social_image_fb_id' => 0, // Fallback image ID
206
 
207
  // Webmasters.
208
  'google_verification' => '', // Google Verification Code
209
  'bing_verification' => '', // Bing Verification Code
210
  'yandex_verification' => '', // Yandex Verification Code
 
211
  'pint_verification' => '', // Pinterest Verification Code
212
 
213
  // Knowledge general. https://developers.google.com/structured-data/customize/contact-points - This is extremely extended and valuable. Expect a premium version.
@@ -248,12 +258,13 @@ class Site_Options extends Sanitize {
248
 
249
  'sitemap_styles' => 1, // Whether to style the sitemap
250
  'sitemap_logo' => 1, // Whether to add logo to sitemap
251
- 'sitemap_color_main' => '333', // Sitemap main color
252
- 'sitemap_color_accent' => '00cd98', // Sitemap accent color
253
 
254
  // Feed.
255
  'excerpt_the_feed' => 1, // Generate feed Excerpts
256
  'source_the_feed' => 1, // Add backlink at the end of the feed
 
257
 
258
  // Schema
259
  'ld_json_searchbox' => 1, // LD+Json Sitelinks Searchbox
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
78
  'alter_archive_query_type' => 'in_query', // Archive query type.
79
  'alter_search_query_type' => 'in_query', // Search query type.
80
 
 
81
  'cache_sitemap' => 1, // Sitemap transient cache.
82
  'cache_object' => 1, // Object caching.
83
 
99
  'disabled_post_types' => [], // Post Type support.
100
 
101
  // Title.
102
+ 'title_separator' => 'hyphen', // Title separator, dropdown
103
  'title_location' => $titleloc, // Title separation location
104
  'title_rem_additions' => 0, // Remove title additions
105
  'title_rem_prefixes' => 0, // Remove title prefixes from archives.
140
 
141
  $this->get_robots_post_type_option_id( 'noarchive' ) => [], // Post Type support.
142
 
143
+ // Robots query protection
144
+ 'advanced_query_protection' => 1,
145
+
146
  // Robots pagination index.
147
  'paged_noindex' => 1, // Every second or later page noindex
148
  'home_paged_noindex' => 0, // Every second or later homepage noindex
194
  'twitter_site' => '', // Twitter business @username
195
  'twitter_creator' => '', // Twitter user @username
196
 
197
+ // oEmbed.
198
+ 'oembed_remove_author' => 0, // Remove author from oEmbeds
199
+
200
  // Social on/off.
201
  'og_tags' => 1, // Output of Open Graph meta tags
202
  'facebook_tags' => 1, // Output the Facebook meta tags
203
  'twitter_tags' => 1, // Output the Twitter meta tags
204
+ 'oembed_scripts' => 1, // Enable WordPress's oEmbed scripts
205
 
206
  // Social image settings.
207
+ 'multi_og_image' => 1, // Allow multiple images to be generated
208
+
209
+ // Theme color settings
210
+ 'theme_color' => '', // Theme color metatag, default none
211
 
212
  // Social FallBack images (fb = fallback)
213
+ 'social_image_fb_url' => '', // Fallback image URL
214
+ 'social_image_fb_id' => 0, // Fallback image ID
215
 
216
  // Webmasters.
217
  'google_verification' => '', // Google Verification Code
218
  'bing_verification' => '', // Bing Verification Code
219
  'yandex_verification' => '', // Yandex Verification Code
220
+ 'baidu_verification' => '', // Baidu Verification Code
221
  'pint_verification' => '', // Pinterest Verification Code
222
 
223
  // Knowledge general. https://developers.google.com/structured-data/customize/contact-points - This is extremely extended and valuable. Expect a premium version.
258
 
259
  'sitemap_styles' => 1, // Whether to style the sitemap
260
  'sitemap_logo' => 1, // Whether to add logo to sitemap
261
+ 'sitemap_color_main' => '222222', // Sitemap main color
262
+ 'sitemap_color_accent' => '00a0d2', // Sitemap accent color
263
 
264
  // Feed.
265
  'excerpt_the_feed' => 1, // Generate feed Excerpts
266
  'source_the_feed' => 1, // Add backlink at the end of the feed
267
+ 'index_the_feed' => 0, // Add backlink at the end of the feed
268
 
269
  // Schema
270
  'ld_json_searchbox' => 1, // LD+Json Sitelinks Searchbox
inc/classes/term-data.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -139,7 +139,7 @@ class Term_Data extends Post_Data {
139
  static $has_deprecated_filter = null;
140
  if ( null === $has_deprecated_filter && \has_filter( 'the_seo_framework_current_term_meta' ) ) {
141
  $has_deprecated_filter = true;
142
- $this->_deprecated_filter( 'the_seo_framework_current_term_meta', '4.0.0', 'get_term_metadata' );
143
  }
144
 
145
  if ( $has_deprecated_filter && $meta ) {
@@ -166,7 +166,21 @@ class Term_Data extends Post_Data {
166
  );
167
  }
168
 
169
- return $cache[ $term_id ] = array_merge( $defaults, $meta );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
  /**
@@ -227,15 +241,15 @@ class Term_Data extends Post_Data {
227
  * Sanitizes and saves term meta data when a term is altered.
228
  *
229
  * @since 2.7.0
230
- * @since 4.0.0: 1. Renamed from `update_term_meta`
231
- * 2. noindex, nofollow, noarchive are now converted to qubits.
232
- * 3. Added new keys to sanitize.
233
- * 4. Now marked as private.
234
- * 5. Added more sanity protection.
235
- * 6. No longer runs when no `autodescription-meta` POST data is sent.
236
- * 7. Now uses the current term meta to set new values.
237
- * 8. No longer deletes meta from abstracting plugins on save when they're deactivated.
238
- * 9. Now allows updating during `WP_AJAX`.
239
  * @securitycheck 3.0.0 OK.
240
  * @access private
241
  * Use $this->save_term_meta() instead.
@@ -260,8 +274,8 @@ class Term_Data extends Post_Data {
260
  * Overwrites all of the term meta on term-edit.
261
  *
262
  * @since 4.0.0
263
- * @since 4.0.2 1: Now tests for valid term ID in the term object.
264
- * 2: Now continues using the filtered term object.
265
  *
266
  * @param int $term_id Term ID.
267
  * @param int $tt_id Term taxonomy ID.
@@ -290,8 +304,8 @@ class Term_Data extends Post_Data {
290
  * Overwrites a part of the term meta on quick-edit.
291
  *
292
  * @since 4.0.0
293
- * @since 4.0.2 1: Now tests for valid term ID in the term object.
294
- * 2: Now continues using the filtered term object.
295
  *
296
  * @param int $term_id Term ID.
297
  * @param int $tt_id Term taxonomy ID.
@@ -327,8 +341,8 @@ class Term_Data extends Post_Data {
327
  * as it reprocesses all term meta.
328
  *
329
  * @since 4.0.0
330
- * @since 4.0.2 1: Now tests for valid term ID in the term object.
331
- * 2: Now continues using the filtered term object.
332
  * @uses $this->save_term_meta() to process all data.
333
  *
334
  * @param string $item The item to update.
@@ -354,8 +368,8 @@ class Term_Data extends Post_Data {
354
  * Updates term meta from input.
355
  *
356
  * @since 4.0.0
357
- * @since 4.0.2 1: Now tests for valid term ID in the term object.
358
- * 2: Now continues using the filtered term object.
359
  *
360
  * @param int $term_id Term ID.
361
  * @param int $tt_id Term Taxonomy ID.
@@ -457,6 +471,7 @@ class Term_Data extends Post_Data {
457
  * Returns hierarchical taxonomies for post type.
458
  *
459
  * @since 3.0.0
 
460
  *
461
  * @param string $get Whether to get the names or objects.
462
  * @param string $post_type The post type. Will default to current post type.
@@ -464,8 +479,7 @@ class Term_Data extends Post_Data {
464
  */
465
  public function get_hierarchical_taxonomies_as( $get = 'objects', $post_type = '' ) {
466
 
467
- if ( ! $post_type )
468
- $post_type = \get_post_type( $this->get_the_real_ID() );
469
 
470
  if ( ! $post_type )
471
  return [];
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
139
  static $has_deprecated_filter = null;
140
  if ( null === $has_deprecated_filter && \has_filter( 'the_seo_framework_current_term_meta' ) ) {
141
  $has_deprecated_filter = true;
142
+ $this->_deprecated_filter( 'the_seo_framework_current_term_meta', '4.0.0', 'the_seo_framework_term_meta' );
143
  }
144
 
145
  if ( $has_deprecated_filter && $meta ) {
166
  );
167
  }
168
 
169
+ /**
170
+ * @since 4.0.5
171
+ * @note Do not delete/unset/add indexes! It'll cause errors.
172
+ * @param array $meta The current term meta.
173
+ * @param int $term_id The term ID.
174
+ */
175
+ $meta = \apply_filters_ref_array(
176
+ 'the_seo_framework_term_meta',
177
+ [
178
+ array_merge( $defaults, $meta ),
179
+ $term_id,
180
+ ]
181
+ );
182
+
183
+ return $cache[ $term_id ] = $meta;
184
  }
185
 
186
  /**
241
  * Sanitizes and saves term meta data when a term is altered.
242
  *
243
  * @since 2.7.0
244
+ * @since 4.0.0 : 1. Renamed from `update_term_meta`
245
+ * 2. noindex, nofollow, noarchive are now converted to qubits.
246
+ * 3. Added new keys to sanitize.
247
+ * 4. Now marked as private.
248
+ * 5. Added more sanity protection.
249
+ * 6. No longer runs when no `autodescription-meta` POST data is sent.
250
+ * 7. Now uses the current term meta to set new values.
251
+ * 8. No longer deletes meta from abstracting plugins on save when they're deactivated.
252
+ * 9. Now allows updating during `WP_AJAX`.
253
  * @securitycheck 3.0.0 OK.
254
  * @access private
255
  * Use $this->save_term_meta() instead.
274
  * Overwrites all of the term meta on term-edit.
275
  *
276
  * @since 4.0.0
277
+ * @since 4.0.2 : 1. Now tests for valid term ID in the term object.
278
+ * 2. Now continues using the filtered term object.
279
  *
280
  * @param int $term_id Term ID.
281
  * @param int $tt_id Term taxonomy ID.
304
  * Overwrites a part of the term meta on quick-edit.
305
  *
306
  * @since 4.0.0
307
+ * @since 4.0.2 : 1. Now tests for valid term ID in the term object.
308
+ * 2. Now continues using the filtered term object.
309
  *
310
  * @param int $term_id Term ID.
311
  * @param int $tt_id Term taxonomy ID.
341
  * as it reprocesses all term meta.
342
  *
343
  * @since 4.0.0
344
+ * @since 4.0.2 : 1. Now tests for valid term ID in the term object.
345
+ * 2. Now continues using the filtered term object.
346
  * @uses $this->save_term_meta() to process all data.
347
  *
348
  * @param string $item The item to update.
368
  * Updates term meta from input.
369
  *
370
  * @since 4.0.0
371
+ * @since 4.0.2 : 1. Now tests for valid term ID in the term object.
372
+ * 2. Now continues using the filtered term object.
373
  *
374
  * @param int $term_id Term ID.
375
  * @param int $tt_id Term Taxonomy ID.
471
  * Returns hierarchical taxonomies for post type.
472
  *
473
  * @since 3.0.0
474
+ * @since 4.0.5 The `$post_type` fallback now uses a real query ID, instead of `$GLOBALS['post']`.
475
  *
476
  * @param string $get Whether to get the names or objects.
477
  * @param string $post_type The post type. Will default to current post type.
479
  */
480
  public function get_hierarchical_taxonomies_as( $get = 'objects', $post_type = '' ) {
481
 
482
+ $post_type = $post_type ?: $this->get_post_type_real_ID();
 
483
 
484
  if ( ! $post_type )
485
  return [];
inc/classes/user-data.class.php CHANGED
@@ -10,7 +10,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
12
  * The SEO Framework plugin
13
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
@@ -38,6 +38,8 @@ class User_Data extends Term_Data {
38
  * Returns default user meta.
39
  *
40
  * @since 3.0.0
 
 
41
  *
42
  * @return array The default user meta index and values.
43
  */
@@ -53,8 +55,8 @@ class User_Data extends Term_Data {
53
  * Returns the current post author ID.
54
  *
55
  * @since 3.0.0
56
- * @since 3.2.2: 1. Now no longer returns the latest post author ID on home-as-blog pages.
57
- * 2. Now always returns an integer.
58
  * @staticvar $cache
59
  *
60
  * @return int Post author ID on success, 0 on failure.
@@ -99,6 +101,7 @@ class User_Data extends Term_Data {
99
  *
100
  * @since 2.7.0
101
  * @since 2.8.0 Always returns array, even if no value is assigned.
 
102
  * @staticvar array $usermeta_cache
103
  *
104
  * @param int $user_id The user ID.
10
 
11
  /**
12
  * The SEO Framework plugin
13
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
14
  *
15
  * This program is free software: you can redistribute it and/or modify
16
  * it under the terms of the GNU General Public License version 3 as published
38
  * Returns default user meta.
39
  *
40
  * @since 3.0.0
41
+ * @TODO add filter as with get_term_meta_defaults() and get_post_meta_defaults()
42
+ * (also define unfiltered values via a different function)
43
  *
44
  * @return array The default user meta index and values.
45
  */
55
  * Returns the current post author ID.
56
  *
57
  * @since 3.0.0
58
+ * @since 3.2.2 : 1. Now no longer returns the latest post author ID on home-as-blog pages.
59
+ * 2. Now always returns an integer.
60
  * @staticvar $cache
61
  *
62
  * @return int Post author ID on success, 0 on failure.
101
  *
102
  * @since 2.7.0
103
  * @since 2.8.0 Always returns array, even if no value is assigned.
104
+ * @TODO update to return default values as with `get_post_meta` and `get_term_meta`
105
  * @staticvar array $usermeta_cache
106
  *
107
  * @param int $user_id The user ID.
inc/compat/php-mbstring.php CHANGED
@@ -6,6 +6,8 @@
6
  * @ignore this file isn't loaded.
7
  */
8
 
 
 
9
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
10
 
11
  /**
6
  * @ignore this file isn't loaded.
7
  */
8
 
9
+ // phpcs:disable -- This file isn't loaded.
10
+
11
  defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
12
 
13
  /**
inc/compat/plugin-edd.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Compat\Plugin\EDD
4
+ * @subpackage The_SEO_Framework\Compatibility
5
+ */
6
+
7
+ namespace The_SEO_Framework;
8
+
9
+ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and $_this = \the_seo_framework_class() and $this instanceof $_this or die;
10
+
11
+ \add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_edd_is_product', 10, 2 );
12
+ /**
13
+ * Sets the is_product query.
14
+ *
15
+ * @since 4.0.5
16
+ * @access private
17
+ *
18
+ * @param bool $is_product Whether this is a product page.
19
+ * @param int|WP_Post|null $post Post ID or post object.
20
+ * @return bool
21
+ */
22
+ function _set_edd_is_product( $is_product, $post ) {
23
+
24
+ if ( ! $is_product ) {
25
+ if ( function_exists( 'edd_get_download' ) ) {
26
+ $post_id = $post ? \get_post( $post ) : \the_seo_framework()->get_the_real_ID();
27
+ $download = \edd_get_download( $post_id );
28
+
29
+ $is_product = ! empty( $download->ID );
30
+ }
31
+ }
32
+
33
+ return $is_product;
34
+ }
35
+
36
+ \add_filter( 'the_seo_framework_is_product_admin', __NAMESPACE__ . '\\_set_edd_is_product_admin' );
37
+ /**
38
+ * Sets the is_product_admin query.
39
+ *
40
+ * @since 4.0.5
41
+ * @access private
42
+ * @TODO is this redundant for TSF?
43
+ *
44
+ * @param bool $is_product_admin Whether this is a product admin query.
45
+ * @return bool
46
+ */
47
+ function _set_edd_is_product_admin( $is_product_admin ) {
48
+
49
+ if ( ! $is_product_admin ) {
50
+ $tsf = \the_seo_framework();
51
+ // Checks for "is_singular_admin()" because the post type is non-hierarchical.
52
+ $is_product_admin = $tsf->is_singular_admin() && 'download' === $tsf->get_admin_post_type();
53
+ }
54
+
55
+ return $is_product_admin;
56
+ }
inc/compat/plugin-polylang.php CHANGED
@@ -107,3 +107,45 @@ function _fix_sitemap_prefix( $prefix = '' ) {
107
  function _fix_home_url( $url, $id ) {
108
  return \the_seo_framework()->is_front_page_by_ID( $id ) && \get_option( 'permalink_structure' ) ? \trailingslashit( $url ) : $url;
109
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  function _fix_home_url( $url, $id ) {
108
  return \the_seo_framework()->is_front_page_by_ID( $id ) && \get_option( 'permalink_structure' ) ? \trailingslashit( $url ) : $url;
109
  }
110
+
111
+ \add_action( 'the_seo_framework_delete_cache_sitemap', __NAMESPACE__ . '\\_polylang_flush_sitemap', 10, 4 );
112
+ /**
113
+ * Deletes all sitemap transients, instead of just one.
114
+ *
115
+ * @since 4.0.5
116
+ * @global \wpdb $wpdb
117
+ * @access private
118
+ * @staticvar bool $cleared
119
+ *
120
+ * @param string $type The flush type. Comes in handy when you use a catch-all function.
121
+ * @param int $id The post, page or TT ID. Defaults to the_seo_framework()->get_the_real_ID().
122
+ * @param array $args Additional arguments. They can overwrite $type and $id.
123
+ * @param bool $success Whether the action cleared.
124
+ */
125
+ function _polylang_flush_sitemap( $type, $id, $args, $success ) {
126
+
127
+ static $cleared = false;
128
+ if ( $cleared ) return;
129
+
130
+ if ( $success ) {
131
+ global $wpdb;
132
+
133
+ $wpdb->query(
134
+ $wpdb->prepare(
135
+ "DELETE FROM $wpdb->options WHERE option_name LIKE %s",
136
+ $wpdb->esc_like( '_transient_tsf_sitemap_' ) . '%'
137
+ )
138
+ ); // No cache OK. DB call ok.
139
+
140
+ //? We didn't use a wildcard after "_transient_" to reduce scans.
141
+ //? A second query is faster on saturated sites.
142
+ $wpdb->query(
143
+ $wpdb->prepare(
144
+ "DELETE FROM $wpdb->options WHERE option_name LIKE %s",
145
+ $wpdb->esc_like( '_transient_timeout_tsf_sitemap_' ) . '%'
146
+ )
147
+ ); // No cache OK. DB call ok.
148
+
149
+ $cleared = true;
150
+ }
151
+ }
inc/compat/plugin-woocommerce.php CHANGED
@@ -41,11 +41,90 @@ function _init_wc_compat() {
41
  \add_filter( 'woocommerce_breadcrumb_main_term', [ $tsf, '_adjust_post_link_category' ], 10, 2 );
42
  }
43
 
44
- \add_filter( 'the_seo_framework_image_generation_params', __NAMESPACE__ . '\\_adjust_image_generation_params', 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  /**
46
  * Adjusts image generation parameters.
47
  *
48
- * @since 4.0.0
49
  * @access private
50
  *
51
  * @param array $params : [
@@ -58,7 +137,7 @@ function _init_wc_compat() {
58
  * Is null when query is autodetermined.
59
  * @return array $params
60
  */
61
- function _adjust_image_generation_params( $params, $args ) {
62
 
63
  $is_product = false;
64
  $is_product_category = false;
41
  \add_filter( 'woocommerce_breadcrumb_main_term', [ $tsf, '_adjust_post_link_category' ], 10, 2 );
42
  }
43
 
44
+ \add_filter( 'the_seo_framework_real_id', __NAMESPACE__ . '\\_set_real_id_wc_shop' );
45
+ /**
46
+ * Sets the correct shop ID on the shop page.
47
+ *
48
+ * @since 4.0.5
49
+ * @access private
50
+ *
51
+ * @param int $id The current ID.
52
+ * @return int
53
+ */
54
+ function _set_real_id_wc_shop( $id ) {
55
+
56
+ if ( \the_seo_framework()->is_wc_shop() ) {
57
+ $id = (int) \get_option( 'woocommerce_shop_page_id' );
58
+ }
59
+
60
+ return $id;
61
+ }
62
+
63
+ \add_filter( 'the_seo_framework_is_singular_archive', __NAMESPACE__ . '\\_set_shop_singular_archive', 10, 2 );
64
+ /**
65
+ * Sets singular archives for the WC shop page.
66
+ *
67
+ * @since 4.0.5
68
+ * @access private
69
+ *
70
+ * @param bool $is_singular_archive Whether the post ID is a singular archive.
71
+ * @param int $id The current or supplied post ID.
72
+ * @return bool
73
+ */
74
+ function _set_shop_singular_archive( $is_singular_archive, $id ) {
75
+ return $is_singular_archive || \the_seo_framework()->is_wc_shop( $id );
76
+ }
77
+
78
+ \add_filter( 'the_seo_framework_is_shop', __NAMESPACE__ . '\\_set_wc_is_shop', 10, 2 );
79
+ /**
80
+ * Sets the is_shop query.
81
+ *
82
+ * @since 4.0.5
83
+ * @access private
84
+ * @TODO is this redundant for TSF?
85
+ *
86
+ * @param bool $is_shop Whether this is a shop page.
87
+ * @param int|WP_Post|null $post Post ID or post object.
88
+ * @return bool
89
+ */
90
+ function _set_wc_is_shop( $is_shop, $post ) {
91
+ return $is_shop || \the_seo_framework()->is_wc_shop( $post );
92
+ }
93
+
94
+ \add_filter( 'the_seo_framework_is_product', __NAMESPACE__ . '\\_set_wc_is_product', 10, 2 );
95
+ /**
96
+ * Sets the is_product query.
97
+ *
98
+ * @since 4.0.5
99
+ *
100
+ * @param bool $is_product Whether this is a product page.
101
+ * @param int|WP_Post|null $post Post ID or post object.
102
+ * @return bool
103
+ */
104
+ function _set_wc_is_product( $is_product, $post ) {
105
+ return $is_product || \the_seo_framework()->is_wc_product( $post );
106
+ }
107
+
108
+ \add_filter( 'the_seo_framework_is_product_admin', __NAMESPACE__ . '\\_set_wc_is_product_admin' );
109
+ /**
110
+ * Sets the is_product_admin query.
111
+ *
112
+ * @since 4.0.5
113
+ * @access private
114
+ * @TODO is this redundant for TSF?
115
+ *
116
+ * @param bool $is_product_admin Whether this is a product admin query.
117
+ * @return bool
118
+ */
119
+ function _set_wc_is_product_admin( $is_product_admin ) {
120
+ return $is_product_admin || \the_seo_framework()->is_wc_product_admin();
121
+ }
122
+
123
+ \add_filter( 'the_seo_framework_image_generation_params', __NAMESPACE__ . '\\_adjust_wc_image_generation_params', 10, 2 );
124
  /**
125
  * Adjusts image generation parameters.
126
  *
127
+ * @since 4.0.5 (introduced @ 4.0.0, renamed to prevent conflict)
128
  * @access private
129
  *
130
  * @param array $params : [
137
  * Is null when query is autodetermined.
138
  * @return array $params
139
  */
140
+ function _adjust_wc_image_generation_params( $params, $args ) {
141
 
142
  $is_product = false;
143
  $is_product_category = false;
inc/compat/plugin-wpforo.php CHANGED
@@ -38,28 +38,42 @@ function _wpforo_fix_page() {
38
  \add_filter( 'the_seo_framework_title_from_generation', __NAMESPACE__ . '\\_wpforo_filter_pre_title', 10, 2 );
39
 
40
  if ( $override['meta'] ) {
41
- \add_filter(
42
- 'get_canonical_url',
43
- function( $canonical_url, $post ) {
44
- return function_exists( '\\wpforo_get_request_uri' ) ? \wpforo_get_request_uri() : $canonical_url;
45
- },
46
- 10,
47
- 2
48
- );
49
 
50
- //* Remove wpforo SEO meta output.
51
  \remove_action( 'wp_head', 'wpforo_add_meta_tags', 1 );
52
  } else {
53
- \add_action(
54
- 'the_seo_framework_after_init',
55
- function() {
56
- \remove_action( 'wp_head', [ \the_seo_framework(), 'html_output' ], 1 );
57
- }
58
- );
59
  }
60
  }
61
  }
62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  /**
64
  * Fixes wpForo page Titles.
65
  *
38
  \add_filter( 'the_seo_framework_title_from_generation', __NAMESPACE__ . '\\_wpforo_filter_pre_title', 10, 2 );
39
 
40
  if ( $override['meta'] ) {
41
+ \add_filter( 'get_canonical_url', __NAMESPACE__ . '\\_wpforo_filter_canonical_url', 10, 2 );
 
 
 
 
 
 
 
42
 
43
+ // Remove TSF's SEO meta output.
44
  \remove_action( 'wp_head', 'wpforo_add_meta_tags', 1 );
45
  } else {
46
+ \add_action( 'the_seo_framework_after_init', __NAMESPACE__ . '\\_wpforo_disable_html_output', 1 );
 
 
 
 
 
47
  }
48
  }
49
  }
50
 
51
+ /**
52
+ * Disables The SEO Framework's meta tag output on wpForo pages.
53
+ *
54
+ * @since 3.1.2 Introduced as Lambda.
55
+ * @since 4.0.5 Introduced as function.
56
+ * @access private
57
+ */
58
+ function _wpforo_disable_html_output() {
59
+ \remove_action( 'wp_head', [ \the_seo_framework(), 'html_output' ], 1 );
60
+ }
61
+
62
+ /**
63
+ * Filters the canonical/request URL for wpForo.
64
+ *
65
+ * @since 2.9.2 Introduced as Lambda.
66
+ * @since 4.0.5 Introduced as function.
67
+ * @access private
68
+ *
69
+ * @param string $canonical_url The post's canonical URL.
70
+ * @param \WP_Post $post Post object.
71
+ * @return string
72
+ */
73
+ function _wpforo_filter_canonical_url( $canonical_url, $post ) {
74
+ return function_exists( '\\wpforo_get_request_uri' ) ? \wpforo_get_request_uri() : $canonical_url;
75
+ }
76
+
77
  /**
78
  * Fixes wpForo page Titles.
79
  *
inc/compat/theme-genesis.php CHANGED
@@ -23,7 +23,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and $_this = \the_seo_framework_class() a
23
  function _disable_genesis_seo( $plugins ) {
24
 
25
  $plugins = [
26
- 'classes' => [
27
  '\\The_SEO_Framework\\Load',
28
  ],
29
  'functions' => [
23
  function _disable_genesis_seo( $plugins ) {
24
 
25
  $plugins = [
26
+ 'classes' => [
27
  '\\The_SEO_Framework\\Load',
28
  ],
29
  'functions' => [
inc/functions/api.php CHANGED
@@ -9,7 +9,7 @@ namespace {
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
@@ -59,9 +59,9 @@ namespace {
59
  * will fail to load views.
60
  *
61
  * @since 2.7.0
62
- * @since 2.8.0: Added did_action and current_action check.
63
  *
64
- * @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded.
65
  */
66
  function the_seo_framework_class() {
67
 
@@ -70,7 +70,8 @@ namespace {
70
  if ( isset( $class ) )
71
  return $class;
72
 
73
- if ( ! ( did_action( 'plugins_loaded' ) || current_action( 'plugins_loaded' ) ) )
 
74
  return false;
75
 
76
  return $class = get_class( the_seo_framework() );
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
59
  * will fail to load views.
60
  *
61
  * @since 2.7.0
62
+ * @since 2.8.0 Added `did_action()` check.
63
  *
64
+ * @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded (yet).
65
  */
66
  function the_seo_framework_class() {
67
 
70
  if ( isset( $class ) )
71
  return $class;
72
 
73
+ // did_action() checks for current action too.
74
+ if ( ! did_action( 'plugins_loaded' ) )
75
  return false;
76
 
77
  return $class = get_class( the_seo_framework() );
inc/functions/deprecated.php CHANGED
@@ -6,7 +6,7 @@
6
 
7
  /**
8
  * The SEO Framework plugin
9
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
10
  *
11
  * This program is free software: you can redistribute it and/or modify
12
  * it under the terms of the GNU General Public License version 3 as published
@@ -33,6 +33,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
33
  * @since 2.3.5 Emptied. (~2.5 months later)
34
  * @since 2.6.2 Emptied. (~6 months later)
35
  * @since 2.9.2 Emptied. (~8 months later)
 
36
  */
37
 
38
  /**
@@ -85,7 +86,7 @@ function the_seo_framework_dot_version( $version = '2.4' ) {
85
  $current_version = the_seo_framework_version();
86
 
87
  if ( $current_version ) {
88
- $version_len = strlen( $version );
89
  $current_version_len = strlen( $current_version );
90
 
91
  //* Only allow 3 length.
6
 
7
  /**
8
  * The SEO Framework plugin
9
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
10
  *
11
  * This program is free software: you can redistribute it and/or modify
12
  * it under the terms of the GNU General Public License version 3 as published
33
  * @since 2.3.5 Emptied. (~2.5 months later)
34
  * @since 2.6.2 Emptied. (~6 months later)
35
  * @since 2.9.2 Emptied. (~8 months later)
36
+ * @TODO 5.0.0 empty this.
37
  */
38
 
39
  /**
86
  $current_version = the_seo_framework_version();
87
 
88
  if ( $current_version ) {
89
+ $version_len = strlen( $version );
90
  $current_version_len = strlen( $current_version );
91
 
92
  //* Only allow 3 length.
inc/functions/upgrade-suggestion.php CHANGED
@@ -8,7 +8,7 @@ namespace The_SEO_Framework\Suggestion;
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2018 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2018 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
inc/index.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The desire to annoy no one, to harm no one, can equally well be the sign
4
+ * of a just as of an anxious disposition.
5
+ *
6
+ * - Friedrich Nietzsche
7
+ */
inc/traits/core/overload.trait.php CHANGED
@@ -9,7 +9,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die;
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
inc/views/admin/metaboxes/feed-metabox.php CHANGED
@@ -28,10 +28,14 @@ switch ( $instance ) :
28
  $source_the_feed_label = esc_html__( 'Add link to source below the feed entry content?', 'autodescription' );
29
  $source_the_feed_label .= ' ' . $this->make_info( __( 'This link will not be followed by search engines.', 'autodescription' ), '', false );
30
 
 
 
 
31
  $this->wrap_fields(
32
  [
33
  $this->make_checkbox( 'excerpt_the_feed', $excerpt_the_feed_label, '', false ),
34
  $this->make_checkbox( 'source_the_feed', $source_the_feed_label, '', false ),
 
35
  ],
36
  true
37
  );
28
  $source_the_feed_label = esc_html__( 'Add link to source below the feed entry content?', 'autodescription' );
29
  $source_the_feed_label .= ' ' . $this->make_info( __( 'This link will not be followed by search engines.', 'autodescription' ), '', false );
30
 
31
+ $index_the_feed_label = esc_html__( 'Allow indexing of feeds?', 'autodescription' );
32
+ $index_the_feed_label .= ' ' . $this->make_info( __( 'If this site publishes podcasts, enable this option. Otherwise, leave it disabled. Indexing feeds can cause search engines to crawl and index new pages slower; however, some podcast services require feeds to be indexable.', 'autodescription' ), '', false );
33
+
34
  $this->wrap_fields(
35
  [
36
  $this->make_checkbox( 'excerpt_the_feed', $excerpt_the_feed_label, '', false ),
37
  $this->make_checkbox( 'source_the_feed', $source_the_feed_label, '', false ),
38
+ $this->make_checkbox( 'index_the_feed', $index_the_feed_label, '', false ),
39
  ],
40
  true
41
  );
inc/views/admin/metaboxes/general-metabox.php CHANGED
@@ -244,26 +244,17 @@ switch ( $instance ) :
244
 
245
  <h4><?php esc_html_e( 'Transient Cache Settings', 'autodescription' ); ?></h4>
246
  <?php
247
- $this->description( __( 'To improve performance, generated SEO output can be stored in the database as transient cache.', 'autodescription' ) );
248
  $this->description( __( 'If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options.', 'autodescription' ) );
249
 
250
  $this->wrap_fields(
251
- [
252
- $this->make_checkbox(
253
- 'cache_meta_schema',
254
- esc_html__( 'Enable automated Schema.org output cache?', 'autodescription' )
255
- . ' ' . $this->make_info( __( 'Schema.org output generally makes multiple calls to the database.', 'autodescription' ), '', false ),
256
- '',
257
- false
258
- ),
259
- $this->make_checkbox(
260
- 'cache_sitemap',
261
- esc_html__( 'Enable sitemap generation cache?', 'autodescription' )
262
- . ' ' . $this->make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
263
- '',
264
- false
265
- ),
266
- ],
267
  true
268
  );
269
 
@@ -436,6 +427,7 @@ switch ( $instance ) :
436
  <h4><?php esc_html_e( 'Disable SEO', 'autodescription' ); ?></h4>
437
  <?php
438
  $this->description( __( 'Select post types which should not receive any SEO optimization whatsoever. This will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types.', 'autodescription' ) );
 
439
  $this->description( __( 'These settings are applied to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
440
  $this->description( __( 'Default post types can not be disabled.', 'autodescription' ) );
441
 
@@ -454,6 +446,7 @@ switch ( $instance ) :
454
 
455
  $boxes[] = $this->make_checkbox_array( [
456
  'id' => 'disabled_post_types',
 
457
  'index' => $post_type,
458
  'label' => $_label,
459
  'escape' => false,
244
 
245
  <h4><?php esc_html_e( 'Transient Cache Settings', 'autodescription' ); ?></h4>
246
  <?php
247
+ $this->description( __( 'To improve performance, generated output can be stored in the database as transient cache.', 'autodescription' ) );
248
  $this->description( __( 'If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options.', 'autodescription' ) );
249
 
250
  $this->wrap_fields(
251
+ $this->make_checkbox(
252
+ 'cache_sitemap',
253
+ esc_html__( 'Enable sitemap generation cache?', 'autodescription' )
254
+ . ' ' . $this->make_info( __( 'Generating the sitemap can use a lot of server resources.', 'autodescription' ), '', false ),
255
+ '',
256
+ false
257
+ ),
 
 
 
 
 
 
 
 
 
258
  true
259
  );
260
 
427
  <h4><?php esc_html_e( 'Disable SEO', 'autodescription' ); ?></h4>
428
  <?php
429
  $this->description( __( 'Select post types which should not receive any SEO optimization whatsoever. This will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types.', 'autodescription' ) );
430
+ $this->attention_description( __( 'Disabling SEO allows search engines to crawl the post type without restrictions or direction.', 'autodescription' ) );
431
  $this->description( __( 'These settings are applied to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect.', 'autodescription' ) );
432
  $this->description( __( 'Default post types can not be disabled.', 'autodescription' ) );
433
 
446
 
447
  $boxes[] = $this->make_checkbox_array( [
448
  'id' => 'disabled_post_types',
449
+ 'class' => 'tsf-disabled-post-types',
450
  'index' => $post_type,
451
  'label' => $_label,
452
  'escape' => false,
inc/views/admin/metaboxes/homepage-metabox.php CHANGED
@@ -418,7 +418,7 @@ switch ( $instance ) :
418
  '<a href="%s" title="%s" target=_blank class=attention>%s</a>',
419
  [
420
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) ),
421
- esc_attr__( 'Edit homepage page settings', 'autodescription' ),
422
  esc_html__( 'Overwritten by page settings', 'autodescription' ),
423
  ]
424
  )
418
  '<a href="%s" title="%s" target=_blank class=attention>%s</a>',
419
  [
420
  esc_url( admin_url( 'post.php?post=' . $home_id . '&action=edit#tsf-inpost-box' ) ),
421
+ esc_attr_x( 'Edit homepage page settings', 'Bear with me: the homepage can be edited globally, or via its page. Thus "homepage page".', 'autodescription' ),
422
  esc_html__( 'Overwritten by page settings', 'autodescription' ),
423
  ]
424
  )
inc/views/admin/metaboxes/robots-metabox.php CHANGED
@@ -35,7 +35,7 @@ switch ( $instance ) :
35
  ],
36
  'nofollow' => [
37
  'value' => 'nofollow',
38
- 'desc' => __( 'These options most likely prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your own links.', 'autodescription' ),
39
  ],
40
  'noarchive' => [
41
  'value' => 'noarchive',
@@ -84,6 +84,22 @@ switch ( $instance ) :
84
 
85
  case 'the_seo_framework_robots_metabox_general':
86
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  <h4><?php esc_html_e( 'Paginated Archive Settings', 'autodescription' ); ?></h4>
88
  <?php
89
  $this->description( __( "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ) );
@@ -188,8 +204,7 @@ switch ( $instance ) :
188
  $this->wrap_fields(
189
  vsprintf(
190
  '<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
191
- <p><select name="%3$s" id="%1$s">%4$s</select></p>
192
- <p class=description>%6$s</p>',
193
  [
194
  $this->get_field_id( 'max_image_preview' ),
195
  esc_html__( 'Maximum image preview size', 'autodescription' ),
@@ -200,15 +215,6 @@ switch ( $instance ) :
200
  '',
201
  false
202
  ),
203
- $this->convert_markdown(
204
- sprintf(
205
- /* translators: Backticks and hyperlink are Markdown! %s = link to documentation. */
206
- esc_html__( 'The "None, disallow preview" setting will not be used when `nofollow` or `noarchive` are set for a page. This is to work around unexpected deindexing behavior in Google Search. [Learn more](%s).', 'autodescription' ),
207
- 'https://kb.theseoframework.com/kb/why-is-max-image-preview-none-purged/'
208
- ),
209
- [ 'code', 'a' ],
210
- [ 'a_external' => true ]
211
- ),
212
  ]
213
  ),
214
  true
35
  ],
36
  'nofollow' => [
37
  'value' => 'nofollow',
38
+ 'desc' => __( 'These options most likely prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your internal links.', 'autodescription' ),
39
  ],
40
  'noarchive' => [
41
  'value' => 'noarchive',
84
 
85
  case 'the_seo_framework_robots_metabox_general':
86
  ?>
87
+ <h4><?php esc_html_e( 'Advanced Query Protection', 'autodescription' ); ?></h4>
88
+ <?php
89
+ $this->description( __( 'Some URL queries can cause WordPress to show faux archives. When search engines spot these, they will crawl and index them, which may cause a drop in ranking. Advanced query protection will prevent robots from indexing these archives.', 'autodescription' ) );
90
+
91
+ $this->wrap_fields(
92
+ $this->make_checkbox(
93
+ 'advanced_query_protection',
94
+ esc_html__( 'Enable advanced query protection?', 'autodescription' ),
95
+ '',
96
+ false
97
+ ),
98
+ true
99
+ );
100
+ ?>
101
+ <hr>
102
+
103
  <h4><?php esc_html_e( 'Paginated Archive Settings', 'autodescription' ); ?></h4>
104
  <?php
105
  $this->description( __( "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages.", 'autodescription' ) );
204
  $this->wrap_fields(
205
  vsprintf(
206
  '<p><label for="%1$s"><strong>%2$s</strong> %5$s</label></p>
207
+ <p><select name="%3$s" id="%1$s">%4$s</select></p>',
 
208
  [
209
  $this->get_field_id( 'max_image_preview' ),
210
  esc_html__( 'Maximum image preview size', 'autodescription' ),
215
  '',
216
  false
217
  ),
 
 
 
 
 
 
 
 
 
218
  ]
219
  ),
220
  true
inc/views/admin/metaboxes/schema-metabox.php CHANGED
@@ -188,16 +188,9 @@ switch ( $instance ) :
188
  echo $this->get_logo_uploader_form( 'knowledge_logo' );
189
  ?>
190
  </p>
191
- <hr>
192
-
193
- <h4><?php esc_html_e( 'Connected Social Pages', 'autodescription' ); ?></h4>
194
  <?php
195
- $this->description( __( "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway.", 'autodescription' ) );
196
- $this->description( __( 'Add links that lead directly to the connected social pages of this website.', 'autodescription' ) );
197
- $this->description( __( 'These settings do not affect sharing behavior with the social networks.', 'autodescription' ) );
198
 
199
  $connectedi18n = _x( 'RelatedProfile', 'No spaces. E.g. https://facebook.com/RelatedProfile', 'autodescription' );
200
-
201
  /**
202
  * @todo maybe genericons?
203
  */
@@ -241,7 +234,11 @@ switch ( $instance ) :
241
  'option' => 'knowledge_linkedin',
242
  'dashicon' => 'genericon-linkedin-alt',
243
  'desc' => __( 'LinkedIn Profile', 'autodescription' ),
244
- 'placeholder' => 'https://www.linkedin.com/in/' . $connectedi18n,
 
 
 
 
245
  'examplelink' => 'https://www.linkedin.com/profile/view',
246
  ],
247
  'pinterest' => [
@@ -267,26 +264,60 @@ switch ( $instance ) :
267
  ],
268
  ];
269
 
 
 
270
  foreach ( $socialsites as $key => $v ) {
 
 
 
 
 
 
 
271
  ?>
272
- <p>
273
- <label for="<?php $this->field_id( $v['option'] ); ?>">
274
- <strong><?php echo esc_html( $v['desc'] ); ?></strong>
275
- <?php
276
- if ( $v['examplelink'] ) {
277
- $this->make_info(
278
- __( 'View your profile.', 'autodescription' ),
279
- $v['examplelink']
280
- );
281
- }
282
- ?>
283
- </label>
284
- </p>
285
- <p>
286
- <input type="url" name="<?php $this->field_name( $v['option'] ); ?>" class="large-text" id="<?php $this->field_id( $v['option'] ); ?>" placeholder="<?php echo esc_attr( $v['placeholder'] ); ?>" value="<?php echo esc_attr( $this->get_option( $v['option'] ) ); ?>" autocomplete=off />
287
- </p>
288
  <?php
289
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  break;
291
 
292
  default:
188
  echo $this->get_logo_uploader_form( 'knowledge_logo' );
189
  ?>
190
  </p>
 
 
 
191
  <?php
 
 
 
192
 
193
  $connectedi18n = _x( 'RelatedProfile', 'No spaces. E.g. https://facebook.com/RelatedProfile', 'autodescription' );
 
194
  /**
195
  * @todo maybe genericons?
196
  */
234
  'option' => 'knowledge_linkedin',
235
  'dashicon' => 'genericon-linkedin-alt',
236
  'desc' => __( 'LinkedIn Profile', 'autodescription' ),
237
+ /**
238
+ * TODO switch to /in/ insteadof /company/ when knowledge-type is personal?
239
+ * Note that this feature is DEPRECATED. https://developers.google.com/search/docs/data-types/social-profile
240
+ */
241
+ 'placeholder' => 'https://www.linkedin.com/company/' . $connectedi18n . '/',
242
  'examplelink' => 'https://www.linkedin.com/profile/view',
243
  ],
244
  'pinterest' => [
264
  ],
265
  ];
266
 
267
+ $output_social_precense = false;
268
+
269
  foreach ( $socialsites as $key => $v ) {
270
+ if ( strlen( $this->get_option( $v['option'] ) ) ) {
271
+ $output_social_precense = true;
272
+ break;
273
+ }
274
+ }
275
+
276
+ if ( $output_social_precense ) :
277
  ?>
278
+ <hr>
279
+
280
+ <h4><?php esc_html_e( 'Connected Social Pages', 'autodescription' ); ?></h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  <?php
282
+ $this->description( __( "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway.", 'autodescription' ) );
283
+ $this->description( __( 'Add links that lead directly to the connected social pages of this website.', 'autodescription' ) );
284
+ $this->description( __( 'These settings do not affect sharing behavior with the social networks.', 'autodescription' ) );
285
+ $this->attention_description_noesc(
286
+ $this->convert_markdown(
287
+ sprintf(
288
+ /* translators: %s = Learn more URL. Markdown! */
289
+ esc_html__( 'These settings are marked for removal. When you clear a field, it will be hidden forever. [Learn more](%s).', 'autodescription' ),
290
+ 'https://developers.google.com/search/docs/data-types/social-profile'
291
+ ),
292
+ [ 'a' ],
293
+ [ 'a_internal' => false ]
294
+ )
295
+ );
296
+
297
+ foreach ( $socialsites as $key => $v ) {
298
+
299
+ if ( ! strlen( $this->get_option( $v['option'] ) ) ) continue;
300
+
301
+ ?>
302
+ <p>
303
+ <label for="<?php $this->field_id( $v['option'] ); ?>">
304
+ <strong><?php echo esc_html( $v['desc'] ); ?></strong>
305
+ <?php
306
+ if ( $v['examplelink'] ) {
307
+ $this->make_info(
308
+ __( 'View your profile.', 'autodescription' ),
309
+ $v['examplelink']
310
+ );
311
+ }
312
+ ?>
313
+ </label>
314
+ </p>
315
+ <p>
316
+ <input type="url" name="<?php $this->field_name( $v['option'] ); ?>" class="large-text" id="<?php $this->field_id( $v['option'] ); ?>" placeholder="<?php echo esc_attr( $v['placeholder'] ); ?>" value="<?php echo esc_attr( $this->get_option( $v['option'] ) ); ?>" autocomplete=off />
317
+ </p>
318
+ <?php
319
+ }
320
+ endif; /* end $output_social_precense */
321
  break;
322
 
323
  default:
inc/views/admin/metaboxes/sitemaps-metabox.php CHANGED
@@ -67,11 +67,11 @@ switch ( $instance ) :
67
  $this->description( __( 'The sitemap does not contribute to ranking, only indexing. Therefore, it is perfectly fine not having every indexable page in the sitemap.', 'autodescription' ) );
68
 
69
  if ( $has_sitemap_plugin ) :
70
- $this->attention_description( __( 'Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect.', 'autodescription' ) );
71
  echo '<hr>';
 
72
  elseif ( $sitemap_detected ) :
73
- $this->attention_description( __( 'Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect.', 'autodescription' ) );
74
  echo '<hr>';
 
75
  endif;
76
  ?>
77
  <hr>
67
  $this->description( __( 'The sitemap does not contribute to ranking, only indexing. Therefore, it is perfectly fine not having every indexable page in the sitemap.', 'autodescription' ) );
68
 
69
  if ( $has_sitemap_plugin ) :
 
70
  echo '<hr>';
71
+ $this->attention_description( __( 'Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect.', 'autodescription' ) );
72
  elseif ( $sitemap_detected ) :
 
73
  echo '<hr>';
74
+ $this->attention_description( __( 'Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect.', 'autodescription' ) );
75
  endif;
76
  ?>
77
  <hr>
inc/views/admin/metaboxes/social-metabox.php CHANGED
@@ -31,6 +31,11 @@ switch ( $instance ) :
31
  'callback' => SeoSettings::class . '::_social_metabox_twitter_tab',
32
  'dashicon' => 'twitter',
33
  ],
 
 
 
 
 
34
  'postdates' => [
35
  'name' => __( 'Post Dates', 'autodescription' ),
36
  'callback' => SeoSettings::class . '::_social_metabox_postdates_tab',
@@ -70,7 +75,6 @@ switch ( $instance ) :
70
  ),
71
  true
72
  );
73
-
74
  if ( $this->detect_og_plugin() )
75
  $this->attention_description( __( 'Note: Another Open Graph plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
76
 
@@ -95,10 +99,19 @@ switch ( $instance ) :
95
  ),
96
  true
97
  );
98
-
99
  if ( $this->detect_twitter_card_plugin() )
100
  $this->attention_description( __( 'Note: Another Twitter Card plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
101
 
 
 
 
 
 
 
 
 
 
 
102
  ?>
103
  <hr>
104
 
@@ -135,6 +148,20 @@ switch ( $instance ) :
135
  </p>
136
  <hr>
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  <h4><?php esc_html_e( 'Site Shortlink Settings', 'autodescription' ); ?></h4>
139
  <?php
140
  $this->description( __( 'The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever.', 'autodescription' ) );
@@ -161,7 +188,7 @@ switch ( $instance ) :
161
  $fb_appid_placeholder = '123456789012345';
162
 
163
  ?>
164
- <h4><?php esc_html_e( 'Default Facebook Integration Settings', 'autodescription' ); ?></h4>
165
  <?php
166
  $this->description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
167
  $this->description( __( 'When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
@@ -229,7 +256,7 @@ switch ( $instance ) :
229
  $twitter_card = $this->get_twitter_card_types();
230
 
231
  ?>
232
- <h4><?php esc_html_e( 'Default Twitter Integration Settings', 'autodescription' ); ?></h4>
233
  <?php
234
  $this->description( __( 'Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
235
 
@@ -311,6 +338,26 @@ switch ( $instance ) :
311
  <?php
312
  break;
313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  case 'the_seo_framework_social_metabox_postdates':
315
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
316
 
31
  'callback' => SeoSettings::class . '::_social_metabox_twitter_tab',
32
  'dashicon' => 'twitter',
33
  ],
34
+ 'oembed' => [
35
+ 'name' => 'oEmbed',
36
+ 'callback' => SeoSettings::class . '::_social_metabox_oembed_tab',
37
+ 'dashicon' => 'share-alt2',
38
+ ],
39
  'postdates' => [
40
  'name' => __( 'Post Dates', 'autodescription' ),
41
  'callback' => SeoSettings::class . '::_social_metabox_postdates_tab',
75
  ),
76
  true
77
  );
 
78
  if ( $this->detect_og_plugin() )
79
  $this->attention_description( __( 'Note: Another Open Graph plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
80
 
99
  ),
100
  true
101
  );
 
102
  if ( $this->detect_twitter_card_plugin() )
103
  $this->attention_description( __( 'Note: Another Twitter Card plugin has been detected. These meta tags might conflict.', 'autodescription' ) );
104
 
105
+ //* Echo oEmbed scripts checkboxes.
106
+ $this->wrap_fields(
107
+ $this->make_checkbox(
108
+ 'oembed_scripts',
109
+ __( 'Output oEmbed scripts?', 'autodescription' ),
110
+ __( 'WordPress, Discord, Drupal, Squarespace, and many other clients can make use of these scripts.', 'autodescription' ),
111
+ true
112
+ ),
113
+ true
114
+ );
115
  ?>
116
  <hr>
117
 
148
  </p>
149
  <hr>
150
 
151
+ <h4><?php esc_html_e( 'Theme Color Settings', 'autodescription' ); ?></h4>
152
+ <?php
153
+ $this->description( __( 'Discord styles embeds with the theme color. The theme color can also affect the tab-color in some browsers.', 'autodescription' ) );
154
+ ?>
155
+ <p>
156
+ <label for="<?php $this->field_id( 'theme_color' ); ?>">
157
+ <strong><?php esc_html_e( 'Theme color', 'autodescription' ); ?></strong>
158
+ </label>
159
+ </p>
160
+ <p>
161
+ <input type="text" name="<?php $this->field_name( 'theme_color' ); ?>" class="tsf-color-picker" id="<?php $this->field_id( 'theme_color' ); ?>" value="<?php echo esc_attr( $this->get_option( 'theme_color' ) ); ?>" data-tsf-default-color="" />
162
+ </p>
163
+ <hr>
164
+
165
  <h4><?php esc_html_e( 'Site Shortlink Settings', 'autodescription' ); ?></h4>
166
  <?php
167
  $this->description( __( 'The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever.', 'autodescription' ) );
188
  $fb_appid_placeholder = '123456789012345';
189
 
190
  ?>
191
+ <h4><?php esc_html_e( 'Facebook Integration Settings', 'autodescription' ); ?></h4>
192
  <?php
193
  $this->description( __( 'Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options.', 'autodescription' ) );
194
  $this->description( __( 'When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared.', 'autodescription' ) );
256
  $twitter_card = $this->get_twitter_card_types();
257
 
258
  ?>
259
+ <h4><?php esc_html_e( 'Twitter Integration Settings', 'autodescription' ); ?></h4>
260
  <?php
261
  $this->description( __( 'Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options.', 'autodescription' ) );
262
 
338
  <?php
339
  break;
340
 
341
+ case 'the_seo_framework_social_metabox_oembed':
342
+ ?>
343
+ <h4><?php esc_html_e( 'oEmbed Settings', 'autodescription' ); ?></h4>
344
+ <?php
345
+ $this->description( __( 'Some social sharing services and clients, like WordPress and Discord, obtain the linked page information via oEmbed.', 'autodescription' ) );
346
+ ?>
347
+ <hr>
348
+ <?php
349
+
350
+ $this->wrap_fields(
351
+ $this->make_checkbox(
352
+ 'oembed_remove_author',
353
+ __( 'Remove author name?', 'autodescription' ),
354
+ __( 'Discord shows the page author name above the sharing embed. Check this options if you find this undesirable.', 'autodescription' ),
355
+ true
356
+ ),
357
+ true
358
+ );
359
+
360
+ break;
361
  case 'the_seo_framework_social_metabox_postdates':
362
  $posts_i18n = esc_html__( 'Posts', 'autodescription' );
363
 
inc/views/admin/metaboxes/title-metabox.php CHANGED
@@ -168,7 +168,7 @@ switch ( $instance ) :
168
  </legend>
169
  <p id="tsf-title-separator" class="tsf-fields">
170
  <?php foreach ( $title_separator as $name => $html ) : ?>
171
- <input type="radio" name="<?php $this->field_name( 'title_separator' ); ?>" id="<?php $this->field_id( 'title_separator_' . $name ); ?>" value="<?php echo esc_attr( $name ); ?>" <?php checked( $default_title_separator, $name ); ?> />
172
  <label for="<?php $this->field_id( 'title_separator_' . $name ); ?>"><?php echo esc_html( $html ); ?></label>
173
  <?php endforeach; ?>
174
  </p>
168
  </legend>
169
  <p id="tsf-title-separator" class="tsf-fields">
170
  <?php foreach ( $title_separator as $name => $html ) : ?>
171
+ <input type="radio" name="<?php $this->field_name( 'title_separator' ); ?>" id="<?php $this->field_id( 'title_separator_' . $name ); ?>" value="<?php echo esc_attr( $name ); ?>" data-entity="<?php echo esc_attr( $html ); ?>" <?php checked( $default_title_separator, $name ); ?> />
172
  <label for="<?php $this->field_id( 'title_separator_' . $name ); ?>"><?php echo esc_html( $html ); ?></label>
173
  <?php endforeach; ?>
174
  </p>
inc/views/admin/metaboxes/webmaster-metabox.php CHANGED
@@ -20,6 +20,60 @@ switch ( $instance ) :
20
  $pint_site_url = 'https://analytics.pinterest.com/';
21
  $yandex_site_url = 'https://webmaster.yandex.com/sites/add/?hostName=' . rawurlencode( $site_url );
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  ?>
24
  <h4><?php esc_html_e( 'Webmaster Integration Settings', 'autodescription' ); ?></h4>
25
  <?php
@@ -28,67 +82,27 @@ switch ( $instance ) :
28
 
29
  ?>
30
  <hr>
31
-
32
- <p>
33
- <label for="<?php $this->field_id( 'google_verification' ); ?>">
34
- <strong><?php esc_html_e( 'Google Search Console Verification Code', 'autodescription' ); ?></strong>
35
- </label>
36
- <?php
37
- $this->make_info(
38
- __( 'Get the Google verification code.', 'autodescription' ),
39
- $google_site_url
40
- );
41
- ?>
42
- </p>
43
- <p>
44
- <input type="text" name="<?php $this->field_name( 'google_verification' ); ?>" class="large-text ltr" id="<?php $this->field_id( 'google_verification' ); ?>" placeholder="ABC1d2eFg34H5iJ6klmNOp7qRstUvWXyZaBc8dEfG9" value="<?php echo esc_attr( $this->get_option( 'google_verification' ) ); ?>" />
45
- </p>
46
-
47
- <p>
48
- <label for="<?php $this->field_id( 'bing_verification' ); ?>">
49
- <strong><?php esc_html_e( 'Bing Webmaster Verification Code', 'autodescription' ); ?></strong>
50
- </label>
51
- <?php
52
- $this->make_info(
53
- __( 'Get the Bing verification code.', 'autodescription' ),
54
- $bing_site_url
55
- );
56
- ?>
57
- </p>
58
- <p>
59
- <input type="text" name="<?php $this->field_name( 'bing_verification' ); ?>" class="large-text ltr" id="<?php $this->field_id( 'bing_verification' ); ?>" placeholder="123A456B78901C2D3456E7890F1A234D" value="<?php echo esc_attr( $this->get_option( 'bing_verification' ) ); ?>" />
60
- </p>
61
-
62
- <p>
63
- <label for="<?php $this->field_id( 'yandex_verification' ); ?>">
64
- <strong><?php esc_html_e( 'Yandex Webmaster Verification Code', 'autodescription' ); ?></strong>
65
- </label>
66
- <?php
67
- $this->make_info(
68
- __( 'Get the Yandex verification code.', 'autodescription' ),
69
- $yandex_site_url
70
  );
71
- ?>
72
- </p>
73
- <p>
74
- <input type="text" name="<?php $this->field_name( 'yandex_verification' ); ?>" class="large-text ltr" id="<?php $this->field_id( 'yandex_verification' ); ?>" placeholder="12345abc678901d2" value="<?php echo esc_attr( $this->get_option( 'yandex_verification' ) ); ?>" />
75
- </p>
76
-
77
- <p>
78
- <label for="<?php $this->field_id( 'pint_verification' ); ?>">
79
- <strong><?php esc_html_e( 'Pinterest Analytics Verification Code', 'autodescription' ); ?></strong>
80
- </label>
81
- <?php
82
- $this->make_info(
83
- __( 'Get the Pinterest verification code.', 'autodescription' ),
84
- $pint_site_url
85
  );
86
- ?>
87
- </p>
88
- <p>
89
- <input type="text" name="<?php $this->field_name( 'pint_verification' ); ?>" class="large-text ltr" id="<?php $this->field_id( 'pint_verification' ); ?>" placeholder="123456a7b8901de2fa34bcdef5a67b98" value="<?php echo esc_attr( $this->get_option( 'pint_verification' ) ); ?>" />
90
- </p>
91
- <?php
92
  break;
93
 
94
  default:
20
  $pint_site_url = 'https://analytics.pinterest.com/';
21
  $yandex_site_url = 'https://webmaster.yandex.com/sites/add/?hostName=' . rawurlencode( $site_url );
22
 
23
+ $settings = [
24
+ 'google' => [
25
+ 'setting' => 'google_verification',
26
+ 'label' => __( 'Google Search Console Verification Code', 'autodescription' ),
27
+ 'info' => $this->make_info(
28
+ __( 'Get the Google verification code.', 'autodescription' ),
29
+ 'https://www.google.com/webmasters/verification/verification?siteUrl=' . rawurlencode( $site_url ) . '&tid=alternate&vtype=vmeta',
30
+ false
31
+ ),
32
+ 'placeholder' => '123A456B78901C2D3456E7890F1A234D',
33
+ ],
34
+ 'bing' => [
35
+ 'setting' => 'bing_verification',
36
+ 'label' => __( 'Bing Webmaster Verification Code', 'autodescription' ),
37
+ 'info' => $this->make_info(
38
+ __( 'Get the Bing verification code.', 'autodescription' ),
39
+ 'https://www.bing.com/webmaster/home/addsite?addurl=' . rawurlencode( $site_url ),
40
+ false
41
+ ),
42
+ 'placeholder' => '123A456B78901C2D3456E7890F1A234D',
43
+ ],
44
+ 'yandex' => [
45
+ 'setting' => 'yandex_verification',
46
+ 'label' => __( 'Yandex Webmaster Verification Code', 'autodescription' ),
47
+ 'info' => $this->make_info(
48
+ __( 'Get the Yandex verification code.', 'autodescription' ),
49
+ 'https://webmaster.yandex.com/sites/add/?hostName=' . rawurlencode( $site_url ),
50
+ false
51
+ ),
52
+ 'placeholder' => '12345abc678901d2',
53
+ ],
54
+ 'baidu' => [
55
+ 'setting' => 'baidu_verification',
56
+ /* translators: literal translation from '百度搜索资源平台'-Code */
57
+ 'label' => __( 'Baidu Search Resource Platform Code', 'autodescription' ),
58
+ 'info' => $this->make_info(
59
+ __( 'Get the Baidu verification code.', 'autodescription' ),
60
+ 'https://ziyuan.baidu.com/login/index?u=/site/siteadd',
61
+ false
62
+ ),
63
+ 'placeholder' => 'a12bcDEFGa',
64
+ ],
65
+ 'pinterest' => [
66
+ 'setting' => 'pint_verification',
67
+ 'label' => __( 'Pinterest Analytics Verification Code', 'autodescription' ),
68
+ 'info' => $this->make_info(
69
+ __( 'Get the Pinterest verification code.', 'autodescription' ),
70
+ 'https://analytics.pinterest.com/',
71
+ false
72
+ ),
73
+ 'placeholder' => '123456a7b8901de2fa34bcdef5a67b90',
74
+ ],
75
+ ];
76
+
77
  ?>
78
  <h4><?php esc_html_e( 'Webmaster Integration Settings', 'autodescription' ); ?></h4>
79
  <?php
82
 
83
  ?>
84
  <hr>
85
+ <?php
86
+ foreach ( $settings as $key => $setting ) :
87
+ vprintf(
88
+ '<p><label for=%s><strong>%s</strong> %s</p>',
89
+ [
90
+ esc_attr( $this->get_field_id( $setting['setting'] ) ),
91
+ esc_html( $setting['label'] ),
92
+ // phpcs:ignore, WordPress.Security.EscapeOutput.OutputNotEscaped -- should be escaped in list.
93
+ $setting['info'],
94
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  );
96
+ vprintf(
97
+ '<p><input type=text name=%s class="large-text ltr" id=%s placeholder="%s" value="%s" /></p>',
98
+ [
99
+ esc_attr( $this->get_field_name( $setting['setting'] ) ),
100
+ esc_attr( $this->get_field_id( $setting['setting'] ) ),
101
+ esc_attr( $setting['placeholder'] ),
102
+ esc_attr( $this->get_option( $setting['setting'] ) ),
103
+ ]
 
 
 
 
 
 
104
  );
105
+ endforeach;
 
 
 
 
 
106
  break;
107
 
108
  default:
inc/views/debug/output.php CHANGED
@@ -18,10 +18,10 @@ if ( ! $this->is_archive() && $this->is_real_front_page() || $this->is_front_pag
18
  } elseif ( $taxonomy ) {
19
  $type = $this->get_tax_type_label( $taxonomy );
20
  } else {
21
- $type = $this->get_post_type_label( get_post_type() );
22
  }
23
 
24
- $cache_key = $this->generate_cache_key( $this->get_the_real_ID(), $taxonomy );
25
 
26
  if ( is_admin() ) {
27
  $bstyle = \is_rtl()
18
  } elseif ( $taxonomy ) {
19
  $type = $this->get_tax_type_label( $taxonomy );
20
  } else {
21
+ $type = $this->get_post_type_label( $this->get_post_type_real_ID() );
22
  }
23
 
24
+ $cache_key = $this->generate_cache_key( $id, $taxonomy );
25
 
26
  if ( is_admin() ) {
27
  $bstyle = \is_rtl()
inc/views/edit/seo-settings-singular.php CHANGED
@@ -14,7 +14,7 @@ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and $_this = the_seo_framework_class() an
14
  $instance = $this->get_view_instance( 'inpost', $instance );
15
 
16
  //* Setup default vars.
17
- $post_id = $this->get_the_real_ID(); // We also have access to object $post at the main call...
18
 
19
  $_generator_args = [
20
  'id' => $post_id,
@@ -133,14 +133,14 @@ switch ( $instance ) :
133
  <?php
134
  esc_html_e( 'Remove the blog name?', 'autodescription' );
135
  echo ' ';
136
- $this->make_info( sprintf( __( 'For the homepage, this option must be managed at the SEO Settings.', 'autodescription' ) ) );
137
  else :
138
  ?>
139
  <input type="checkbox" name="autodescription[_tsf_title_no_blogname]" id="autodescription_title_no_blogname" value="1" <?php checked( $this->get_post_meta_item( '_tsf_title_no_blogname' ) ); ?> />
140
  <?php
141
  esc_html_e( 'Remove the blog name?', 'autodescription' );
142
  echo ' ';
143
- $this->make_info( sprintf( __( 'Use this when you want to rearrange the title parts manually.', 'autodescription' ) ) );
144
  endif;
145
  ?>
146
  </label>
14
  $instance = $this->get_view_instance( 'inpost', $instance );
15
 
16
  //* Setup default vars.
17
+ $post_id = $this->get_the_real_ID(); // We also have access to object $post at the main call...
18
 
19
  $_generator_args = [
20
  'id' => $post_id,
133
  <?php
134
  esc_html_e( 'Remove the blog name?', 'autodescription' );
135
  echo ' ';
136
+ $this->make_info( __( 'This option must be managed on the SEO Settings page for the homepage.', 'autodescription' ) );
137
  else :
138
  ?>
139
  <input type="checkbox" name="autodescription[_tsf_title_no_blogname]" id="autodescription_title_no_blogname" value="1" <?php checked( $this->get_post_meta_item( '_tsf_title_no_blogname' ) ); ?> />
140
  <?php
141
  esc_html_e( 'Remove the blog name?', 'autodescription' );
142
  echo ' ';
143
+ $this->make_info( __( 'Use this when you want to rearrange the title parts manually.', 'autodescription' ) );
144
  endif;
145
  ?>
146
  </label>
inc/views/edit/seo-settings-tt.php CHANGED
@@ -139,7 +139,7 @@ $robots_settings = [
139
  <?php
140
  esc_html_e( 'Remove the blog name?', 'autodescription' );
141
  echo ' ';
142
- $this->make_info( sprintf( __( 'Use this when you want to rearrange the title parts manually.', 'autodescription' ) ) );
143
  ?>
144
  </label>
145
  </td>
139
  <?php
140
  esc_html_e( 'Remove the blog name?', 'autodescription' );
141
  echo ' ';
142
+ $this->make_info( __( 'Use this when you want to rearrange the title parts manually.', 'autodescription' ) );
143
  ?>
144
  </label>
145
  </td>
inc/views/list/bulk-post.php CHANGED
@@ -36,6 +36,20 @@ $robots_settings = [
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  <fieldset class=inline-edit-col-left>
40
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
41
  <div class=inline-edit-col>
@@ -64,4 +78,18 @@ $robots_settings = [
64
  </div>
65
  </div>
66
  </fieldset>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  </div>
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
39
+ <?php
40
+ /**
41
+ * @since 4.0.5
42
+ * @param string $post_type The current post type.
43
+ * @param string $taxonomy The current taxonomy type (if any).
44
+ */
45
+ \do_action_ref_array(
46
+ 'the_seo_framework_before_bulk_edit',
47
+ [
48
+ $post_type,
49
+ $taxonomy,
50
+ ]
51
+ );
52
+ ?>
53
  <fieldset class=inline-edit-col-left>
54
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
55
  <div class=inline-edit-col>
78
  </div>
79
  </div>
80
  </fieldset>
81
+ <?php
82
+ /**
83
+ * @since 4.0.5
84
+ * @param string $post_type The current post type.
85
+ * @param string $taxonomy The current taxonomy type (if any).
86
+ */
87
+ \do_action_ref_array(
88
+ 'the_seo_framework_after_bulk_edit',
89
+ [
90
+ $post_type,
91
+ $taxonomy,
92
+ ]
93
+ );
94
+ ?>
95
  </div>
inc/views/list/quick-post.php CHANGED
@@ -36,6 +36,20 @@ $robots_settings = [
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  <fieldset class=inline-edit-col-left>
40
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
41
  <div class=inline-edit-col>
@@ -78,4 +92,18 @@ $robots_settings = [
78
  </div>
79
  </div>
80
  </fieldset>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </div>
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
39
+ <?php
40
+ /**
41
+ * @since 4.0.5
42
+ * @param string $post_type The post type slug, or current screen name if this is a taxonomy list table.
43
+ * @param string $taxonomy The current taxonomy type (if any).
44
+ */
45
+ \do_action_ref_array(
46
+ 'the_seo_framework_before_quick_edit',
47
+ [
48
+ $post_type,
49
+ $taxonomy,
50
+ ]
51
+ );
52
+ ?>
53
  <fieldset class=inline-edit-col-left>
54
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
55
  <div class=inline-edit-col>
92
  </div>
93
  </div>
94
  </fieldset>
95
+ <?php
96
+ /**
97
+ * @since 4.0.5
98
+ * @param string $post_type The post type slug, or current screen name if this is a taxonomy list table.
99
+ * @param string $post_type The current taxonomy type (if any).
100
+ */
101
+ \do_action_ref_array(
102
+ 'the_seo_framework_after_quick_edit',
103
+ [
104
+ $post_type,
105
+ $taxonomy,
106
+ ]
107
+ );
108
+ ?>
109
  </div>
inc/views/list/quick-term.php CHANGED
@@ -36,6 +36,20 @@ $robots_settings = [
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  <fieldset class=inline-edit-col-full>
40
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
41
  <div class=inline-edit-col>
@@ -78,4 +92,18 @@ $robots_settings = [
78
  </div>
79
  </div>
80
  </fieldset>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </div>
36
 
37
  ?>
38
  <div class=tsf-quick-edit-columns>
39
+ <?php
40
+ /**
41
+ * @since 4.0.5
42
+ * @param string $post_type The post type slug, or current screen name if this is a taxonomy list table.
43
+ * @param string $taxonomy The current taxonomy type (if any).
44
+ */
45
+ \do_action_ref_array(
46
+ 'the_seo_framework_before_quick_edit',
47
+ [
48
+ $post_type,
49
+ $taxonomy,
50
+ ]
51
+ );
52
+ ?>
53
  <fieldset class=inline-edit-col-full>
54
  <legend class=inline-edit-legend><?php esc_html_e( 'Visibility SEO Settings', 'autodescription' ); ?></legend>
55
  <div class=inline-edit-col>
92
  </div>
93
  </div>
94
  </fieldset>
95
+ <?php
96
+ /**
97
+ * @since 4.0.5
98
+ * @param string $post_type The post type slug, or current screen name if this is a taxonomy list table.
99
+ * @param string $taxonomy The current taxonomy type (if any).
100
+ */
101
+ \do_action_ref_array(
102
+ 'the_seo_framework_after_quick_edit',
103
+ [
104
+ $post_type,
105
+ $taxonomy,
106
+ ]
107
+ );
108
+ ?>
109
  </div>
inc/views/templates/settings/index.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The best way to find yourself is to lose yourself in the service of others.
4
+ *
5
+ * - Mahātmā Mohandas Karamchand Gandhi
6
+ */
inc/views/templates/settings/settings.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package The_SEO_Framework\Templates\Settings
4
+ * @subpackage The_SEO_Framework\Admin\Settings
5
+ */
6
+
7
+ defined( 'THE_SEO_FRAMEWORK_PRESENT' ) and The_SEO_Framework\Builders\Scripts::verify( $_secret ) or die;
8
+
9
+ ?>
10
+ <script type="text/html" id="tmpl-tsf-disabled-post-type-help">
11
+ <span class="tsf-post-type-warning">
12
+ <?php
13
+ the_seo_framework()->make_info(
14
+ \esc_html__( "This post type is disabled, so this option won't work.", 'autodescription' )
15
+ );
16
+ ?>
17
+ </span>
18
+ </script>
19
+ <?php
language/autodescription.pot CHANGED
@@ -1,46 +1,46 @@
1
- # Copyright (C) 2019 The SEO Framework
2
  # This file is distributed under the same license as the The SEO Framework package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: The SEO Framework 4.0.3\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
- "POT-Creation-Date: 2019-11-11 17:46:56+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2019-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
  #. translators: %s = Version number, surrounded in markdown-backticks.
16
 
17
- #: bootstrap/upgrade.php:250
18
  msgid "Thank you for updating The SEO Framework! Your website has been upgraded successfully to use The SEO Framework at database version `%s`."
19
  msgstr ""
20
 
21
- #: bootstrap/upgrade.php:261
22
- msgid "Thank you for installing The SEO Framework! Your website is now optimized for SEO, automatically. We hope you enjoy our free plugin. Good luck with your site!"
23
  msgstr ""
24
 
25
  #. translators: %s = Link, markdown.
26
 
27
- #: bootstrap/upgrade.php:270
28
  msgid "The SEO Framework only identifies itself rarely during plugin upgrades. We'd like to use this opportunity to highlight our [plugin setup guide](%s)."
29
  msgstr ""
30
 
31
- #: bootstrap/upgrade.php:416
32
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
33
  msgstr ""
34
 
35
- #: bootstrap/upgrade.php:446
36
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
37
  msgstr ""
38
 
39
- #: bootstrap/upgrade.php:568
40
  msgid "A cronjob is now used to ping search engines, and it alerts them to changes in your sitemap."
41
  msgstr ""
42
 
43
- #: bootstrap/upgrade.php:583
44
  msgid "The positions in the \"Meta Title Additions Location\" setting for the homepage have been reversed, left to right, but the output has not been changed. If you must downgrade for some reason, remember to switch the location back again."
45
  msgstr ""
46
 
@@ -132,7 +132,7 @@ msgstr ""
132
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
133
  msgstr ""
134
 
135
- #: inc/classes/admin-init.class.php:638 inc/classes/admin-init.class.php:699
136
  msgid "Image could not be processed."
137
  msgstr ""
138
 
@@ -144,68 +144,68 @@ msgstr ""
144
  msgid "SEO"
145
  msgstr ""
146
 
147
- #: inc/classes/admin-pages.class.php:199
148
  msgid "SEO settings are saved, and the caches have been flushed."
149
  msgstr ""
150
 
151
- #: inc/classes/admin-pages.class.php:204
152
  msgid "No SEO settings were changed, but the caches have been flushed."
153
  msgstr ""
154
 
155
- #: inc/classes/admin-pages.class.php:209
156
  msgid "SEO settings are reset, and the caches have been flushed."
157
  msgstr ""
158
 
159
- #: inc/classes/admin-pages.class.php:214
160
  msgid "An unknown error occurred saving SEO settings."
161
  msgstr ""
162
 
163
- #: inc/classes/admin-pages.class.php:237
164
  msgid "Multiple SEO tools have been detected. You should only use one."
165
  msgstr ""
166
 
167
- #: inc/classes/admin-pages.class.php:390
168
  msgid "Dismiss this notice"
169
  msgstr ""
170
 
171
- #: inc/classes/admin-pages.class.php:1041
172
- #: inc/classes/bridges/scripts.class.php:621
173
  msgctxt "Button hover"
174
  msgid "Select social image"
175
  msgstr ""
176
 
177
- #: inc/classes/admin-pages.class.php:1052
178
- #: inc/classes/bridges/scripts.class.php:620
179
  msgid "Select Image"
180
  msgstr ""
181
 
182
- #: inc/classes/admin-pages.class.php:1098
183
- #: inc/classes/bridges/scripts.class.php:629
184
  msgid "Select Logo"
185
  msgstr ""
186
 
187
- #: inc/classes/admin-pages.class.php:1148
188
  msgid "Click to change the counter type"
189
  msgstr ""
190
 
191
  #. translators: %s = number
192
 
193
- #: inc/classes/admin-pages.class.php:1151
194
  msgid "Characters Used: %s"
195
  msgstr ""
196
 
197
- #: inc/classes/bridges/postsettings.class.php:72
198
- #: inc/classes/bridges/postsettings.class.php:80
199
  msgid "Homepage SEO Settings"
200
  msgstr ""
201
 
202
- #: inc/classes/bridges/postsettings.class.php:74
203
  msgid "The SEO Settings may take precedence over these settings."
204
  msgstr ""
205
 
206
  #. translators: %s = Post Type label
207
 
208
- #: inc/classes/bridges/postsettings.class.php:84
209
  msgid "%s SEO Settings"
210
  msgstr ""
211
 
@@ -218,14 +218,14 @@ msgid "Are you sure you want to reset all SEO settings to their defaults?"
218
  msgstr ""
219
 
220
  #: inc/classes/bridges/scripts.class.php:418
221
- #: inc/classes/bridges/scripts.class.php:484
222
- #: inc/classes/generate-title.class.php:1173
223
  msgid "Private: %s"
224
  msgstr ""
225
 
226
  #: inc/classes/bridges/scripts.class.php:420
227
- #: inc/classes/bridges/scripts.class.php:486
228
- #: inc/classes/generate-title.class.php:1158
229
  msgid "Protected: %s"
230
  msgstr ""
231
 
@@ -233,73 +233,73 @@ msgstr ""
233
  #. Current taxonomy term
234
  #. translators: 1 = 'Assessment(s)', 2 = A list of assessments.
235
 
236
- #: inc/classes/bridges/scripts.class.php:538
237
- #: inc/classes/generate-title.class.php:767
238
- #: inc/classes/generate-title.class.php:830
239
  #: inc/classes/interpreters/seobar.class.php:342
240
  msgid "%1$s: %2$s"
241
  msgstr ""
242
 
243
- #: inc/classes/bridges/scripts.class.php:622
244
  msgid "Change Image"
245
  msgstr ""
246
 
247
- #: inc/classes/bridges/scripts.class.php:623
248
  msgid "Remove Image"
249
  msgstr ""
250
 
251
- #: inc/classes/bridges/scripts.class.php:624
252
  msgid "Remove selected social image"
253
  msgstr ""
254
 
255
- #: inc/classes/bridges/scripts.class.php:625
256
  msgctxt "Frame title"
257
  msgid "Select Social Image"
258
  msgstr ""
259
 
260
- #: inc/classes/bridges/scripts.class.php:626
261
- #: inc/classes/bridges/scripts.class.php:635
262
  msgid "Use this image"
263
  msgstr ""
264
 
265
- #: inc/classes/bridges/scripts.class.php:631
266
  msgid "Change Logo"
267
  msgstr ""
268
 
269
- #: inc/classes/bridges/scripts.class.php:632
270
  msgid "Remove Logo"
271
  msgstr ""
272
 
273
- #: inc/classes/bridges/scripts.class.php:633
274
  msgid "Unset selected logo"
275
  msgstr ""
276
 
277
- #: inc/classes/bridges/scripts.class.php:634
278
  msgctxt "Frame title"
279
  msgid "Select Logo"
280
  msgstr ""
281
 
282
  #. translators: %s = term name
283
 
284
- #: inc/classes/bridges/scripts.class.php:894
285
  msgid "Select Primary %s"
286
  msgstr ""
287
 
288
  #. translators: %s = term name
289
 
290
- #: inc/classes/bridges/scripts.class.php:899
291
  msgid "Make primary %s"
292
  msgstr ""
293
 
294
  #. translators: %s = term name
295
 
296
- #: inc/classes/bridges/scripts.class.php:901
297
  msgid "Primary %s"
298
  msgstr ""
299
 
300
  #. translators: Pixel counter. 1: number (value), 2: number (guideline)
301
 
302
- #: inc/classes/bridges/scripts.class.php:996
303
  msgid "%1$d out of %2$d pixels are used."
304
  msgstr ""
305
 
@@ -349,292 +349,308 @@ msgstr ""
349
  #. translators: 1 = An assessment, 2 = Disclaimer, e.g. "take it with a grain
350
  #. of salt"
351
 
352
- #: inc/classes/builders/seobar-page.class.php:146
353
- #: inc/classes/builders/seobar-page.class.php:343
354
- #: inc/classes/builders/seobar-term.class.php:160
355
- #: inc/classes/builders/seobar-term.class.php:334
356
  msgid "%1$s (%2$s)"
357
  msgstr ""
358
 
359
- #: inc/classes/builders/seobar-page.class.php:147
360
- #: inc/classes/builders/seobar-page.class.php:344
361
- #: inc/classes/builders/seobar-term.class.php:161
362
- #: inc/classes/builders/seobar-term.class.php:335
363
  msgid "Estimated from the number of characters found. The pixel counter asserts the true length."
364
  msgstr ""
365
 
366
- #: inc/classes/builders/seobar-page.class.php:150
367
- #: inc/classes/builders/seobar-term.class.php:164
368
  msgid "No title could be fetched."
369
  msgstr ""
370
 
371
- #: inc/classes/builders/seobar-page.class.php:151
372
- #: inc/classes/builders/seobar-term.class.php:165
373
- msgid "No title could be fetched, \"Untitled\" is used instead."
 
 
374
  msgstr ""
375
 
376
- #: inc/classes/builders/seobar-page.class.php:152
377
  msgid "A page protection state is added which increases the length."
378
  msgstr ""
379
 
380
- #: inc/classes/builders/seobar-page.class.php:154
381
- #: inc/classes/builders/seobar-term.class.php:168
382
  msgid "It's not branded. Search engines may ignore your title."
383
  msgstr ""
384
 
385
- #: inc/classes/builders/seobar-page.class.php:155
386
- #: inc/classes/builders/seobar-term.class.php:169
387
  msgid "It's manually branded."
388
  msgstr ""
389
 
390
- #: inc/classes/builders/seobar-page.class.php:156
391
- #: inc/classes/builders/seobar-term.class.php:170
392
  msgid "It's automatically branded."
393
  msgstr ""
394
 
395
- #: inc/classes/builders/seobar-page.class.php:158
396
- #: inc/classes/builders/seobar-term.class.php:172
397
  msgid "The blog name is found multiple times."
398
  msgstr ""
399
 
400
- #: inc/classes/builders/seobar-page.class.php:161
401
- #: inc/classes/builders/seobar-term.class.php:175
 
 
 
 
 
 
 
402
  msgid "Incomplete."
403
  msgstr ""
404
 
405
- #: inc/classes/builders/seobar-page.class.php:162
406
- #: inc/classes/builders/seobar-term.class.php:176
407
  msgid "The branding is duplicated."
408
  msgstr ""
409
 
410
- #: inc/classes/builders/seobar-page.class.php:163
411
- #: inc/classes/builders/seobar-term.class.php:177
412
  msgid "Not branded."
413
  msgstr ""
414
 
415
- #: inc/classes/builders/seobar-page.class.php:167
416
- #: inc/classes/builders/seobar-term.class.php:181
 
 
 
 
 
 
 
417
  msgctxt "Title Generated"
418
  msgid "TG"
419
  msgstr ""
420
 
421
- #: inc/classes/builders/seobar-page.class.php:168
422
- #: inc/classes/builders/seobar-term.class.php:182
423
  msgid "Title, generated"
424
  msgstr ""
425
 
426
- #: inc/classes/builders/seobar-page.class.php:170
427
- #: inc/classes/builders/seobar-page.class.php:369
428
- #: inc/classes/builders/seobar-term.class.php:184
429
- #: inc/classes/builders/seobar-term.class.php:357
430
  msgid "Automatically generated."
431
  msgstr ""
432
 
433
- #: inc/classes/builders/seobar-page.class.php:172
434
- #: inc/classes/builders/seobar-term.class.php:186
435
  msgid "It's built using the page title."
436
  msgstr ""
437
 
438
- #: inc/classes/builders/seobar-page.class.php:176
439
- #: inc/classes/builders/seobar-term.class.php:190
440
  msgctxt "Title"
441
  msgid "T"
442
  msgstr ""
443
 
444
- #: inc/classes/builders/seobar-page.class.php:177
445
- #: inc/classes/builders/seobar-term.class.php:191
446
  msgid "Title"
447
  msgstr ""
448
 
449
- #: inc/classes/builders/seobar-page.class.php:179
450
- #: inc/classes/builders/seobar-page.class.php:387
451
  msgid "Obtained from page SEO meta input."
452
  msgstr ""
453
 
454
- #: inc/classes/builders/seobar-page.class.php:181
455
- #: inc/classes/builders/seobar-page.class.php:389
456
  msgid "It's built from page SEO meta input."
457
  msgstr ""
458
 
459
- #: inc/classes/builders/seobar-page.class.php:202
460
  msgid "The title inputted at the SEO Settings screen is used."
461
  msgstr ""
462
 
463
- #: inc/classes/builders/seobar-page.class.php:204
464
  msgid "The title inputted at the Edit Page screen is used."
465
  msgstr ""
466
 
467
- #: inc/classes/builders/seobar-page.class.php:212
468
  msgid "The title is built from the blog name."
469
  msgstr ""
470
 
471
- #: inc/classes/builders/seobar-page.class.php:352
472
  msgid "There is no usable content, so no description could be generated."
473
  msgstr ""
474
 
475
- #: inc/classes/builders/seobar-page.class.php:353
476
  msgid "A foreign page builder is used, so no description is generated."
477
  msgstr ""
478
 
479
- #: inc/classes/builders/seobar-page.class.php:354
480
  msgid "The page is protected, so no description is generated."
481
  msgstr ""
482
 
483
- #: inc/classes/builders/seobar-page.class.php:355
484
  msgid "It's built using the excerpt field."
485
  msgstr ""
486
 
487
  #. translators: %s = list of duplicated words
488
 
489
- #: inc/classes/builders/seobar-page.class.php:357
490
- #: inc/classes/builders/seobar-term.class.php:345
491
  msgid "Found duplicated words: %s"
492
  msgstr ""
493
 
494
- #: inc/classes/builders/seobar-page.class.php:360
495
- #: inc/classes/builders/seobar-page.class.php:378
496
- #: inc/classes/builders/seobar-term.class.php:348
497
- #: inc/classes/builders/seobar-term.class.php:366
498
  msgid "Empty."
499
  msgstr ""
500
 
501
- #: inc/classes/builders/seobar-page.class.php:361
502
- #: inc/classes/builders/seobar-term.class.php:349
503
  msgid "Found duplicated words."
504
  msgstr ""
505
 
506
- #: inc/classes/builders/seobar-page.class.php:362
507
- #: inc/classes/builders/seobar-term.class.php:350
508
  msgid "Found too many duplicated words."
509
  msgstr ""
510
 
511
- #: inc/classes/builders/seobar-page.class.php:366
512
- #: inc/classes/builders/seobar-term.class.php:354
513
  msgctxt "Description Generated"
514
  msgid "DG"
515
  msgstr ""
516
 
517
- #: inc/classes/builders/seobar-page.class.php:367
518
- #: inc/classes/builders/seobar-term.class.php:355
519
  msgid "Description, generated"
520
  msgstr ""
521
 
522
- #: inc/classes/builders/seobar-page.class.php:371
523
  msgid "It's built using the page content."
524
  msgstr ""
525
 
526
- #: inc/classes/builders/seobar-page.class.php:375
527
- #: inc/classes/builders/seobar-page.class.php:384
528
- #: inc/classes/builders/seobar-term.class.php:363
529
- #: inc/classes/builders/seobar-term.class.php:372
530
  msgctxt "Description"
531
  msgid "D"
532
  msgstr ""
533
 
534
- #: inc/classes/builders/seobar-page.class.php:376
535
- #: inc/classes/builders/seobar-page.class.php:385
536
- #: inc/classes/builders/seobar-term.class.php:364
537
- #: inc/classes/builders/seobar-term.class.php:373
538
  msgid "Description"
539
  msgstr ""
540
 
541
- #: inc/classes/builders/seobar-page.class.php:380
542
  msgid "No page description is set."
543
  msgstr ""
544
 
545
- #: inc/classes/builders/seobar-page.class.php:410
546
  msgid "The description inputted at the SEO Settings screen is used."
547
  msgstr ""
548
 
549
- #: inc/classes/builders/seobar-page.class.php:412
550
  msgid "The description inputted at the Edit Page screen is used."
551
  msgstr ""
552
 
553
  #. translators: 1: Word found, 2: Occurrences
554
 
555
- #: inc/classes/builders/seobar-page.class.php:461
556
- #: inc/classes/builders/seobar-term.class.php:431
557
  msgid "&#8220;%1$s&#8221; is used %2$d times."
558
  msgstr ""
559
 
560
- #: inc/classes/builders/seobar-page.class.php:538
561
- #: inc/classes/builders/seobar-page.class.php:695
562
- #: inc/classes/builders/seobar-page.class.php:826
563
- #: inc/classes/builders/seobar-term.class.php:508
564
- #: inc/classes/builders/seobar-term.class.php:662
565
- #: inc/classes/builders/seobar-term.class.php:782
566
  msgid "The robots.txt file is nonstandard, and may still direct search engines differently."
567
  msgstr ""
568
 
569
- #: inc/classes/builders/seobar-page.class.php:539
570
- #: inc/classes/builders/seobar-page.class.php:696
571
- #: inc/classes/builders/seobar-page.class.php:827
572
- #: inc/classes/builders/seobar-term.class.php:509
573
- #: inc/classes/builders/seobar-term.class.php:663
574
- #: inc/classes/builders/seobar-term.class.php:783
575
  msgid "WordPress discourages crawling via the Reading Settings."
576
  msgstr ""
577
 
578
- #: inc/classes/builders/seobar-page.class.php:540
579
- #: inc/classes/builders/seobar-term.class.php:510
580
  msgid "Indexing is discouraged for the whole site at the SEO Settings screen."
581
  msgstr ""
582
 
583
- #: inc/classes/builders/seobar-page.class.php:541
584
  msgid "Indexing is discouraged for this post type at the SEO Settings screen."
585
  msgstr ""
586
 
587
- #: inc/classes/builders/seobar-page.class.php:542
588
  msgid "The page is protected, so indexing is discouraged."
589
  msgstr ""
590
 
591
- #: inc/classes/builders/seobar-page.class.php:543
592
  msgid "The page SEO meta input overrides the indexing state."
593
  msgstr ""
594
 
595
- #: inc/classes/builders/seobar-page.class.php:544
596
- #: inc/classes/builders/seobar-term.class.php:517
597
  msgid "A custom canonical URL is set that points to another page."
598
  msgstr ""
599
 
600
- #: inc/classes/builders/seobar-page.class.php:547
601
- #: inc/classes/builders/seobar-page.class.php:703
602
- #: inc/classes/builders/seobar-page.class.php:834
603
- #: inc/classes/builders/seobar-term.class.php:520
604
- #: inc/classes/builders/seobar-term.class.php:672
605
- #: inc/classes/builders/seobar-term.class.php:792
606
  msgid "WordPress overrides the robots directive."
607
  msgstr ""
608
 
609
- #: inc/classes/builders/seobar-page.class.php:548
610
  msgid "The page is protected."
611
  msgstr ""
612
 
613
- #: inc/classes/builders/seobar-page.class.php:549
614
- #: inc/classes/builders/seobar-page.class.php:704
615
- #: inc/classes/builders/seobar-page.class.php:835
616
  msgid "The page is not published."
617
  msgstr ""
618
 
619
- #: inc/classes/builders/seobar-page.class.php:550
620
- #: inc/classes/builders/seobar-term.class.php:523
621
  msgid "The canonical URL points to another page."
622
  msgstr ""
623
 
624
- #: inc/classes/builders/seobar-page.class.php:554
625
- #: inc/classes/builders/seobar-page.class.php:563
626
- #: inc/classes/builders/seobar-page.class.php:572
627
- #: inc/classes/builders/seobar-term.class.php:527
628
- #: inc/classes/builders/seobar-term.class.php:536
629
  msgctxt "Indexing"
630
  msgid "I"
631
  msgstr ""
632
 
633
- #: inc/classes/builders/seobar-page.class.php:555
634
- #: inc/classes/builders/seobar-page.class.php:564
635
- #: inc/classes/builders/seobar-page.class.php:573
636
- #: inc/classes/builders/seobar-term.class.php:528
637
- #: inc/classes/builders/seobar-term.class.php:537
638
  #: inc/views/admin/metaboxes/robots-metabox.php:54
639
  #: inc/views/edit/seo-settings-singular.php:196
640
  #: inc/views/edit/seo-settings-tt.php:60 inc/views/list/bulk-post.php:19
@@ -642,129 +658,129 @@ msgstr ""
642
  msgid "Indexing"
643
  msgstr ""
644
 
645
- #: inc/classes/builders/seobar-page.class.php:557
646
  msgid "Page may be indexed."
647
  msgstr ""
648
 
649
- #: inc/classes/builders/seobar-page.class.php:559
650
- #: inc/classes/builders/seobar-term.class.php:532
651
  msgid "The robots meta tag allows indexing."
652
  msgstr ""
653
 
654
- #: inc/classes/builders/seobar-page.class.php:566
655
  msgid "Page may not be indexed."
656
  msgstr ""
657
 
658
- #: inc/classes/builders/seobar-page.class.php:568
659
- #: inc/classes/builders/seobar-term.class.php:541
660
  msgid "The robots meta tag does not allow indexing."
661
  msgstr ""
662
 
663
- #: inc/classes/builders/seobar-page.class.php:575
664
- #: inc/classes/builders/seobar-page.class.php:729
665
- #: inc/classes/builders/seobar-page.class.php:860
666
  msgid "Page is invisible."
667
  msgstr ""
668
 
669
- #: inc/classes/builders/seobar-page.class.php:577
670
- #: inc/classes/builders/seobar-page.class.php:731
671
- #: inc/classes/builders/seobar-page.class.php:862
672
  msgid "This page isn't published and can't be found publicly."
673
  msgstr ""
674
 
675
- #: inc/classes/builders/seobar-page.class.php:632
676
  msgid "Indexing is discouraged for the homepage at the SEO Settings screen."
677
  msgstr ""
678
 
679
- #: inc/classes/builders/seobar-page.class.php:697
680
- #: inc/classes/builders/seobar-term.class.php:664
681
  msgid "Link following is discouraged for the whole site at the SEO Settings screen."
682
  msgstr ""
683
 
684
- #: inc/classes/builders/seobar-page.class.php:698
685
  msgid "Link following is discouraged for this post type at the SEO Settings screen."
686
  msgstr ""
687
 
688
- #: inc/classes/builders/seobar-page.class.php:699
689
  msgid "The page SEO meta input overrides the link following state."
690
  msgstr ""
691
 
692
- #: inc/classes/builders/seobar-page.class.php:700
693
  msgid "The page may not be indexed, this may also discourage link following."
694
  msgstr ""
695
 
696
- #: inc/classes/builders/seobar-page.class.php:708
697
- #: inc/classes/builders/seobar-page.class.php:717
698
- #: inc/classes/builders/seobar-page.class.php:726
699
- #: inc/classes/builders/seobar-term.class.php:676
700
- #: inc/classes/builders/seobar-term.class.php:685
701
  msgctxt "Following"
702
  msgid "F"
703
  msgstr ""
704
 
705
- #: inc/classes/builders/seobar-page.class.php:709
706
- #: inc/classes/builders/seobar-page.class.php:718
707
- #: inc/classes/builders/seobar-page.class.php:727
708
- #: inc/classes/builders/seobar-term.class.php:677
709
- #: inc/classes/builders/seobar-term.class.php:686
710
  #: inc/views/admin/metaboxes/robots-metabox.php:60
711
  #: inc/views/list/quick-term.php:26
712
  msgid "Following"
713
  msgstr ""
714
 
715
- #: inc/classes/builders/seobar-page.class.php:711
716
  msgid "Page links may be followed."
717
  msgstr ""
718
 
719
- #: inc/classes/builders/seobar-page.class.php:713
720
- #: inc/classes/builders/seobar-term.class.php:681
721
  msgid "The robots meta tag allows link following."
722
  msgstr ""
723
 
724
- #: inc/classes/builders/seobar-page.class.php:720
725
  msgid "Page links may not be followed."
726
  msgstr ""
727
 
728
- #: inc/classes/builders/seobar-page.class.php:722
729
- #: inc/classes/builders/seobar-term.class.php:690
730
  msgid "The robots meta tag does not allow link following."
731
  msgstr ""
732
 
733
- #: inc/classes/builders/seobar-page.class.php:774
734
  msgid "Link following is discouraged for the homepage at the SEO Settings screen."
735
  msgstr ""
736
 
737
- #: inc/classes/builders/seobar-page.class.php:828
738
- #: inc/classes/builders/seobar-term.class.php:784
739
  msgid "Archiving is discouraged for the whole site at the SEO Settings screen."
740
  msgstr ""
741
 
742
- #: inc/classes/builders/seobar-page.class.php:829
743
  msgid "Archiving is discouraged for this post type at the SEO Settings screen."
744
  msgstr ""
745
 
746
- #: inc/classes/builders/seobar-page.class.php:830
747
  msgid "The page SEO meta input overrides the archiving state."
748
  msgstr ""
749
 
750
- #: inc/classes/builders/seobar-page.class.php:831
751
  msgid "The page may not be indexed, this may also discourage archiving."
752
  msgstr ""
753
 
754
- #: inc/classes/builders/seobar-page.class.php:839
755
- #: inc/classes/builders/seobar-page.class.php:848
756
- #: inc/classes/builders/seobar-page.class.php:857
757
- #: inc/classes/builders/seobar-term.class.php:796
758
- #: inc/classes/builders/seobar-term.class.php:805
759
  msgctxt "Archiving"
760
  msgid "A"
761
  msgstr ""
762
 
763
- #: inc/classes/builders/seobar-page.class.php:840
764
- #: inc/classes/builders/seobar-page.class.php:849
765
- #: inc/classes/builders/seobar-page.class.php:858
766
- #: inc/classes/builders/seobar-term.class.php:797
767
- #: inc/classes/builders/seobar-term.class.php:806
768
  #: inc/views/admin/metaboxes/robots-metabox.php:66
769
  #: inc/views/edit/seo-settings-singular.php:212
770
  #: inc/views/edit/seo-settings-tt.php:86 inc/views/list/bulk-post.php:33
@@ -772,188 +788,188 @@ msgstr ""
772
  msgid "Archiving"
773
  msgstr ""
774
 
775
- #: inc/classes/builders/seobar-page.class.php:842
776
  msgid "Page may be archived."
777
  msgstr ""
778
 
779
- #: inc/classes/builders/seobar-page.class.php:844
780
- #: inc/classes/builders/seobar-term.class.php:801
781
  msgid "The robots meta tag allows archiving."
782
  msgstr ""
783
 
784
- #: inc/classes/builders/seobar-page.class.php:851
785
  msgid "Page may not be archived."
786
  msgstr ""
787
 
788
- #: inc/classes/builders/seobar-page.class.php:853
789
- #: inc/classes/builders/seobar-term.class.php:810
790
  msgid "The robots meta tag does not allow archiving."
791
  msgstr ""
792
 
793
- #: inc/classes/builders/seobar-page.class.php:905
794
  msgid "Archiving is discouraged for the homepage at the SEO Settings screen."
795
  msgstr ""
796
 
797
- #: inc/classes/builders/seobar-page.class.php:956
798
- #: inc/classes/builders/seobar-page.class.php:972
799
- #: inc/classes/builders/seobar-term.class.php:900
800
- #: inc/classes/builders/seobar-term.class.php:916
801
  msgctxt "Redirect"
802
  msgid "R"
803
  msgstr ""
804
 
805
- #: inc/classes/builders/seobar-page.class.php:957
806
- #: inc/classes/builders/seobar-page.class.php:973
807
- #: inc/classes/builders/seobar-term.class.php:901
808
- #: inc/classes/builders/seobar-term.class.php:917
809
  msgid "Redirection"
810
  msgstr ""
811
 
812
- #: inc/classes/builders/seobar-page.class.php:959
813
  msgid "Page does not redirect visitors."
814
  msgstr ""
815
 
816
- #: inc/classes/builders/seobar-page.class.php:961
817
- #: inc/classes/builders/seobar-term.class.php:905
818
  msgid "All visitors and crawlers may access this page."
819
  msgstr ""
820
 
821
- #: inc/classes/builders/seobar-page.class.php:975
822
  msgid "Page redirects visitors."
823
  msgstr ""
824
 
825
- #: inc/classes/builders/seobar-page.class.php:977
826
- #: inc/classes/builders/seobar-term.class.php:921
827
  msgid "All visitors and crawlers are being redirected. So, no other SEO enhancements are effective."
828
  msgstr ""
829
 
830
- #: inc/classes/builders/seobar-term.class.php:166
831
  msgid "A term label prefix is automatically added which increases the length."
832
  msgstr ""
833
 
834
- #: inc/classes/builders/seobar-term.class.php:193
835
- #: inc/classes/builders/seobar-term.class.php:375
836
  msgid "Obtained from term SEO meta input."
837
  msgstr ""
838
 
839
- #: inc/classes/builders/seobar-term.class.php:195
840
- #: inc/classes/builders/seobar-term.class.php:377
841
  msgid "It's built from term SEO meta input."
842
  msgstr ""
843
 
844
- #: inc/classes/builders/seobar-term.class.php:343
845
  msgid "No description could be generated."
846
  msgstr ""
847
 
848
- #: inc/classes/builders/seobar-term.class.php:359
849
  msgid "It's built using the term description field."
850
  msgstr ""
851
 
852
- #: inc/classes/builders/seobar-term.class.php:368
853
  msgid "No term description is set."
854
  msgstr ""
855
 
856
- #: inc/classes/builders/seobar-term.class.php:511
857
  msgid "Indexing is discouraged for all bound post types to this term at the SEO Settings screen."
858
  msgstr ""
859
 
860
- #: inc/classes/builders/seobar-term.class.php:512
861
  msgid "Indexing is discouraged for all post categories at the SEO Settings screen."
862
  msgstr ""
863
 
864
- #: inc/classes/builders/seobar-term.class.php:513
865
  msgid "Indexing is discouraged for all post tags at the SEO Settings screen."
866
  msgstr ""
867
 
868
- #: inc/classes/builders/seobar-term.class.php:514
869
  msgid "The term SEO meta input overrides the indexing state."
870
  msgstr ""
871
 
872
- #: inc/classes/builders/seobar-term.class.php:515
873
  msgid "No posts are attached to this term, so indexing is disabled."
874
  msgstr ""
875
 
876
- #: inc/classes/builders/seobar-term.class.php:516
877
  msgid "No posts are attached to this term, so indexing should be disabled."
878
  msgstr ""
879
 
880
- #: inc/classes/builders/seobar-term.class.php:521
881
  msgid "The term is empty."
882
  msgstr ""
883
 
884
- #: inc/classes/builders/seobar-term.class.php:522
885
  msgid "The term is empty yet still indexed."
886
  msgstr ""
887
 
888
- #: inc/classes/builders/seobar-term.class.php:530
889
  msgid "Term may be indexed."
890
  msgstr ""
891
 
892
- #: inc/classes/builders/seobar-term.class.php:539
893
  msgid "Term may not be indexed."
894
  msgstr ""
895
 
896
- #: inc/classes/builders/seobar-term.class.php:665
897
  msgid "Link following is discouraged for all bound post types to this term at the SEO Settings screen."
898
  msgstr ""
899
 
900
- #: inc/classes/builders/seobar-term.class.php:666
901
  msgid "Link following is discouraged for all post categories at the SEO Settings screen."
902
  msgstr ""
903
 
904
- #: inc/classes/builders/seobar-term.class.php:667
905
  msgid "Link following is discouraged for all post tags at the SEO Settings screen."
906
  msgstr ""
907
 
908
- #: inc/classes/builders/seobar-term.class.php:668
909
  msgid "The term SEO meta input overrides the link following state."
910
  msgstr ""
911
 
912
- #: inc/classes/builders/seobar-term.class.php:669
913
  msgid "The term may not be indexed, this may also discourage link following."
914
  msgstr ""
915
 
916
- #: inc/classes/builders/seobar-term.class.php:679
917
  msgid "Term links may be followed."
918
  msgstr ""
919
 
920
- #: inc/classes/builders/seobar-term.class.php:688
921
  msgid "Term links may not be followed."
922
  msgstr ""
923
 
924
- #: inc/classes/builders/seobar-term.class.php:785
925
  msgid "Archiving is discouraged for all bound post types to this term at the SEO Settings screen."
926
  msgstr ""
927
 
928
- #: inc/classes/builders/seobar-term.class.php:786
929
  msgid "Archiving is discouraged for all post categories at the SEO Settings screen."
930
  msgstr ""
931
 
932
- #: inc/classes/builders/seobar-term.class.php:787
933
  msgid "Archiving is discouraged for all post tags at the SEO Settings screen."
934
  msgstr ""
935
 
936
- #: inc/classes/builders/seobar-term.class.php:788
937
  msgid "The term SEO meta input overrides the archiving state."
938
  msgstr ""
939
 
940
- #: inc/classes/builders/seobar-term.class.php:789
941
  msgid "The term may not be indexed, this may also discourage archiving."
942
  msgstr ""
943
 
944
- #: inc/classes/builders/seobar-term.class.php:799
945
  msgid "Term may be archived."
946
  msgstr ""
947
 
948
- #: inc/classes/builders/seobar-term.class.php:808
949
  msgid "Term may not be archived."
950
  msgstr ""
951
 
952
- #: inc/classes/builders/seobar-term.class.php:903
953
  msgid "Term does not redirect visitors."
954
  msgstr ""
955
 
956
- #: inc/classes/builders/seobar-term.class.php:919
957
  msgid "Term redirects visitors."
958
  msgstr ""
959
 
@@ -967,27 +983,31 @@ msgstr ""
967
  msgid "Settings"
968
  msgstr ""
969
 
970
- #: inc/classes/core.class.php:225
971
  msgctxt "About us"
972
  msgid "About"
973
  msgstr ""
974
 
975
- #: inc/classes/core.class.php:230
976
  msgctxt "Plugin extensions"
977
  msgid "Extensions"
978
  msgstr ""
979
 
980
- #: inc/classes/core.class.php:263
 
 
 
 
981
  msgid "View documentation"
982
  msgstr ""
983
 
984
- #: inc/classes/core.class.php:270
985
  msgid "View API docs"
986
  msgstr ""
987
 
988
- #: inc/classes/core.class.php:277
989
  msgctxt "Extension Manager is a product name; do not translate it."
990
- msgid "Get the Extension Manager"
991
  msgstr ""
992
 
993
  #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
@@ -1059,124 +1079,125 @@ msgstr ""
1059
 
1060
  #. translators: Category archive title. 1: Category name
1061
 
1062
- #: inc/classes/generate-title.class.php:756
1063
- #: inc/classes/generate-title.class.php:777
1064
  msgid "Category: %s"
1065
  msgstr ""
1066
 
1067
  #. translators: Tag archive title. 1: Tag name
1068
 
1069
- #: inc/classes/generate-title.class.php:760
1070
- #: inc/classes/generate-title.class.php:781
1071
  msgid "Tag: %s"
1072
  msgstr ""
1073
 
1074
- #: inc/classes/generate-title.class.php:771
1075
- #: inc/classes/generate-title.class.php:833
1076
- msgid "Archives"
1077
- msgstr ""
1078
-
1079
  #. translators: Author archive title. 1: Author name
1080
 
1081
- #: inc/classes/generate-title.class.php:785
 
1082
  msgid "Author: %s"
1083
  msgstr ""
1084
 
1085
- #: inc/classes/generate-title.class.php:788
 
 
 
 
 
1086
  msgctxt "yearly archives date format"
1087
  msgid "Y"
1088
  msgstr ""
1089
 
1090
  #. translators: Yearly archive title. 1: Year
1091
 
1092
- #: inc/classes/generate-title.class.php:790
1093
  msgid "Year: %s"
1094
  msgstr ""
1095
 
1096
- #: inc/classes/generate-title.class.php:792
1097
  msgctxt "monthly archives date format"
1098
  msgid "F Y"
1099
  msgstr ""
1100
 
1101
  #. translators: Monthly archive title. 1: Month name and year
1102
 
1103
- #: inc/classes/generate-title.class.php:794
1104
  msgid "Month: %s"
1105
  msgstr ""
1106
 
1107
- #: inc/classes/generate-title.class.php:796
1108
  msgctxt "daily archives date format"
1109
  msgid "F j, Y"
1110
  msgstr ""
1111
 
1112
  #. translators: Daily archive title. 1: Date
1113
 
1114
- #: inc/classes/generate-title.class.php:798
1115
  msgid "Day: %s"
1116
  msgstr ""
1117
 
1118
- #: inc/classes/generate-title.class.php:802
1119
  msgctxt "post format archive title"
1120
  msgid "Asides"
1121
  msgstr ""
1122
 
1123
- #: inc/classes/generate-title.class.php:804
1124
  msgctxt "post format archive title"
1125
  msgid "Galleries"
1126
  msgstr ""
1127
 
1128
- #: inc/classes/generate-title.class.php:806
1129
  msgctxt "post format archive title"
1130
  msgid "Images"
1131
  msgstr ""
1132
 
1133
- #: inc/classes/generate-title.class.php:808
1134
  msgctxt "post format archive title"
1135
  msgid "Videos"
1136
  msgstr ""
1137
 
1138
- #: inc/classes/generate-title.class.php:810
1139
  msgctxt "post format archive title"
1140
  msgid "Quotes"
1141
  msgstr ""
1142
 
1143
- #: inc/classes/generate-title.class.php:812
1144
  msgctxt "post format archive title"
1145
  msgid "Links"
1146
  msgstr ""
1147
 
1148
- #: inc/classes/generate-title.class.php:814
1149
  msgctxt "post format archive title"
1150
  msgid "Statuses"
1151
  msgstr ""
1152
 
1153
- #: inc/classes/generate-title.class.php:816
1154
  msgctxt "post format archive title"
1155
  msgid "Audio"
1156
  msgstr ""
1157
 
1158
- #: inc/classes/generate-title.class.php:818
1159
  msgctxt "post format archive title"
1160
  msgid "Chats"
1161
  msgstr ""
1162
 
1163
  #. translators: Post type archive title. 1: Post type name
1164
 
1165
- #: inc/classes/generate-title.class.php:823
1166
  msgid "Archives: %s"
1167
  msgstr ""
1168
 
1169
- #: inc/classes/generate-title.class.php:980
1170
  msgid "Untitled"
1171
  msgstr ""
1172
 
1173
  #. translators: %s: search phrase
1174
 
1175
- #: inc/classes/generate-title.class.php:992
1176
  msgid "Search Results for &#8220;%s&#8221;"
1177
  msgstr ""
1178
 
1179
- #: inc/classes/generate-title.class.php:1107
1180
  msgid "Page %s"
1181
  msgstr ""
1182
 
@@ -1206,7 +1227,7 @@ msgid "Facebook profile page"
1206
  msgstr ""
1207
 
1208
  #: inc/classes/profile.class.php:92
1209
- #: inc/views/admin/metaboxes/social-metabox.php:155
1210
  msgctxt "Example Facebook Personal URL"
1211
  msgid "https://www.facebook.com/YourPersonalProfile"
1212
  msgstr ""
@@ -1216,12 +1237,12 @@ msgid "Twitter profile name"
1216
  msgstr ""
1217
 
1218
  #: inc/classes/profile.class.php:99
1219
- #: inc/views/admin/metaboxes/social-metabox.php:227
1220
  msgctxt "Twitter @username"
1221
  msgid "@your-personal-username"
1222
  msgstr ""
1223
 
1224
- #: inc/classes/render.class.php:1113
1225
  msgid "by Sybre Waaijer"
1226
  msgstr ""
1227
 
@@ -1284,13 +1305,21 @@ msgstr ""
1284
  msgid "This link will not be followed by search engines."
1285
  msgstr ""
1286
 
 
 
 
 
 
 
 
 
1287
  #. translators: %s = Reading Settings URL. Links are in Markdown!
1288
 
1289
- #: inc/views/admin/metaboxes/feed-metabox.php:44
1290
  msgid "Note: The feed is already converted into an excerpt through the [Reading Settings](%s)."
1291
  msgstr ""
1292
 
1293
- #: inc/views/admin/metaboxes/feed-metabox.php:57
1294
  msgid "View the main feed."
1295
  msgstr ""
1296
 
@@ -1425,153 +1454,149 @@ msgid "Transient Cache Settings"
1425
  msgstr ""
1426
 
1427
  #: inc/views/admin/metaboxes/general-metabox.php:247
1428
- msgid "To improve performance, generated SEO output can be stored in the database as transient cache."
1429
  msgstr ""
1430
 
1431
  #: inc/views/admin/metaboxes/general-metabox.php:248
1432
  msgid "If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options."
1433
  msgstr ""
1434
 
1435
- #: inc/views/admin/metaboxes/general-metabox.php:254
1436
- msgid "Enable automated Schema.org output cache?"
1437
- msgstr ""
1438
-
1439
- #: inc/views/admin/metaboxes/general-metabox.php:255
1440
- msgid "Schema.org output generally makes multiple calls to the database."
1441
- msgstr ""
1442
-
1443
- #: inc/views/admin/metaboxes/general-metabox.php:261
1444
  msgid "Enable sitemap generation cache?"
1445
  msgstr ""
1446
 
1447
- #: inc/views/admin/metaboxes/general-metabox.php:262
1448
  msgid "Generating the sitemap can use a lot of server resources."
1449
  msgstr ""
1450
 
1451
- #: inc/views/admin/metaboxes/general-metabox.php:274
1452
  msgid "Object Cache Settings"
1453
  msgstr ""
1454
 
1455
- #: inc/views/admin/metaboxes/general-metabox.php:280
1456
  msgid "Enable object cache?"
1457
  msgstr ""
1458
 
1459
- #: inc/views/admin/metaboxes/general-metabox.php:281
1460
  msgid "Object cache generally works faster than transient cache."
1461
  msgstr ""
1462
 
1463
- #: inc/views/admin/metaboxes/general-metabox.php:282
1464
  msgid "An object cache handler has been detected. If you enable this option, you may wish to disable the Schema.org transient caching."
1465
  msgstr ""
1466
 
1467
- #: inc/views/admin/metaboxes/general-metabox.php:292
1468
  msgid "Canonical URL Settings"
1469
  msgstr ""
1470
 
1471
- #: inc/views/admin/metaboxes/general-metabox.php:294
1472
  msgid "The canonical URL meta tag urges search engines to go to the outputted URL."
1473
  msgstr ""
1474
 
1475
- #: inc/views/admin/metaboxes/general-metabox.php:295
1476
  msgid "If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL."
1477
  msgstr ""
1478
 
1479
- #: inc/views/admin/metaboxes/general-metabox.php:299
1480
  msgid "Scheme Settings"
1481
  msgstr ""
1482
 
1483
- #: inc/views/admin/metaboxes/general-metabox.php:301
1484
  msgid "If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines."
1485
  msgstr ""
1486
 
1487
- #: inc/views/admin/metaboxes/general-metabox.php:303
1488
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1489
  msgid "Preferred canonical URL scheme:"
1490
  msgstr ""
1491
 
1492
  #. translators: %s = HTTP or HTTPS
1493
 
1494
- #: inc/views/admin/metaboxes/general-metabox.php:311
1495
  msgid "Detect automatically (%s)"
1496
  msgstr ""
1497
 
1498
- #: inc/views/admin/metaboxes/general-metabox.php:325
1499
  msgid "Link Relationship Settings"
1500
  msgstr ""
1501
 
1502
- #: inc/views/admin/metaboxes/general-metabox.php:327
1503
  msgid "Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results."
1504
  msgstr ""
1505
 
1506
- #: inc/views/admin/metaboxes/general-metabox.php:328
1507
  msgid "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues."
1508
  msgstr ""
1509
 
1510
  #. translators: the backticks are Markdown! Preserve them as-is!
1511
 
1512
- #: inc/views/admin/metaboxes/general-metabox.php:334
1513
  msgid "Add `rel` link tags to posts and pages?"
1514
  msgstr ""
1515
 
1516
  #. translators: the backticks are Markdown! Preserve them as-is!
1517
 
1518
- #: inc/views/admin/metaboxes/general-metabox.php:345
1519
  msgid "Add `rel` link tags to archives?"
1520
  msgstr ""
1521
 
1522
  #. translators: the backticks are Markdown! Preserve them as-is!
1523
 
1524
- #: inc/views/admin/metaboxes/general-metabox.php:356
1525
  msgid "Add `rel` link tags to the homepage?"
1526
  msgstr ""
1527
 
1528
- #: inc/views/admin/metaboxes/general-metabox.php:383
1529
  msgid "Timestamp Settings"
1530
  msgstr ""
1531
 
1532
- #: inc/views/admin/metaboxes/general-metabox.php:385
1533
  msgid "Timestamps help indicate when a page has been published and modified."
1534
  msgstr ""
1535
 
1536
- #: inc/views/admin/metaboxes/general-metabox.php:391
1537
  msgid "Timestamp Format Settings"
1538
  msgstr ""
1539
 
1540
- #: inc/views/admin/metaboxes/general-metabox.php:392
1541
  msgid "This setting determines how specific the timestamp is."
1542
  msgstr ""
1543
 
1544
- #: inc/views/admin/metaboxes/general-metabox.php:404
1545
  msgid "This outputs the complete date."
1546
  msgstr ""
1547
 
1548
- #: inc/views/admin/metaboxes/general-metabox.php:417
1549
  msgid "This outputs the complete date including hours, minutes, and timezone."
1550
  msgstr ""
1551
 
1552
- #: inc/views/admin/metaboxes/general-metabox.php:429
1553
- #: inc/views/admin/metaboxes/robots-metabox.php:313
1554
  msgid "Post Type Settings"
1555
  msgstr ""
1556
 
1557
- #: inc/views/admin/metaboxes/general-metabox.php:431
1558
  msgid "Post types are special content types. These options should not need changing when post types are registered correctly."
1559
  msgstr ""
1560
 
1561
- #: inc/views/admin/metaboxes/general-metabox.php:436
1562
  msgid "Disable SEO"
1563
  msgstr ""
1564
 
1565
- #: inc/views/admin/metaboxes/general-metabox.php:438
1566
  msgid "Select post types which should not receive any SEO optimization whatsoever. This will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types."
1567
  msgstr ""
1568
 
1569
- #: inc/views/admin/metaboxes/general-metabox.php:439
1570
- #: inc/views/admin/metaboxes/robots-metabox.php:315
 
 
 
 
1571
  msgid "These settings are applied to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect."
1572
  msgstr ""
1573
 
1574
- #: inc/views/admin/metaboxes/general-metabox.php:440
1575
  msgid "Default post types can not be disabled."
1576
  msgstr ""
1577
 
@@ -1690,7 +1715,7 @@ msgid "Twitter Description"
1690
  msgstr ""
1691
 
1692
  #: inc/views/admin/metaboxes/homepage-metabox.php:370
1693
- #: inc/views/admin/metaboxes/social-metabox.php:105
1694
  msgid "Social Image Settings"
1695
  msgstr ""
1696
 
@@ -1711,6 +1736,7 @@ msgid "The social image URL can be used by search engines and social networks al
1711
  msgstr ""
1712
 
1713
  #: inc/views/admin/metaboxes/homepage-metabox.php:421
 
1714
  msgid "Edit homepage page settings"
1715
  msgstr ""
1716
 
@@ -1803,7 +1829,7 @@ msgid "These options most likely prevent indexing of the selected archives and p
1803
  msgstr ""
1804
 
1805
  #: inc/views/admin/metaboxes/robots-metabox.php:38
1806
- msgid "These options most likely prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your own links."
1807
  msgstr ""
1808
 
1809
  #: inc/views/admin/metaboxes/robots-metabox.php:42
@@ -1811,139 +1837,144 @@ msgid "These options most likely prevent caching of the selected archives and pa
1811
  msgstr ""
1812
 
1813
  #: inc/views/admin/metaboxes/robots-metabox.php:87
1814
- msgid "Paginated Archive Settings"
1815
  msgstr ""
1816
 
1817
  #: inc/views/admin/metaboxes/robots-metabox.php:89
 
 
 
 
 
 
 
 
 
 
 
 
1818
  msgid "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages."
1819
  msgstr ""
1820
 
1821
  #. translators: the backticks are Markdown! Preserve them as-is!
1822
 
1823
- #: inc/views/admin/metaboxes/robots-metabox.php:96
1824
  msgid "Apply `noindex` to every second or later archive page?"
1825
  msgstr ""
1826
 
1827
- #: inc/views/admin/metaboxes/robots-metabox.php:107
1828
  msgid "Copyright Directive Settings"
1829
  msgstr ""
1830
 
1831
- #: inc/views/admin/metaboxes/robots-metabox.php:109
1832
  msgid "Some search engines allow you to control copyright directives on the content they aggregate. It's best to allow some content to be taken by these aggregators, as that can improve contextualized exposure via snippets and previews. When left unspecified, regional regulations may apply. It is up to the aggregator to honor these requests."
1833
  msgstr ""
1834
 
1835
- #: inc/views/admin/metaboxes/robots-metabox.php:114
1836
  msgid "Specify aggregator copyright compliance directives?"
1837
  msgstr ""
1838
 
1839
- #: inc/views/admin/metaboxes/robots-metabox.php:122
1840
  msgid "Unlimited"
1841
  msgstr ""
1842
 
1843
- #: inc/views/admin/metaboxes/robots-metabox.php:123
1844
  msgctxt "quanity: zero"
1845
  msgid "None, disallow snippet"
1846
  msgstr ""
1847
 
1848
  #. translators: %d = number
1849
 
1850
- #: inc/views/admin/metaboxes/robots-metabox.php:127
1851
  msgid "%d character"
1852
  msgid_plural "%d characters"
1853
  msgstr[0] ""
1854
  msgstr[1] ""
1855
 
1856
- #: inc/views/admin/metaboxes/robots-metabox.php:133
1857
- #: inc/views/admin/metaboxes/robots-metabox.php:229
1858
  msgid "Standard directive"
1859
  msgstr ""
1860
 
1861
- #: inc/views/admin/metaboxes/robots-metabox.php:134
1862
- #: inc/views/admin/metaboxes/robots-metabox.php:230
1863
  msgid "Granular directive"
1864
  msgstr ""
1865
 
1866
- #: inc/views/admin/metaboxes/robots-metabox.php:157
1867
  msgid "Maximum text snippet length"
1868
  msgstr ""
1869
 
1870
- #: inc/views/admin/metaboxes/robots-metabox.php:161
1871
  msgid "This may limit the text snippet length for all pages on this site."
1872
  msgstr ""
1873
 
1874
- #: inc/views/admin/metaboxes/robots-metabox.php:165
1875
  msgid "This directive also imposes a limit on meta descriptions and structured data, which unintentionally restricts the amount of information you can share. Therefore, it's best to use at least a 320 character limit."
1876
  msgstr ""
1877
 
1878
- #: inc/views/admin/metaboxes/robots-metabox.php:174
1879
  msgctxt "quanity: zero"
1880
  msgid "None, disallow preview"
1881
  msgstr ""
1882
 
1883
- #: inc/views/admin/metaboxes/robots-metabox.php:175
1884
  msgid "Thumbnail or standard size"
1885
  msgstr ""
1886
 
1887
- #: inc/views/admin/metaboxes/robots-metabox.php:176
1888
  msgid "Large or full size"
1889
  msgstr ""
1890
 
1891
- #: inc/views/admin/metaboxes/robots-metabox.php:195
1892
  msgid "Maximum image preview size"
1893
  msgstr ""
1894
 
1895
- #: inc/views/admin/metaboxes/robots-metabox.php:199
1896
  msgid "This may limit the image preview size for all images from this site."
1897
  msgstr ""
1898
 
1899
- #. translators: Backticks and hyperlink are Markdown! %s = link to
1900
- #. documentation.
1901
-
1902
- #: inc/views/admin/metaboxes/robots-metabox.php:206
1903
- msgid "The \"None, disallow preview\" setting will not be used when `nofollow` or `noarchive` are set for a page. This is to work around unexpected deindexing behavior in Google Search. [Learn more](%s)."
1904
- msgstr ""
1905
-
1906
- #: inc/views/admin/metaboxes/robots-metabox.php:218
1907
  msgid "Full video preview"
1908
  msgstr ""
1909
 
1910
- #: inc/views/admin/metaboxes/robots-metabox.php:219
1911
  msgctxt "quanity: zero"
1912
  msgid "None, still image only"
1913
  msgstr ""
1914
 
1915
  #. translators: %d = number
1916
 
1917
- #: inc/views/admin/metaboxes/robots-metabox.php:223
1918
  msgid "%d second"
1919
  msgid_plural "%d seconds"
1920
  msgstr[0] ""
1921
  msgstr[1] ""
1922
 
1923
- #: inc/views/admin/metaboxes/robots-metabox.php:252
1924
  msgid "Maximum video preview length"
1925
  msgstr ""
1926
 
1927
- #: inc/views/admin/metaboxes/robots-metabox.php:256
1928
  msgid "This may limit the video preview length for all videos on this site."
1929
  msgstr ""
1930
 
1931
  #. translators: 1 = noindex/nofollow/noarchive, 2 = Post, Post type, Category
1932
  #. archives, the entire site, etc.
1933
 
1934
- #: inc/views/admin/metaboxes/robots-metabox.php:271
1935
  msgid "Apply %1$s to %2$s?"
1936
  msgstr ""
1937
 
1938
- #: inc/views/admin/metaboxes/robots-metabox.php:276
1939
  msgid "Robots Settings"
1940
  msgstr ""
1941
 
1942
- #: inc/views/admin/metaboxes/robots-metabox.php:301
1943
  msgid "Warning: No public site should ever enable this option."
1944
  msgstr ""
1945
 
1946
- #: inc/views/admin/metaboxes/robots-metabox.php:320
1947
  msgid "Warning: No site should enable these options for Posts and Pages."
1948
  msgstr ""
1949
 
@@ -2074,64 +2105,70 @@ msgid "Setting a logo requires JavaScript."
2074
  msgstr ""
2075
 
2076
  #: inc/views/admin/metaboxes/schema-metabox.php:193
2077
- msgid "Connected Social Pages"
2078
- msgstr ""
2079
-
2080
- #: inc/views/admin/metaboxes/schema-metabox.php:195
2081
- msgid "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway."
2082
- msgstr ""
2083
-
2084
- #: inc/views/admin/metaboxes/schema-metabox.php:196
2085
- msgid "Add links that lead directly to the connected social pages of this website."
2086
- msgstr ""
2087
-
2088
- #: inc/views/admin/metaboxes/schema-metabox.php:197
2089
- msgid "These settings do not affect sharing behavior with the social networks."
2090
- msgstr ""
2091
-
2092
- #: inc/views/admin/metaboxes/schema-metabox.php:199
2093
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
2094
  msgid "RelatedProfile"
2095
  msgstr ""
2096
 
2097
- #: inc/views/admin/metaboxes/schema-metabox.php:208
2098
  msgid "Facebook Page"
2099
  msgstr ""
2100
 
2101
- #: inc/views/admin/metaboxes/schema-metabox.php:215
2102
  msgid "Twitter Profile"
2103
  msgstr ""
2104
 
2105
- #: inc/views/admin/metaboxes/schema-metabox.php:222
2106
  msgctxt "Google+ is dead. &#8224; is a cross, indicating that."
2107
  msgid "Google+ Profile&#8224;"
2108
  msgstr ""
2109
 
2110
- #: inc/views/admin/metaboxes/schema-metabox.php:229
2111
  msgid "Instagram Profile"
2112
  msgstr ""
2113
 
2114
- #: inc/views/admin/metaboxes/schema-metabox.php:236
2115
  msgid "Youtube Profile"
2116
  msgstr ""
2117
 
2118
- #: inc/views/admin/metaboxes/schema-metabox.php:243
2119
  msgid "LinkedIn Profile"
2120
  msgstr ""
2121
 
2122
- #: inc/views/admin/metaboxes/schema-metabox.php:250
2123
  msgid "Pinterest Profile"
2124
  msgstr ""
2125
 
2126
- #: inc/views/admin/metaboxes/schema-metabox.php:257
2127
  msgid "SoundCloud Profile"
2128
  msgstr ""
2129
 
2130
- #: inc/views/admin/metaboxes/schema-metabox.php:264
2131
  msgid "Tumblr Blog"
2132
  msgstr ""
2133
 
2134
- #: inc/views/admin/metaboxes/schema-metabox.php:278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2135
  msgid "View your profile."
2136
  msgstr ""
2137
 
@@ -2160,11 +2197,11 @@ msgstr ""
2160
  msgid "The sitemap does not contribute to ranking, only indexing. Therefore, it is perfectly fine not having every indexable page in the sitemap."
2161
  msgstr ""
2162
 
2163
- #: inc/views/admin/metaboxes/sitemaps-metabox.php:70
2164
  msgid "Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect."
2165
  msgstr ""
2166
 
2167
- #: inc/views/admin/metaboxes/sitemaps-metabox.php:73
2168
  msgid "Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect."
2169
  msgstr ""
2170
 
@@ -2341,187 +2378,223 @@ msgstr ""
2341
  msgid "Sitemap title and lines color"
2342
  msgstr ""
2343
 
2344
- #: inc/views/admin/metaboxes/social-metabox.php:35
2345
  msgid "Post Dates"
2346
  msgstr ""
2347
 
2348
- #: inc/views/admin/metaboxes/social-metabox.php:55
2349
  msgid "Social Meta Tags Settings"
2350
  msgstr ""
2351
 
2352
- #: inc/views/admin/metaboxes/social-metabox.php:57
2353
  msgid "Output various meta tags for social site integration, among other 3rd party services."
2354
  msgstr ""
2355
 
2356
- #: inc/views/admin/metaboxes/social-metabox.php:67
2357
  msgid "Output Open Graph meta tags?"
2358
  msgstr ""
2359
 
2360
- #: inc/views/admin/metaboxes/social-metabox.php:68
2361
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these meta tags."
2362
  msgstr ""
2363
 
2364
- #: inc/views/admin/metaboxes/social-metabox.php:75
2365
  msgid "Note: Another Open Graph plugin has been detected. These meta tags might conflict."
2366
  msgstr ""
2367
 
2368
- #: inc/views/admin/metaboxes/social-metabox.php:81
2369
  msgid "Output Facebook meta tags?"
2370
  msgstr ""
2371
 
2372
- #: inc/views/admin/metaboxes/social-metabox.php:82
2373
  msgid "Output various meta tags targeted at Facebook."
2374
  msgstr ""
2375
 
2376
- #: inc/views/admin/metaboxes/social-metabox.php:92
2377
  msgid "Output Twitter meta tags?"
2378
  msgstr ""
2379
 
2380
- #: inc/views/admin/metaboxes/social-metabox.php:93
2381
  msgid "Output various meta tags targeted at Twitter."
2382
  msgstr ""
2383
 
2384
- #: inc/views/admin/metaboxes/social-metabox.php:100
2385
  msgid "Note: Another Twitter Card plugin has been detected. These meta tags might conflict."
2386
  msgstr ""
2387
 
2388
- #: inc/views/admin/metaboxes/social-metabox.php:107
 
 
 
 
 
 
 
 
2389
  msgid "A social image can be displayed when your website is shared. It is a great way to grab attention."
2390
  msgstr ""
2391
 
2392
- #: inc/views/admin/metaboxes/social-metabox.php:113
2393
  msgid "Output multiple Open Graph image tags?"
2394
  msgstr ""
2395
 
2396
- #: inc/views/admin/metaboxes/social-metabox.php:114
2397
  msgid "This enables users to select any image attached to the page shared on social networks, like Facebook."
2398
  msgstr ""
2399
 
2400
- #: inc/views/admin/metaboxes/social-metabox.php:122
2401
  msgid "Social Image Fallback URL"
2402
  msgstr ""
2403
 
2404
- #: inc/views/admin/metaboxes/social-metabox.php:123
2405
  msgid "When no image is available from the page or term, this fallback image will be used instead."
2406
  msgstr ""
2407
 
2408
- #: inc/views/admin/metaboxes/social-metabox.php:138
 
 
 
 
 
 
 
 
 
 
 
 
2409
  msgid "Site Shortlink Settings"
2410
  msgstr ""
2411
 
2412
- #: inc/views/admin/metaboxes/social-metabox.php:140
2413
  msgid "The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever."
2414
  msgstr ""
2415
 
2416
- #: inc/views/admin/metaboxes/social-metabox.php:145
2417
  msgid "Output shortlink tag?"
2418
  msgstr ""
2419
 
2420
- #: inc/views/admin/metaboxes/social-metabox.php:158
2421
  msgctxt "Example Facebook Business URL"
2422
  msgid "https://www.facebook.com/YourBusinessProfile"
2423
  msgstr ""
2424
 
2425
- #: inc/views/admin/metaboxes/social-metabox.php:164
2426
- msgid "Default Facebook Integration Settings"
2427
  msgstr ""
2428
 
2429
- #: inc/views/admin/metaboxes/social-metabox.php:166
2430
  msgid "Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options."
2431
  msgstr ""
2432
 
2433
- #: inc/views/admin/metaboxes/social-metabox.php:167
2434
  msgid "When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared."
2435
  msgstr ""
2436
 
2437
- #: inc/views/admin/metaboxes/social-metabox.php:173
2438
  msgid "Facebook App ID"
2439
  msgstr ""
2440
 
2441
- #: inc/views/admin/metaboxes/social-metabox.php:177
2442
  msgid "Get Facebook App ID."
2443
  msgstr ""
2444
 
2445
- #: inc/views/admin/metaboxes/social-metabox.php:189
2446
  msgid "Facebook Publisher page"
2447
  msgstr ""
2448
 
2449
- #: inc/views/admin/metaboxes/social-metabox.php:193
2450
  msgid "Only Facebook Business Pages are accepted."
2451
  msgstr ""
2452
 
2453
- #: inc/views/admin/metaboxes/social-metabox.php:205
2454
  msgid "Facebook Author Fallback Page"
2455
  msgstr ""
2456
 
2457
- #: inc/views/admin/metaboxes/social-metabox.php:209
2458
  msgid "Your Facebook profile."
2459
  msgstr ""
2460
 
2461
- #: inc/views/admin/metaboxes/social-metabox.php:215
2462
- #: inc/views/admin/metaboxes/social-metabox.php:307
2463
  msgid "Authors can override this option on their profile page."
2464
  msgstr ""
2465
 
2466
- #: inc/views/admin/metaboxes/social-metabox.php:224
2467
  msgctxt "Twitter @username"
2468
  msgid "@your-site-username"
2469
  msgstr ""
2470
 
2471
- #: inc/views/admin/metaboxes/social-metabox.php:232
2472
- msgid "Default Twitter Integration Settings"
2473
  msgstr ""
2474
 
2475
- #: inc/views/admin/metaboxes/social-metabox.php:234
2476
  msgid "Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
2477
  msgstr ""
2478
 
2479
- #: inc/views/admin/metaboxes/social-metabox.php:240
2480
  msgid "Twitter Card Type"
2481
  msgstr ""
2482
 
2483
- #: inc/views/admin/metaboxes/social-metabox.php:243
2484
  msgid "The Twitter Card type may have the image highlighted, either small at the side or large above."
2485
  msgstr ""
2486
 
2487
- #: inc/views/admin/metaboxes/social-metabox.php:276
2488
  msgid "When the following options are filled in, Twitter might link your Twitter Site or Author Profile when your post or page is shared."
2489
  msgstr ""
2490
 
2491
- #: inc/views/admin/metaboxes/social-metabox.php:281
2492
  msgid "Website Twitter Profile"
2493
  msgstr ""
2494
 
2495
- #: inc/views/admin/metaboxes/social-metabox.php:285
2496
- #: inc/views/admin/metaboxes/social-metabox.php:301
2497
  msgid "Find your @username."
2498
  msgstr ""
2499
 
2500
- #: inc/views/admin/metaboxes/social-metabox.php:297
2501
  msgid "Twitter Author Fallback Profile"
2502
  msgstr ""
2503
 
2504
- #: inc/views/admin/metaboxes/social-metabox.php:315
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2505
  msgid "Posts"
2506
  msgstr ""
2507
 
2508
- #: inc/views/admin/metaboxes/social-metabox.php:318
2509
  msgid "Post Date Settings"
2510
  msgstr ""
2511
 
2512
- #: inc/views/admin/metaboxes/social-metabox.php:320
2513
  msgid "Some social sites output the shared post's publishing and modified data in the sharing snippet."
2514
  msgstr ""
2515
 
2516
  #. translators: the backticks are Markdown! Preserve them as-is!
2517
 
2518
- #: inc/views/admin/metaboxes/social-metabox.php:331
2519
  msgid "Add `article:published_time` to posts?"
2520
  msgstr ""
2521
 
2522
  #. translators: the backticks are Markdown! Preserve them as-is!
2523
 
2524
- #: inc/views/admin/metaboxes/social-metabox.php:341
2525
  msgid "Add `article:modified_time` to posts?"
2526
  msgstr ""
2527
 
@@ -2624,50 +2697,60 @@ msgstr ""
2624
  msgid "Remove term type prefixes from title?"
2625
  msgstr ""
2626
 
2627
- #: inc/views/admin/metaboxes/webmaster-metabox.php:24
2628
- msgid "Webmaster Integration Settings"
2629
- msgstr ""
2630
-
2631
  #: inc/views/admin/metaboxes/webmaster-metabox.php:26
2632
- msgid "When adding your website to Google, Bing and other Webmaster Tools, you'll be asked to add a code or file to your website for verification purposes. These options will help you easily integrate those codes."
2633
- msgstr ""
2634
-
2635
- #: inc/views/admin/metaboxes/webmaster-metabox.php:27
2636
- msgid "Verifying your website has no SEO value whatsoever. But you might gain added benefits such as search ranking insights to help you improve your website's content."
2637
- msgstr ""
2638
-
2639
- #: inc/views/admin/metaboxes/webmaster-metabox.php:34
2640
  msgid "Google Search Console Verification Code"
2641
  msgstr ""
2642
 
2643
- #: inc/views/admin/metaboxes/webmaster-metabox.php:38
2644
  msgid "Get the Google verification code."
2645
  msgstr ""
2646
 
2647
- #: inc/views/admin/metaboxes/webmaster-metabox.php:49
2648
  msgid "Bing Webmaster Verification Code"
2649
  msgstr ""
2650
 
2651
- #: inc/views/admin/metaboxes/webmaster-metabox.php:53
2652
  msgid "Get the Bing verification code."
2653
  msgstr ""
2654
 
2655
- #: inc/views/admin/metaboxes/webmaster-metabox.php:64
2656
  msgid "Yandex Webmaster Verification Code"
2657
  msgstr ""
2658
 
2659
- #: inc/views/admin/metaboxes/webmaster-metabox.php:68
2660
  msgid "Get the Yandex verification code."
2661
  msgstr ""
2662
 
2663
- #: inc/views/admin/metaboxes/webmaster-metabox.php:79
 
 
 
 
 
 
 
 
 
 
2664
  msgid "Pinterest Analytics Verification Code"
2665
  msgstr ""
2666
 
2667
- #: inc/views/admin/metaboxes/webmaster-metabox.php:83
2668
  msgid "Get the Pinterest verification code."
2669
  msgstr ""
2670
 
 
 
 
 
 
 
 
 
 
 
 
 
2671
  #: inc/views/admin/seo-settings-wrap.php:20
2672
  #: inc/views/admin/seo-settings-wrap.php:38
2673
  msgid "Save Settings"
@@ -2694,7 +2777,7 @@ msgid "Remove the blog name?"
2694
  msgstr ""
2695
 
2696
  #: inc/views/edit/seo-settings-singular.php:136
2697
- msgid "For the homepage, this option must be managed at the SEO Settings."
2698
  msgstr ""
2699
 
2700
  #: inc/views/edit/seo-settings-singular.php:143
@@ -2709,8 +2792,8 @@ msgid "Link following"
2709
  msgstr ""
2710
 
2711
  #: inc/views/edit/seo-settings-singular.php:222
2712
- #: inc/views/edit/seo-settings-tt.php:279 inc/views/list/quick-post.php:43
2713
- #: inc/views/list/quick-term.php:43
2714
  msgid "Canonical URL"
2715
  msgstr ""
2716
 
@@ -2730,8 +2813,8 @@ msgstr ""
2730
  #. translators: %s = default option value
2731
 
2732
  #: inc/views/edit/seo-settings-singular.php:289
2733
- #: inc/views/edit/seo-settings-tt.php:316 inc/views/list/quick-post.php:60
2734
- #: inc/views/list/quick-term.php:60
2735
  msgid "Default (%s)"
2736
  msgstr ""
2737
 
@@ -2748,8 +2831,8 @@ msgid "Exclude this page from all archive queries on this site."
2748
  msgstr ""
2749
 
2750
  #: inc/views/edit/seo-settings-singular.php:347
2751
- #: inc/views/edit/seo-settings-tt.php:332 inc/views/list/quick-post.php:73
2752
- #: inc/views/list/quick-term.php:73
2753
  msgid "301 Redirect URL"
2754
  msgstr ""
2755
 
@@ -2778,8 +2861,8 @@ msgstr ""
2778
  msgid "Social SEO Settings"
2779
  msgstr ""
2780
 
2781
- #: inc/views/edit/seo-settings-tt.php:272 inc/views/list/bulk-post.php:40
2782
- #: inc/views/list/quick-post.php:40 inc/views/list/quick-term.php:40
2783
  msgid "Visibility SEO Settings"
2784
  msgstr ""
2785
 
@@ -2787,11 +2870,11 @@ msgstr ""
2787
  msgid "These directives may urge robots not to display, follow links on, or create a cached copy of this term."
2788
  msgstr ""
2789
 
2790
- #: inc/views/list/bulk-post.php:53
2791
  msgid "&mdash; No Change &mdash;"
2792
  msgstr ""
2793
 
2794
- #: inc/views/list/bulk-post.php:54
2795
  msgid "Default (unknown)"
2796
  msgstr ""
2797
 
@@ -2851,6 +2934,10 @@ msgstr ""
2851
  #: inc/views/templates/inpost/primary-term-selector.php:28
2852
  msgid "The buttons below are for primary %s selection."
2853
  msgstr ""
 
 
 
 
2854
  #. Plugin Name of the plugin/theme
2855
  msgid "The SEO Framework"
2856
  msgstr ""
1
+ # Copyright (C) 2020 The SEO Framework
2
  # This file is distributed under the same license as the The SEO Framework package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: The SEO Framework 4.0.5\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/autodescription\n"
7
+ "POT-Creation-Date: 2020-03-04 04:17:22+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
  #. translators: %s = Version number, surrounded in markdown-backticks.
16
 
17
+ #: bootstrap/upgrade.php:255
18
  msgid "Thank you for updating The SEO Framework! Your website has been upgraded successfully to use The SEO Framework at database version `%s`."
19
  msgstr ""
20
 
21
+ #: bootstrap/upgrade.php:266
22
+ msgid "Thank you for installing The SEO Framework! Your website is now optimized for search and social sharing, automatically. We hope you enjoy our free plugin. Good luck with your site!"
23
  msgstr ""
24
 
25
  #. translators: %s = Link, markdown.
26
 
27
+ #: bootstrap/upgrade.php:275
28
  msgid "The SEO Framework only identifies itself rarely during plugin upgrades. We'd like to use this opportunity to highlight our [plugin setup guide](%s)."
29
  msgstr ""
30
 
31
+ #: bootstrap/upgrade.php:421
32
  msgid "Twitter Photo Cards have been deprecated. Your site now uses Summary Cards when applicable."
33
  msgstr ""
34
 
35
+ #: bootstrap/upgrade.php:451
36
  msgid "The previous sitemap timestamp settings have been converted into new global timestamp settings."
37
  msgstr ""
38
 
39
+ #: bootstrap/upgrade.php:574
40
  msgid "A cronjob is now used to ping search engines, and it alerts them to changes in your sitemap."
41
  msgstr ""
42
 
43
+ #: bootstrap/upgrade.php:589
44
  msgid "The positions in the \"Meta Title Additions Location\" setting for the homepage have been reversed, left to right, but the output has not been changed. If you must downgrade for some reason, remember to switch the location back again."
45
  msgstr ""
46
 
132
  msgid "There has been an error redirecting. Refresh the page or follow [this link](%s)."
133
  msgstr ""
134
 
135
+ #: inc/classes/admin-init.class.php:640 inc/classes/admin-init.class.php:701
136
  msgid "Image could not be processed."
137
  msgstr ""
138
 
144
  msgid "SEO"
145
  msgstr ""
146
 
147
+ #: inc/classes/admin-pages.class.php:198
148
  msgid "SEO settings are saved, and the caches have been flushed."
149
  msgstr ""
150
 
151
+ #: inc/classes/admin-pages.class.php:203
152
  msgid "No SEO settings were changed, but the caches have been flushed."
153
  msgstr ""
154
 
155
+ #: inc/classes/admin-pages.class.php:208
156
  msgid "SEO settings are reset, and the caches have been flushed."
157
  msgstr ""
158
 
159
+ #: inc/classes/admin-pages.class.php:213
160
  msgid "An unknown error occurred saving SEO settings."
161
  msgstr ""
162
 
163
+ #: inc/classes/admin-pages.class.php:236
164
  msgid "Multiple SEO tools have been detected. You should only use one."
165
  msgstr ""
166
 
167
+ #: inc/classes/admin-pages.class.php:389
168
  msgid "Dismiss this notice"
169
  msgstr ""
170
 
171
+ #: inc/classes/admin-pages.class.php:1048
172
+ #: inc/classes/bridges/scripts.class.php:624
173
  msgctxt "Button hover"
174
  msgid "Select social image"
175
  msgstr ""
176
 
177
+ #: inc/classes/admin-pages.class.php:1059
178
+ #: inc/classes/bridges/scripts.class.php:623
179
  msgid "Select Image"
180
  msgstr ""
181
 
182
+ #: inc/classes/admin-pages.class.php:1105
183
+ #: inc/classes/bridges/scripts.class.php:632
184
  msgid "Select Logo"
185
  msgstr ""
186
 
187
+ #: inc/classes/admin-pages.class.php:1155
188
  msgid "Click to change the counter type"
189
  msgstr ""
190
 
191
  #. translators: %s = number
192
 
193
+ #: inc/classes/admin-pages.class.php:1158
194
  msgid "Characters Used: %s"
195
  msgstr ""
196
 
197
+ #: inc/classes/bridges/postsettings.class.php:74
198
+ #: inc/classes/bridges/postsettings.class.php:82
199
  msgid "Homepage SEO Settings"
200
  msgstr ""
201
 
202
+ #: inc/classes/bridges/postsettings.class.php:76
203
  msgid "The SEO Settings may take precedence over these settings."
204
  msgstr ""
205
 
206
  #. translators: %s = Post Type label
207
 
208
+ #: inc/classes/bridges/postsettings.class.php:86
209
  msgid "%s SEO Settings"
210
  msgstr ""
211
 
218
  msgstr ""
219
 
220
  #: inc/classes/bridges/scripts.class.php:418
221
+ #: inc/classes/bridges/scripts.class.php:487
222
+ #: inc/classes/generate-title.class.php:1179
223
  msgid "Private: %s"
224
  msgstr ""
225
 
226
  #: inc/classes/bridges/scripts.class.php:420
227
+ #: inc/classes/bridges/scripts.class.php:489
228
+ #: inc/classes/generate-title.class.php:1164
229
  msgid "Protected: %s"
230
  msgstr ""
231
 
233
  #. Current taxonomy term
234
  #. translators: 1 = 'Assessment(s)', 2 = A list of assessments.
235
 
236
+ #: inc/classes/bridges/scripts.class.php:541
237
+ #: inc/classes/generate-title.class.php:769
238
+ #: inc/classes/generate-title.class.php:836
239
  #: inc/classes/interpreters/seobar.class.php:342
240
  msgid "%1$s: %2$s"
241
  msgstr ""
242
 
243
+ #: inc/classes/bridges/scripts.class.php:625
244
  msgid "Change Image"
245
  msgstr ""
246
 
247
+ #: inc/classes/bridges/scripts.class.php:626
248
  msgid "Remove Image"
249
  msgstr ""
250
 
251
+ #: inc/classes/bridges/scripts.class.php:627
252
  msgid "Remove selected social image"
253
  msgstr ""
254
 
255
+ #: inc/classes/bridges/scripts.class.php:628
256
  msgctxt "Frame title"
257
  msgid "Select Social Image"
258
  msgstr ""
259
 
260
+ #: inc/classes/bridges/scripts.class.php:629
261
+ #: inc/classes/bridges/scripts.class.php:638
262
  msgid "Use this image"
263
  msgstr ""
264
 
265
+ #: inc/classes/bridges/scripts.class.php:634
266
  msgid "Change Logo"
267
  msgstr ""
268
 
269
+ #: inc/classes/bridges/scripts.class.php:635
270
  msgid "Remove Logo"
271
  msgstr ""
272
 
273
+ #: inc/classes/bridges/scripts.class.php:636
274
  msgid "Unset selected logo"
275
  msgstr ""
276
 
277
+ #: inc/classes/bridges/scripts.class.php:637
278
  msgctxt "Frame title"
279
  msgid "Select Logo"
280
  msgstr ""
281
 
282
  #. translators: %s = term name
283
 
284
+ #: inc/classes/bridges/scripts.class.php:897
285
  msgid "Select Primary %s"
286
  msgstr ""
287
 
288
  #. translators: %s = term name
289
 
290
+ #: inc/classes/bridges/scripts.class.php:902
291
  msgid "Make primary %s"
292
  msgstr ""
293
 
294
  #. translators: %s = term name
295
 
296
+ #: inc/classes/bridges/scripts.class.php:904
297
  msgid "Primary %s"
298
  msgstr ""
299
 
300
  #. translators: Pixel counter. 1: number (value), 2: number (guideline)
301
 
302
+ #: inc/classes/bridges/scripts.class.php:999
303
  msgid "%1$d out of %2$d pixels are used."
304
  msgstr ""
305
 
349
  #. translators: 1 = An assessment, 2 = Disclaimer, e.g. "take it with a grain
350
  #. of salt"
351
 
352
+ #: inc/classes/builders/seobar-page.class.php:149
353
+ #: inc/classes/builders/seobar-page.class.php:364
354
+ #: inc/classes/builders/seobar-term.class.php:164
355
+ #: inc/classes/builders/seobar-term.class.php:355
356
  msgid "%1$s (%2$s)"
357
  msgstr ""
358
 
359
+ #: inc/classes/builders/seobar-page.class.php:150
360
+ #: inc/classes/builders/seobar-page.class.php:365
361
+ #: inc/classes/builders/seobar-term.class.php:165
362
+ #: inc/classes/builders/seobar-term.class.php:356
363
  msgid "Estimated from the number of characters found. The pixel counter asserts the true length."
364
  msgstr ""
365
 
366
+ #: inc/classes/builders/seobar-page.class.php:153
367
+ #: inc/classes/builders/seobar-term.class.php:168
368
  msgid "No title could be fetched."
369
  msgstr ""
370
 
371
+ #. translators: %s = "Untitled"
372
+
373
+ #: inc/classes/builders/seobar-page.class.php:156
374
+ #: inc/classes/builders/seobar-term.class.php:171
375
+ msgid "No title could be fetched, \"%s\" is used instead."
376
  msgstr ""
377
 
378
+ #: inc/classes/builders/seobar-page.class.php:159
379
  msgid "A page protection state is added which increases the length."
380
  msgstr ""
381
 
382
+ #: inc/classes/builders/seobar-page.class.php:161
383
+ #: inc/classes/builders/seobar-term.class.php:176
384
  msgid "It's not branded. Search engines may ignore your title."
385
  msgstr ""
386
 
387
+ #: inc/classes/builders/seobar-page.class.php:162
388
+ #: inc/classes/builders/seobar-term.class.php:177
389
  msgid "It's manually branded."
390
  msgstr ""
391
 
392
+ #: inc/classes/builders/seobar-page.class.php:163
393
+ #: inc/classes/builders/seobar-term.class.php:178
394
  msgid "It's automatically branded."
395
  msgstr ""
396
 
397
+ #: inc/classes/builders/seobar-page.class.php:165
398
+ #: inc/classes/builders/seobar-term.class.php:180
399
  msgid "The blog name is found multiple times."
400
  msgstr ""
401
 
402
+ #: inc/classes/builders/seobar-page.class.php:166
403
+ #: inc/classes/builders/seobar-page.class.php:379
404
+ #: inc/classes/builders/seobar-term.class.php:181
405
+ #: inc/classes/builders/seobar-term.class.php:367
406
+ msgid "Markup syntax was found that isn't transformed. Consider replacing it with static input."
407
+ msgstr ""
408
+
409
+ #: inc/classes/builders/seobar-page.class.php:169
410
+ #: inc/classes/builders/seobar-term.class.php:184
411
  msgid "Incomplete."
412
  msgstr ""
413
 
414
+ #: inc/classes/builders/seobar-page.class.php:170
415
+ #: inc/classes/builders/seobar-term.class.php:185
416
  msgid "The branding is duplicated."
417
  msgstr ""
418
 
419
+ #: inc/classes/builders/seobar-page.class.php:171
420
+ #: inc/classes/builders/seobar-term.class.php:186
421
  msgid "Not branded."
422
  msgstr ""
423
 
424
+ #: inc/classes/builders/seobar-page.class.php:172
425
+ #: inc/classes/builders/seobar-page.class.php:385
426
+ #: inc/classes/builders/seobar-term.class.php:187
427
+ #: inc/classes/builders/seobar-term.class.php:373
428
+ msgid "Found markup syntax."
429
+ msgstr ""
430
+
431
+ #: inc/classes/builders/seobar-page.class.php:176
432
+ #: inc/classes/builders/seobar-term.class.php:191
433
  msgctxt "Title Generated"
434
  msgid "TG"
435
  msgstr ""
436
 
437
+ #: inc/classes/builders/seobar-page.class.php:177
438
+ #: inc/classes/builders/seobar-term.class.php:192
439
  msgid "Title, generated"
440
  msgstr ""
441
 
442
+ #: inc/classes/builders/seobar-page.class.php:179
443
+ #: inc/classes/builders/seobar-page.class.php:392
444
+ #: inc/classes/builders/seobar-term.class.php:194
445
+ #: inc/classes/builders/seobar-term.class.php:380
446
  msgid "Automatically generated."
447
  msgstr ""
448
 
449
+ #: inc/classes/builders/seobar-page.class.php:181
450
+ #: inc/classes/builders/seobar-term.class.php:196
451
  msgid "It's built using the page title."
452
  msgstr ""
453
 
454
+ #: inc/classes/builders/seobar-page.class.php:185
455
+ #: inc/classes/builders/seobar-term.class.php:200
456
  msgctxt "Title"
457
  msgid "T"
458
  msgstr ""
459
 
460
+ #: inc/classes/builders/seobar-page.class.php:186
461
+ #: inc/classes/builders/seobar-term.class.php:201
462
  msgid "Title"
463
  msgstr ""
464
 
465
+ #: inc/classes/builders/seobar-page.class.php:188
466
+ #: inc/classes/builders/seobar-page.class.php:410
467
  msgid "Obtained from page SEO meta input."
468
  msgstr ""
469
 
470
+ #: inc/classes/builders/seobar-page.class.php:190
471
+ #: inc/classes/builders/seobar-page.class.php:412
472
  msgid "It's built from page SEO meta input."
473
  msgstr ""
474
 
475
+ #: inc/classes/builders/seobar-page.class.php:211
476
  msgid "The title inputted at the SEO Settings screen is used."
477
  msgstr ""
478
 
479
+ #: inc/classes/builders/seobar-page.class.php:213
480
  msgid "The title inputted at the Edit Page screen is used."
481
  msgstr ""
482
 
483
+ #: inc/classes/builders/seobar-page.class.php:230
484
  msgid "The title is built from the blog name."
485
  msgstr ""
486
 
487
+ #: inc/classes/builders/seobar-page.class.php:373
488
  msgid "There is no usable content, so no description could be generated."
489
  msgstr ""
490
 
491
+ #: inc/classes/builders/seobar-page.class.php:374
492
  msgid "A foreign page builder is used, so no description is generated."
493
  msgstr ""
494
 
495
+ #: inc/classes/builders/seobar-page.class.php:375
496
  msgid "The page is protected, so no description is generated."
497
  msgstr ""
498
 
499
+ #: inc/classes/builders/seobar-page.class.php:376
500
  msgid "It's built using the excerpt field."
501
  msgstr ""
502
 
503
  #. translators: %s = list of duplicated words
504
 
505
+ #: inc/classes/builders/seobar-page.class.php:378
506
+ #: inc/classes/builders/seobar-term.class.php:366
507
  msgid "Found duplicated words: %s"
508
  msgstr ""
509
 
510
+ #: inc/classes/builders/seobar-page.class.php:382
511
+ #: inc/classes/builders/seobar-page.class.php:401
512
+ #: inc/classes/builders/seobar-term.class.php:370
513
+ #: inc/classes/builders/seobar-term.class.php:389
514
  msgid "Empty."
515
  msgstr ""
516
 
517
+ #: inc/classes/builders/seobar-page.class.php:383
518
+ #: inc/classes/builders/seobar-term.class.php:371
519
  msgid "Found duplicated words."
520
  msgstr ""
521
 
522
+ #: inc/classes/builders/seobar-page.class.php:384
523
+ #: inc/classes/builders/seobar-term.class.php:372
524
  msgid "Found too many duplicated words."
525
  msgstr ""
526
 
527
+ #: inc/classes/builders/seobar-page.class.php:389
528
+ #: inc/classes/builders/seobar-term.class.php:377
529
  msgctxt "Description Generated"
530
  msgid "DG"
531
  msgstr ""
532
 
533
+ #: inc/classes/builders/seobar-page.class.php:390
534
+ #: inc/classes/builders/seobar-term.class.php:378
535
  msgid "Description, generated"
536
  msgstr ""
537
 
538
+ #: inc/classes/builders/seobar-page.class.php:394
539
  msgid "It's built using the page content."
540
  msgstr ""
541
 
542
+ #: inc/classes/builders/seobar-page.class.php:398
543
+ #: inc/classes/builders/seobar-page.class.php:407
544
+ #: inc/classes/builders/seobar-term.class.php:386
545
+ #: inc/classes/builders/seobar-term.class.php:395
546
  msgctxt "Description"
547
  msgid "D"
548
  msgstr ""
549
 
550
+ #: inc/classes/builders/seobar-page.class.php:399
551
+ #: inc/classes/builders/seobar-page.class.php:408
552
+ #: inc/classes/builders/seobar-term.class.php:387
553
+ #: inc/classes/builders/seobar-term.class.php:396
554
  msgid "Description"
555
  msgstr ""
556
 
557
+ #: inc/classes/builders/seobar-page.class.php:403
558
  msgid "No page description is set."
559
  msgstr ""
560
 
561
+ #: inc/classes/builders/seobar-page.class.php:433
562
  msgid "The description inputted at the SEO Settings screen is used."
563
  msgstr ""
564
 
565
+ #: inc/classes/builders/seobar-page.class.php:435
566
  msgid "The description inputted at the Edit Page screen is used."
567
  msgstr ""
568
 
569
  #. translators: 1: Word found, 2: Occurrences
570
 
571
+ #: inc/classes/builders/seobar-page.class.php:493
572
+ #: inc/classes/builders/seobar-term.class.php:463
573
  msgid "&#8220;%1$s&#8221; is used %2$d times."
574
  msgstr ""
575
 
576
+ #: inc/classes/builders/seobar-page.class.php:570
577
+ #: inc/classes/builders/seobar-page.class.php:727
578
+ #: inc/classes/builders/seobar-page.class.php:858
579
+ #: inc/classes/builders/seobar-term.class.php:540
580
+ #: inc/classes/builders/seobar-term.class.php:694
581
+ #: inc/classes/builders/seobar-term.class.php:814
582
  msgid "The robots.txt file is nonstandard, and may still direct search engines differently."
583
  msgstr ""
584
 
585
+ #: inc/classes/builders/seobar-page.class.php:571
586
+ #: inc/classes/builders/seobar-page.class.php:728
587
+ #: inc/classes/builders/seobar-page.class.php:859
588
+ #: inc/classes/builders/seobar-term.class.php:541
589
+ #: inc/classes/builders/seobar-term.class.php:695
590
+ #: inc/classes/builders/seobar-term.class.php:815
591
  msgid "WordPress discourages crawling via the Reading Settings."
592
  msgstr ""
593
 
594
+ #: inc/classes/builders/seobar-page.class.php:572
595
+ #: inc/classes/builders/seobar-term.class.php:542
596
  msgid "Indexing is discouraged for the whole site at the SEO Settings screen."
597
  msgstr ""
598
 
599
+ #: inc/classes/builders/seobar-page.class.php:573
600
  msgid "Indexing is discouraged for this post type at the SEO Settings screen."
601
  msgstr ""
602
 
603
+ #: inc/classes/builders/seobar-page.class.php:574
604
  msgid "The page is protected, so indexing is discouraged."
605
  msgstr ""
606
 
607
+ #: inc/classes/builders/seobar-page.class.php:575
608
  msgid "The page SEO meta input overrides the indexing state."
609
  msgstr ""
610
 
611
+ #: inc/classes/builders/seobar-page.class.php:576
612
+ #: inc/classes/builders/seobar-term.class.php:549
613
  msgid "A custom canonical URL is set that points to another page."
614
  msgstr ""
615
 
616
+ #: inc/classes/builders/seobar-page.class.php:579
617
+ #: inc/classes/builders/seobar-page.class.php:735
618
+ #: inc/classes/builders/seobar-page.class.php:866
619
+ #: inc/classes/builders/seobar-term.class.php:552
620
+ #: inc/classes/builders/seobar-term.class.php:704
621
+ #: inc/classes/builders/seobar-term.class.php:824
622
  msgid "WordPress overrides the robots directive."
623
  msgstr ""
624
 
625
+ #: inc/classes/builders/seobar-page.class.php:580
626
  msgid "The page is protected."
627
  msgstr ""
628
 
629
+ #: inc/classes/builders/seobar-page.class.php:581
630
+ #: inc/classes/builders/seobar-page.class.php:736
631
+ #: inc/classes/builders/seobar-page.class.php:867
632
  msgid "The page is not published."
633
  msgstr ""
634
 
635
+ #: inc/classes/builders/seobar-page.class.php:582
636
+ #: inc/classes/builders/seobar-term.class.php:555
637
  msgid "The canonical URL points to another page."
638
  msgstr ""
639
 
640
+ #: inc/classes/builders/seobar-page.class.php:586
641
+ #: inc/classes/builders/seobar-page.class.php:595
642
+ #: inc/classes/builders/seobar-page.class.php:604
643
+ #: inc/classes/builders/seobar-term.class.php:559
644
+ #: inc/classes/builders/seobar-term.class.php:568
645
  msgctxt "Indexing"
646
  msgid "I"
647
  msgstr ""
648
 
649
+ #: inc/classes/builders/seobar-page.class.php:587
650
+ #: inc/classes/builders/seobar-page.class.php:596
651
+ #: inc/classes/builders/seobar-page.class.php:605
652
+ #: inc/classes/builders/seobar-term.class.php:560
653
+ #: inc/classes/builders/seobar-term.class.php:569
654
  #: inc/views/admin/metaboxes/robots-metabox.php:54
655
  #: inc/views/edit/seo-settings-singular.php:196
656
  #: inc/views/edit/seo-settings-tt.php:60 inc/views/list/bulk-post.php:19
658
  msgid "Indexing"
659
  msgstr ""
660
 
661
+ #: inc/classes/builders/seobar-page.class.php:589
662
  msgid "Page may be indexed."
663
  msgstr ""
664
 
665
+ #: inc/classes/builders/seobar-page.class.php:591
666
+ #: inc/classes/builders/seobar-term.class.php:564
667
  msgid "The robots meta tag allows indexing."
668
  msgstr ""
669
 
670
+ #: inc/classes/builders/seobar-page.class.php:598
671
  msgid "Page may not be indexed."
672
  msgstr ""
673
 
674
+ #: inc/classes/builders/seobar-page.class.php:600
675
+ #: inc/classes/builders/seobar-term.class.php:573
676
  msgid "The robots meta tag does not allow indexing."
677
  msgstr ""
678
 
679
+ #: inc/classes/builders/seobar-page.class.php:607
680
+ #: inc/classes/builders/seobar-page.class.php:761
681
+ #: inc/classes/builders/seobar-page.class.php:892
682
  msgid "Page is invisible."
683
  msgstr ""
684
 
685
+ #: inc/classes/builders/seobar-page.class.php:609
686
+ #: inc/classes/builders/seobar-page.class.php:763
687
+ #: inc/classes/builders/seobar-page.class.php:894
688
  msgid "This page isn't published and can't be found publicly."
689
  msgstr ""
690
 
691
+ #: inc/classes/builders/seobar-page.class.php:664
692
  msgid "Indexing is discouraged for the homepage at the SEO Settings screen."
693
  msgstr ""
694
 
695
+ #: inc/classes/builders/seobar-page.class.php:729
696
+ #: inc/classes/builders/seobar-term.class.php:696
697
  msgid "Link following is discouraged for the whole site at the SEO Settings screen."
698
  msgstr ""
699
 
700
+ #: inc/classes/builders/seobar-page.class.php:730
701
  msgid "Link following is discouraged for this post type at the SEO Settings screen."
702
  msgstr ""
703
 
704
+ #: inc/classes/builders/seobar-page.class.php:731
705
  msgid "The page SEO meta input overrides the link following state."
706
  msgstr ""
707
 
708
+ #: inc/classes/builders/seobar-page.class.php:732
709
  msgid "The page may not be indexed, this may also discourage link following."
710
  msgstr ""
711
 
712
+ #: inc/classes/builders/seobar-page.class.php:740
713
+ #: inc/classes/builders/seobar-page.class.php:749
714
+ #: inc/classes/builders/seobar-page.class.php:758
715
+ #: inc/classes/builders/seobar-term.class.php:708
716
+ #: inc/classes/builders/seobar-term.class.php:717
717
  msgctxt "Following"
718
  msgid "F"
719
  msgstr ""
720
 
721
+ #: inc/classes/builders/seobar-page.class.php:741
722
+ #: inc/classes/builders/seobar-page.class.php:750
723
+ #: inc/classes/builders/seobar-page.class.php:759
724
+ #: inc/classes/builders/seobar-term.class.php:709
725
+ #: inc/classes/builders/seobar-term.class.php:718
726
  #: inc/views/admin/metaboxes/robots-metabox.php:60
727
  #: inc/views/list/quick-term.php:26
728
  msgid "Following"
729
  msgstr ""
730
 
731
+ #: inc/classes/builders/seobar-page.class.php:743
732
  msgid "Page links may be followed."
733
  msgstr ""
734
 
735
+ #: inc/classes/builders/seobar-page.class.php:745
736
+ #: inc/classes/builders/seobar-term.class.php:713
737
  msgid "The robots meta tag allows link following."
738
  msgstr ""
739
 
740
+ #: inc/classes/builders/seobar-page.class.php:752
741
  msgid "Page links may not be followed."
742
  msgstr ""
743
 
744
+ #: inc/classes/builders/seobar-page.class.php:754
745
+ #: inc/classes/builders/seobar-term.class.php:722
746
  msgid "The robots meta tag does not allow link following."
747
  msgstr ""
748
 
749
+ #: inc/classes/builders/seobar-page.class.php:806
750
  msgid "Link following is discouraged for the homepage at the SEO Settings screen."
751
  msgstr ""
752
 
753
+ #: inc/classes/builders/seobar-page.class.php:860
754
+ #: inc/classes/builders/seobar-term.class.php:816
755
  msgid "Archiving is discouraged for the whole site at the SEO Settings screen."
756
  msgstr ""
757
 
758
+ #: inc/classes/builders/seobar-page.class.php:861
759
  msgid "Archiving is discouraged for this post type at the SEO Settings screen."
760
  msgstr ""
761
 
762
+ #: inc/classes/builders/seobar-page.class.php:862
763
  msgid "The page SEO meta input overrides the archiving state."
764
  msgstr ""
765
 
766
+ #: inc/classes/builders/seobar-page.class.php:863
767
  msgid "The page may not be indexed, this may also discourage archiving."
768
  msgstr ""
769
 
770
+ #: inc/classes/builders/seobar-page.class.php:871
771
+ #: inc/classes/builders/seobar-page.class.php:880
772
+ #: inc/classes/builders/seobar-page.class.php:889
773
+ #: inc/classes/builders/seobar-term.class.php:828
774
+ #: inc/classes/builders/seobar-term.class.php:837
775
  msgctxt "Archiving"
776
  msgid "A"
777
  msgstr ""
778
 
779
+ #: inc/classes/builders/seobar-page.class.php:872
780
+ #: inc/classes/builders/seobar-page.class.php:881
781
+ #: inc/classes/builders/seobar-page.class.php:890
782
+ #: inc/classes/builders/seobar-term.class.php:829
783
+ #: inc/classes/builders/seobar-term.class.php:838
784
  #: inc/views/admin/metaboxes/robots-metabox.php:66
785
  #: inc/views/edit/seo-settings-singular.php:212
786
  #: inc/views/edit/seo-settings-tt.php:86 inc/views/list/bulk-post.php:33
788
  msgid "Archiving"
789
  msgstr ""
790
 
791
+ #: inc/classes/builders/seobar-page.class.php:874
792
  msgid "Page may be archived."
793
  msgstr ""
794
 
795
+ #: inc/classes/builders/seobar-page.class.php:876
796
+ #: inc/classes/builders/seobar-term.class.php:833
797
  msgid "The robots meta tag allows archiving."
798
  msgstr ""
799
 
800
+ #: inc/classes/builders/seobar-page.class.php:883
801
  msgid "Page may not be archived."
802
  msgstr ""
803
 
804
+ #: inc/classes/builders/seobar-page.class.php:885
805
+ #: inc/classes/builders/seobar-term.class.php:842
806
  msgid "The robots meta tag does not allow archiving."
807
  msgstr ""
808
 
809
+ #: inc/classes/builders/seobar-page.class.php:937
810
  msgid "Archiving is discouraged for the homepage at the SEO Settings screen."
811
  msgstr ""
812
 
813
+ #: inc/classes/builders/seobar-page.class.php:988
814
+ #: inc/classes/builders/seobar-page.class.php:1004
815
+ #: inc/classes/builders/seobar-term.class.php:932
816
+ #: inc/classes/builders/seobar-term.class.php:948
817
  msgctxt "Redirect"
818
  msgid "R"
819
  msgstr ""
820
 
821
+ #: inc/classes/builders/seobar-page.class.php:989
822
+ #: inc/classes/builders/seobar-page.class.php:1005
823
+ #: inc/classes/builders/seobar-term.class.php:933
824
+ #: inc/classes/builders/seobar-term.class.php:949
825
  msgid "Redirection"
826
  msgstr ""
827
 
828
+ #: inc/classes/builders/seobar-page.class.php:991
829
  msgid "Page does not redirect visitors."
830
  msgstr ""
831
 
832
+ #: inc/classes/builders/seobar-page.class.php:993
833
+ #: inc/classes/builders/seobar-term.class.php:937
834
  msgid "All visitors and crawlers may access this page."
835
  msgstr ""
836
 
837
+ #: inc/classes/builders/seobar-page.class.php:1007
838
  msgid "Page redirects visitors."
839
  msgstr ""
840
 
841
+ #: inc/classes/builders/seobar-page.class.php:1009
842
+ #: inc/classes/builders/seobar-term.class.php:953
843
  msgid "All visitors and crawlers are being redirected. So, no other SEO enhancements are effective."
844
  msgstr ""
845
 
846
+ #: inc/classes/builders/seobar-term.class.php:174
847
  msgid "A term label prefix is automatically added which increases the length."
848
  msgstr ""
849
 
850
+ #: inc/classes/builders/seobar-term.class.php:203
851
+ #: inc/classes/builders/seobar-term.class.php:398
852
  msgid "Obtained from term SEO meta input."
853
  msgstr ""
854
 
855
+ #: inc/classes/builders/seobar-term.class.php:205
856
+ #: inc/classes/builders/seobar-term.class.php:400
857
  msgid "It's built from term SEO meta input."
858
  msgstr ""
859
 
860
+ #: inc/classes/builders/seobar-term.class.php:364
861
  msgid "No description could be generated."
862
  msgstr ""
863
 
864
+ #: inc/classes/builders/seobar-term.class.php:382
865
  msgid "It's built using the term description field."
866
  msgstr ""
867
 
868
+ #: inc/classes/builders/seobar-term.class.php:391
869
  msgid "No term description is set."
870
  msgstr ""
871
 
872
+ #: inc/classes/builders/seobar-term.class.php:543
873
  msgid "Indexing is discouraged for all bound post types to this term at the SEO Settings screen."
874
  msgstr ""
875
 
876
+ #: inc/classes/builders/seobar-term.class.php:544
877
  msgid "Indexing is discouraged for all post categories at the SEO Settings screen."
878
  msgstr ""
879
 
880
+ #: inc/classes/builders/seobar-term.class.php:545
881
  msgid "Indexing is discouraged for all post tags at the SEO Settings screen."
882
  msgstr ""
883
 
884
+ #: inc/classes/builders/seobar-term.class.php:546
885
  msgid "The term SEO meta input overrides the indexing state."
886
  msgstr ""
887
 
888
+ #: inc/classes/builders/seobar-term.class.php:547
889
  msgid "No posts are attached to this term, so indexing is disabled."
890
  msgstr ""
891
 
892
+ #: inc/classes/builders/seobar-term.class.php:548
893
  msgid "No posts are attached to this term, so indexing should be disabled."
894
  msgstr ""
895
 
896
+ #: inc/classes/builders/seobar-term.class.php:553
897
  msgid "The term is empty."
898
  msgstr ""
899
 
900
+ #: inc/classes/builders/seobar-term.class.php:554
901
  msgid "The term is empty yet still indexed."
902
  msgstr ""
903
 
904
+ #: inc/classes/builders/seobar-term.class.php:562
905
  msgid "Term may be indexed."
906
  msgstr ""
907
 
908
+ #: inc/classes/builders/seobar-term.class.php:571
909
  msgid "Term may not be indexed."
910
  msgstr ""
911
 
912
+ #: inc/classes/builders/seobar-term.class.php:697
913
  msgid "Link following is discouraged for all bound post types to this term at the SEO Settings screen."
914
  msgstr ""
915
 
916
+ #: inc/classes/builders/seobar-term.class.php:698
917
  msgid "Link following is discouraged for all post categories at the SEO Settings screen."
918
  msgstr ""
919
 
920
+ #: inc/classes/builders/seobar-term.class.php:699
921
  msgid "Link following is discouraged for all post tags at the SEO Settings screen."
922
  msgstr ""
923
 
924
+ #: inc/classes/builders/seobar-term.class.php:700
925
  msgid "The term SEO meta input overrides the link following state."
926
  msgstr ""
927
 
928
+ #: inc/classes/builders/seobar-term.class.php:701
929
  msgid "The term may not be indexed, this may also discourage link following."
930
  msgstr ""
931
 
932
+ #: inc/classes/builders/seobar-term.class.php:711
933
  msgid "Term links may be followed."
934
  msgstr ""
935
 
936
+ #: inc/classes/builders/seobar-term.class.php:720
937
  msgid "Term links may not be followed."
938
  msgstr ""
939
 
940
+ #: inc/classes/builders/seobar-term.class.php:817
941
  msgid "Archiving is discouraged for all bound post types to this term at the SEO Settings screen."
942
  msgstr ""
943
 
944
+ #: inc/classes/builders/seobar-term.class.php:818
945
  msgid "Archiving is discouraged for all post categories at the SEO Settings screen."
946
  msgstr ""
947
 
948
+ #: inc/classes/builders/seobar-term.class.php:819
949
  msgid "Archiving is discouraged for all post tags at the SEO Settings screen."
950
  msgstr ""
951
 
952
+ #: inc/classes/builders/seobar-term.class.php:820
953
  msgid "The term SEO meta input overrides the archiving state."
954
  msgstr ""
955
 
956
+ #: inc/classes/builders/seobar-term.class.php:821
957
  msgid "The term may not be indexed, this may also discourage archiving."
958
  msgstr ""
959
 
960
+ #: inc/classes/builders/seobar-term.class.php:831
961
  msgid "Term may be archived."
962
  msgstr ""
963
 
964
+ #: inc/classes/builders/seobar-term.class.php:840
965
  msgid "Term may not be archived."
966
  msgstr ""
967
 
968
+ #: inc/classes/builders/seobar-term.class.php:935
969
  msgid "Term does not redirect visitors."
970
  msgstr ""
971
 
972
+ #: inc/classes/builders/seobar-term.class.php:951
973
  msgid "Term redirects visitors."
974
  msgstr ""
975
 
983
  msgid "Settings"
984
  msgstr ""
985
 
986
+ #: inc/classes/core.class.php:227
987
  msgctxt "About us"
988
  msgid "About"
989
  msgstr ""
990
 
991
+ #: inc/classes/core.class.php:232
992
  msgctxt "Plugin extensions"
993
  msgid "Extensions"
994
  msgstr ""
995
 
996
+ #: inc/classes/core.class.php:265
997
+ msgid "Get support"
998
+ msgstr ""
999
+
1000
+ #: inc/classes/core.class.php:272
1001
  msgid "View documentation"
1002
  msgstr ""
1003
 
1004
+ #: inc/classes/core.class.php:279
1005
  msgid "View API docs"
1006
  msgstr ""
1007
 
1008
+ #: inc/classes/core.class.php:286
1009
  msgctxt "Extension Manager is a product name; do not translate it."
1010
+ msgid "Get Extension Manager"
1011
  msgstr ""
1012
 
1013
  #. translators: 1: Function name, 2: 'Deprecated', 3: Plugin Version
1079
 
1080
  #. translators: Category archive title. 1: Category name
1081
 
1082
+ #: inc/classes/generate-title.class.php:758
1083
+ #: inc/classes/generate-title.class.php:783
1084
  msgid "Category: %s"
1085
  msgstr ""
1086
 
1087
  #. translators: Tag archive title. 1: Tag name
1088
 
1089
+ #: inc/classes/generate-title.class.php:762
1090
+ #: inc/classes/generate-title.class.php:787
1091
  msgid "Tag: %s"
1092
  msgstr ""
1093
 
 
 
 
 
 
1094
  #. translators: Author archive title. 1: Author name
1095
 
1096
+ #: inc/classes/generate-title.class.php:775
1097
+ #: inc/classes/generate-title.class.php:791
1098
  msgid "Author: %s"
1099
  msgstr ""
1100
 
1101
+ #: inc/classes/generate-title.class.php:777
1102
+ #: inc/classes/generate-title.class.php:839
1103
+ msgid "Archives"
1104
+ msgstr ""
1105
+
1106
+ #: inc/classes/generate-title.class.php:794
1107
  msgctxt "yearly archives date format"
1108
  msgid "Y"
1109
  msgstr ""
1110
 
1111
  #. translators: Yearly archive title. 1: Year
1112
 
1113
+ #: inc/classes/generate-title.class.php:796
1114
  msgid "Year: %s"
1115
  msgstr ""
1116
 
1117
+ #: inc/classes/generate-title.class.php:798
1118
  msgctxt "monthly archives date format"
1119
  msgid "F Y"
1120
  msgstr ""
1121
 
1122
  #. translators: Monthly archive title. 1: Month name and year
1123
 
1124
+ #: inc/classes/generate-title.class.php:800
1125
  msgid "Month: %s"
1126
  msgstr ""
1127
 
1128
+ #: inc/classes/generate-title.class.php:802
1129
  msgctxt "daily archives date format"
1130
  msgid "F j, Y"
1131
  msgstr ""
1132
 
1133
  #. translators: Daily archive title. 1: Date
1134
 
1135
+ #: inc/classes/generate-title.class.php:804
1136
  msgid "Day: %s"
1137
  msgstr ""
1138
 
1139
+ #: inc/classes/generate-title.class.php:808
1140
  msgctxt "post format archive title"
1141
  msgid "Asides"
1142
  msgstr ""
1143
 
1144
+ #: inc/classes/generate-title.class.php:810
1145
  msgctxt "post format archive title"
1146
  msgid "Galleries"
1147
  msgstr ""
1148
 
1149
+ #: inc/classes/generate-title.class.php:812
1150
  msgctxt "post format archive title"
1151
  msgid "Images"
1152
  msgstr ""
1153
 
1154
+ #: inc/classes/generate-title.class.php:814
1155
  msgctxt "post format archive title"
1156
  msgid "Videos"
1157
  msgstr ""
1158
 
1159
+ #: inc/classes/generate-title.class.php:816
1160
  msgctxt "post format archive title"
1161
  msgid "Quotes"
1162
  msgstr ""
1163
 
1164
+ #: inc/classes/generate-title.class.php:818
1165
  msgctxt "post format archive title"
1166
  msgid "Links"
1167
  msgstr ""
1168
 
1169
+ #: inc/classes/generate-title.class.php:820
1170
  msgctxt "post format archive title"
1171
  msgid "Statuses"
1172
  msgstr ""
1173
 
1174
+ #: inc/classes/generate-title.class.php:822
1175
  msgctxt "post format archive title"
1176
  msgid "Audio"
1177
  msgstr ""
1178
 
1179
+ #: inc/classes/generate-title.class.php:824
1180
  msgctxt "post format archive title"
1181
  msgid "Chats"
1182
  msgstr ""
1183
 
1184
  #. translators: Post type archive title. 1: Post type name
1185
 
1186
+ #: inc/classes/generate-title.class.php:829
1187
  msgid "Archives: %s"
1188
  msgstr ""
1189
 
1190
+ #: inc/classes/generate-title.class.php:986
1191
  msgid "Untitled"
1192
  msgstr ""
1193
 
1194
  #. translators: %s: search phrase
1195
 
1196
+ #: inc/classes/generate-title.class.php:998
1197
  msgid "Search Results for &#8220;%s&#8221;"
1198
  msgstr ""
1199
 
1200
+ #: inc/classes/generate-title.class.php:1113
1201
  msgid "Page %s"
1202
  msgstr ""
1203
 
1227
  msgstr ""
1228
 
1229
  #: inc/classes/profile.class.php:92
1230
+ #: inc/views/admin/metaboxes/social-metabox.php:182
1231
  msgctxt "Example Facebook Personal URL"
1232
  msgid "https://www.facebook.com/YourPersonalProfile"
1233
  msgstr ""
1237
  msgstr ""
1238
 
1239
  #: inc/classes/profile.class.php:99
1240
+ #: inc/views/admin/metaboxes/social-metabox.php:254
1241
  msgctxt "Twitter @username"
1242
  msgid "@your-personal-username"
1243
  msgstr ""
1244
 
1245
+ #: inc/classes/render.class.php:1162
1246
  msgid "by Sybre Waaijer"
1247
  msgstr ""
1248
 
1305
  msgid "This link will not be followed by search engines."
1306
  msgstr ""
1307
 
1308
+ #: inc/views/admin/metaboxes/feed-metabox.php:31
1309
+ msgid "Allow indexing of feeds?"
1310
+ msgstr ""
1311
+
1312
+ #: inc/views/admin/metaboxes/feed-metabox.php:32
1313
+ msgid "If this site publishes podcasts, enable this option. Otherwise, leave it disabled. Indexing feeds can cause search engines to crawl and index new pages slower; however, some podcast services require feeds to be indexable."
1314
+ msgstr ""
1315
+
1316
  #. translators: %s = Reading Settings URL. Links are in Markdown!
1317
 
1318
+ #: inc/views/admin/metaboxes/feed-metabox.php:48
1319
  msgid "Note: The feed is already converted into an excerpt through the [Reading Settings](%s)."
1320
  msgstr ""
1321
 
1322
+ #: inc/views/admin/metaboxes/feed-metabox.php:61
1323
  msgid "View the main feed."
1324
  msgstr ""
1325
 
1454
  msgstr ""
1455
 
1456
  #: inc/views/admin/metaboxes/general-metabox.php:247
1457
+ msgid "To improve performance, generated output can be stored in the database as transient cache."
1458
  msgstr ""
1459
 
1460
  #: inc/views/admin/metaboxes/general-metabox.php:248
1461
  msgid "If your website has thousands of pages, or if other forms of caching are used, you might wish to adjust these options."
1462
  msgstr ""
1463
 
1464
+ #: inc/views/admin/metaboxes/general-metabox.php:253
 
 
 
 
 
 
 
 
1465
  msgid "Enable sitemap generation cache?"
1466
  msgstr ""
1467
 
1468
+ #: inc/views/admin/metaboxes/general-metabox.php:254
1469
  msgid "Generating the sitemap can use a lot of server resources."
1470
  msgstr ""
1471
 
1472
+ #: inc/views/admin/metaboxes/general-metabox.php:265
1473
  msgid "Object Cache Settings"
1474
  msgstr ""
1475
 
1476
+ #: inc/views/admin/metaboxes/general-metabox.php:271
1477
  msgid "Enable object cache?"
1478
  msgstr ""
1479
 
1480
+ #: inc/views/admin/metaboxes/general-metabox.php:272
1481
  msgid "Object cache generally works faster than transient cache."
1482
  msgstr ""
1483
 
1484
+ #: inc/views/admin/metaboxes/general-metabox.php:273
1485
  msgid "An object cache handler has been detected. If you enable this option, you may wish to disable the Schema.org transient caching."
1486
  msgstr ""
1487
 
1488
+ #: inc/views/admin/metaboxes/general-metabox.php:283
1489
  msgid "Canonical URL Settings"
1490
  msgstr ""
1491
 
1492
+ #: inc/views/admin/metaboxes/general-metabox.php:285
1493
  msgid "The canonical URL meta tag urges search engines to go to the outputted URL."
1494
  msgstr ""
1495
 
1496
+ #: inc/views/admin/metaboxes/general-metabox.php:286
1497
  msgid "If the canonical URL meta tag represents the visited page, then the search engine will crawl the visited page. Otherwise, the search engine may go to the outputted URL."
1498
  msgstr ""
1499
 
1500
+ #: inc/views/admin/metaboxes/general-metabox.php:290
1501
  msgid "Scheme Settings"
1502
  msgstr ""
1503
 
1504
+ #: inc/views/admin/metaboxes/general-metabox.php:292
1505
  msgid "If your website is accessible via both HTTP as HTTPS, you may want to set this to HTTPS if not detected automatically. Secure connections are preferred by search engines."
1506
  msgstr ""
1507
 
1508
+ #: inc/views/admin/metaboxes/general-metabox.php:294
1509
  msgctxt "= Detect Automatically, HTTPS, HTTP"
1510
  msgid "Preferred canonical URL scheme:"
1511
  msgstr ""
1512
 
1513
  #. translators: %s = HTTP or HTTPS
1514
 
1515
+ #: inc/views/admin/metaboxes/general-metabox.php:302
1516
  msgid "Detect automatically (%s)"
1517
  msgstr ""
1518
 
1519
+ #: inc/views/admin/metaboxes/general-metabox.php:316
1520
  msgid "Link Relationship Settings"
1521
  msgstr ""
1522
 
1523
+ #: inc/views/admin/metaboxes/general-metabox.php:318
1524
  msgid "Some search engines look for relations between the content of your pages. If you have pagination on a post or page, or have archives indexed, these options will help search engines look for the right page to display in the search results."
1525
  msgstr ""
1526
 
1527
+ #: inc/views/admin/metaboxes/general-metabox.php:319
1528
  msgid "It's recommended to turn these options on for better SEO consistency and to prevent duplicated content issues."
1529
  msgstr ""
1530
 
1531
  #. translators: the backticks are Markdown! Preserve them as-is!
1532
 
1533
+ #: inc/views/admin/metaboxes/general-metabox.php:325
1534
  msgid "Add `rel` link tags to posts and pages?"
1535
  msgstr ""
1536
 
1537
  #. translators: the backticks are Markdown! Preserve them as-is!
1538
 
1539
+ #: inc/views/admin/metaboxes/general-metabox.php:336
1540
  msgid "Add `rel` link tags to archives?"
1541
  msgstr ""
1542
 
1543
  #. translators: the backticks are Markdown! Preserve them as-is!
1544
 
1545
+ #: inc/views/admin/metaboxes/general-metabox.php:347
1546
  msgid "Add `rel` link tags to the homepage?"
1547
  msgstr ""
1548
 
1549
+ #: inc/views/admin/metaboxes/general-metabox.php:374
1550
  msgid "Timestamp Settings"
1551
  msgstr ""
1552
 
1553
+ #: inc/views/admin/metaboxes/general-metabox.php:376
1554
  msgid "Timestamps help indicate when a page has been published and modified."
1555
  msgstr ""
1556
 
1557
+ #: inc/views/admin/metaboxes/general-metabox.php:382
1558
  msgid "Timestamp Format Settings"
1559
  msgstr ""
1560
 
1561
+ #: inc/views/admin/metaboxes/general-metabox.php:383
1562
  msgid "This setting determines how specific the timestamp is."
1563
  msgstr ""
1564
 
1565
+ #: inc/views/admin/metaboxes/general-metabox.php:395
1566
  msgid "This outputs the complete date."
1567
  msgstr ""
1568
 
1569
+ #: inc/views/admin/metaboxes/general-metabox.php:408
1570
  msgid "This outputs the complete date including hours, minutes, and timezone."
1571
  msgstr ""
1572
 
1573
+ #: inc/views/admin/metaboxes/general-metabox.php:420
1574
+ #: inc/views/admin/metaboxes/robots-metabox.php:319
1575
  msgid "Post Type Settings"
1576
  msgstr ""
1577
 
1578
+ #: inc/views/admin/metaboxes/general-metabox.php:422
1579
  msgid "Post types are special content types. These options should not need changing when post types are registered correctly."
1580
  msgstr ""
1581
 
1582
+ #: inc/views/admin/metaboxes/general-metabox.php:427
1583
  msgid "Disable SEO"
1584
  msgstr ""
1585
 
1586
+ #: inc/views/admin/metaboxes/general-metabox.php:429
1587
  msgid "Select post types which should not receive any SEO optimization whatsoever. This will remove meta optimizations, SEO suggestions, and sitemap inclusions for the selected post types."
1588
  msgstr ""
1589
 
1590
+ #: inc/views/admin/metaboxes/general-metabox.php:430
1591
+ msgid "Disabling SEO allows search engines to crawl the post type without restrictions or direction."
1592
+ msgstr ""
1593
+
1594
+ #: inc/views/admin/metaboxes/general-metabox.php:431
1595
+ #: inc/views/admin/metaboxes/robots-metabox.php:321
1596
  msgid "These settings are applied to the post type pages and their terms. When terms are shared between post types, all their post types should be checked for this to have an effect."
1597
  msgstr ""
1598
 
1599
+ #: inc/views/admin/metaboxes/general-metabox.php:432
1600
  msgid "Default post types can not be disabled."
1601
  msgstr ""
1602
 
1715
  msgstr ""
1716
 
1717
  #: inc/views/admin/metaboxes/homepage-metabox.php:370
1718
+ #: inc/views/admin/metaboxes/social-metabox.php:118
1719
  msgid "Social Image Settings"
1720
  msgstr ""
1721
 
1736
  msgstr ""
1737
 
1738
  #: inc/views/admin/metaboxes/homepage-metabox.php:421
1739
+ msgctxt "Bear with me: the homepage can be edited globally, or via its page. Thus \"homepage page\"."
1740
  msgid "Edit homepage page settings"
1741
  msgstr ""
1742
 
1829
  msgstr ""
1830
 
1831
  #: inc/views/admin/metaboxes/robots-metabox.php:38
1832
+ msgid "These options most likely prevent links from being followed on the selected archives and pages. If you enable this, the selected archives or pages in-page links will gain no SEO value, including your internal links."
1833
  msgstr ""
1834
 
1835
  #: inc/views/admin/metaboxes/robots-metabox.php:42
1837
  msgstr ""
1838
 
1839
  #: inc/views/admin/metaboxes/robots-metabox.php:87
1840
+ msgid "Advanced Query Protection"
1841
  msgstr ""
1842
 
1843
  #: inc/views/admin/metaboxes/robots-metabox.php:89
1844
+ msgid "Some URL queries can cause WordPress to show faux archives. When search engines spot these, they will crawl and index them, which may cause a drop in ranking. Advanced query protection will prevent robots from indexing these archives."
1845
+ msgstr ""
1846
+
1847
+ #: inc/views/admin/metaboxes/robots-metabox.php:94
1848
+ msgid "Enable advanced query protection?"
1849
+ msgstr ""
1850
+
1851
+ #: inc/views/admin/metaboxes/robots-metabox.php:103
1852
+ msgid "Paginated Archive Settings"
1853
+ msgstr ""
1854
+
1855
+ #: inc/views/admin/metaboxes/robots-metabox.php:105
1856
  msgid "Indexing the second or later page of any archive might cause duplication errors. Search engines look down upon them; therefore, it's recommended to disable indexing of those pages."
1857
  msgstr ""
1858
 
1859
  #. translators: the backticks are Markdown! Preserve them as-is!
1860
 
1861
+ #: inc/views/admin/metaboxes/robots-metabox.php:112
1862
  msgid "Apply `noindex` to every second or later archive page?"
1863
  msgstr ""
1864
 
1865
+ #: inc/views/admin/metaboxes/robots-metabox.php:123
1866
  msgid "Copyright Directive Settings"
1867
  msgstr ""
1868
 
1869
+ #: inc/views/admin/metaboxes/robots-metabox.php:125
1870
  msgid "Some search engines allow you to control copyright directives on the content they aggregate. It's best to allow some content to be taken by these aggregators, as that can improve contextualized exposure via snippets and previews. When left unspecified, regional regulations may apply. It is up to the aggregator to honor these requests."
1871
  msgstr ""
1872
 
1873
+ #: inc/views/admin/metaboxes/robots-metabox.php:130
1874
  msgid "Specify aggregator copyright compliance directives?"
1875
  msgstr ""
1876
 
1877
+ #: inc/views/admin/metaboxes/robots-metabox.php:138
1878
  msgid "Unlimited"
1879
  msgstr ""
1880
 
1881
+ #: inc/views/admin/metaboxes/robots-metabox.php:139
1882
  msgctxt "quanity: zero"
1883
  msgid "None, disallow snippet"
1884
  msgstr ""
1885
 
1886
  #. translators: %d = number
1887
 
1888
+ #: inc/views/admin/metaboxes/robots-metabox.php:143
1889
  msgid "%d character"
1890
  msgid_plural "%d characters"
1891
  msgstr[0] ""
1892
  msgstr[1] ""
1893
 
1894
+ #: inc/views/admin/metaboxes/robots-metabox.php:149
1895
+ #: inc/views/admin/metaboxes/robots-metabox.php:235
1896
  msgid "Standard directive"
1897
  msgstr ""
1898
 
1899
+ #: inc/views/admin/metaboxes/robots-metabox.php:150
1900
+ #: inc/views/admin/metaboxes/robots-metabox.php:236
1901
  msgid "Granular directive"
1902
  msgstr ""
1903
 
1904
+ #: inc/views/admin/metaboxes/robots-metabox.php:173
1905
  msgid "Maximum text snippet length"
1906
  msgstr ""
1907
 
1908
+ #: inc/views/admin/metaboxes/robots-metabox.php:177
1909
  msgid "This may limit the text snippet length for all pages on this site."
1910
  msgstr ""
1911
 
1912
+ #: inc/views/admin/metaboxes/robots-metabox.php:181
1913
  msgid "This directive also imposes a limit on meta descriptions and structured data, which unintentionally restricts the amount of information you can share. Therefore, it's best to use at least a 320 character limit."
1914
  msgstr ""
1915
 
1916
+ #: inc/views/admin/metaboxes/robots-metabox.php:190
1917
  msgctxt "quanity: zero"
1918
  msgid "None, disallow preview"
1919
  msgstr ""
1920
 
1921
+ #: inc/views/admin/metaboxes/robots-metabox.php:191
1922
  msgid "Thumbnail or standard size"
1923
  msgstr ""
1924
 
1925
+ #: inc/views/admin/metaboxes/robots-metabox.php:192
1926
  msgid "Large or full size"
1927
  msgstr ""
1928
 
1929
+ #: inc/views/admin/metaboxes/robots-metabox.php:210
1930
  msgid "Maximum image preview size"
1931
  msgstr ""
1932
 
1933
+ #: inc/views/admin/metaboxes/robots-metabox.php:214
1934
  msgid "This may limit the image preview size for all images from this site."
1935
  msgstr ""
1936
 
1937
+ #: inc/views/admin/metaboxes/robots-metabox.php:224
 
 
 
 
 
 
 
1938
  msgid "Full video preview"
1939
  msgstr ""
1940
 
1941
+ #: inc/views/admin/metaboxes/robots-metabox.php:225
1942
  msgctxt "quanity: zero"
1943
  msgid "None, still image only"
1944
  msgstr ""
1945
 
1946
  #. translators: %d = number
1947
 
1948
+ #: inc/views/admin/metaboxes/robots-metabox.php:229
1949
  msgid "%d second"
1950
  msgid_plural "%d seconds"
1951
  msgstr[0] ""
1952
  msgstr[1] ""
1953
 
1954
+ #: inc/views/admin/metaboxes/robots-metabox.php:258
1955
  msgid "Maximum video preview length"
1956
  msgstr ""
1957
 
1958
+ #: inc/views/admin/metaboxes/robots-metabox.php:262
1959
  msgid "This may limit the video preview length for all videos on this site."
1960
  msgstr ""
1961
 
1962
  #. translators: 1 = noindex/nofollow/noarchive, 2 = Post, Post type, Category
1963
  #. archives, the entire site, etc.
1964
 
1965
+ #: inc/views/admin/metaboxes/robots-metabox.php:277
1966
  msgid "Apply %1$s to %2$s?"
1967
  msgstr ""
1968
 
1969
+ #: inc/views/admin/metaboxes/robots-metabox.php:282
1970
  msgid "Robots Settings"
1971
  msgstr ""
1972
 
1973
+ #: inc/views/admin/metaboxes/robots-metabox.php:307
1974
  msgid "Warning: No public site should ever enable this option."
1975
  msgstr ""
1976
 
1977
+ #: inc/views/admin/metaboxes/robots-metabox.php:326
1978
  msgid "Warning: No site should enable these options for Posts and Pages."
1979
  msgstr ""
1980
 
2105
  msgstr ""
2106
 
2107
  #: inc/views/admin/metaboxes/schema-metabox.php:193
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2108
  msgctxt "No spaces. E.g. https://facebook.com/RelatedProfile"
2109
  msgid "RelatedProfile"
2110
  msgstr ""
2111
 
2112
+ #: inc/views/admin/metaboxes/schema-metabox.php:201
2113
  msgid "Facebook Page"
2114
  msgstr ""
2115
 
2116
+ #: inc/views/admin/metaboxes/schema-metabox.php:208
2117
  msgid "Twitter Profile"
2118
  msgstr ""
2119
 
2120
+ #: inc/views/admin/metaboxes/schema-metabox.php:215
2121
  msgctxt "Google+ is dead. &#8224; is a cross, indicating that."
2122
  msgid "Google+ Profile&#8224;"
2123
  msgstr ""
2124
 
2125
+ #: inc/views/admin/metaboxes/schema-metabox.php:222
2126
  msgid "Instagram Profile"
2127
  msgstr ""
2128
 
2129
+ #: inc/views/admin/metaboxes/schema-metabox.php:229
2130
  msgid "Youtube Profile"
2131
  msgstr ""
2132
 
2133
+ #: inc/views/admin/metaboxes/schema-metabox.php:236
2134
  msgid "LinkedIn Profile"
2135
  msgstr ""
2136
 
2137
+ #: inc/views/admin/metaboxes/schema-metabox.php:247
2138
  msgid "Pinterest Profile"
2139
  msgstr ""
2140
 
2141
+ #: inc/views/admin/metaboxes/schema-metabox.php:254
2142
  msgid "SoundCloud Profile"
2143
  msgstr ""
2144
 
2145
+ #: inc/views/admin/metaboxes/schema-metabox.php:261
2146
  msgid "Tumblr Blog"
2147
  msgstr ""
2148
 
2149
+ #: inc/views/admin/metaboxes/schema-metabox.php:280
2150
+ msgid "Connected Social Pages"
2151
+ msgstr ""
2152
+
2153
+ #: inc/views/admin/metaboxes/schema-metabox.php:282
2154
+ msgid "Don't have a page at a site or is the profile only privately accessible? Leave that field empty. Unsure? Fill it in anyway."
2155
+ msgstr ""
2156
+
2157
+ #: inc/views/admin/metaboxes/schema-metabox.php:283
2158
+ msgid "Add links that lead directly to the connected social pages of this website."
2159
+ msgstr ""
2160
+
2161
+ #: inc/views/admin/metaboxes/schema-metabox.php:284
2162
+ msgid "These settings do not affect sharing behavior with the social networks."
2163
+ msgstr ""
2164
+
2165
+ #. translators: %s = Learn more URL. Markdown!
2166
+
2167
+ #: inc/views/admin/metaboxes/schema-metabox.php:289
2168
+ msgid "These settings are marked for removal. When you clear a field, it will be hidden forever. [Learn more](%s)."
2169
+ msgstr ""
2170
+
2171
+ #: inc/views/admin/metaboxes/schema-metabox.php:308
2172
  msgid "View your profile."
2173
  msgstr ""
2174
 
2197
  msgid "The sitemap does not contribute to ranking, only indexing. Therefore, it is perfectly fine not having every indexable page in the sitemap."
2198
  msgstr ""
2199
 
2200
+ #: inc/views/admin/metaboxes/sitemaps-metabox.php:71
2201
  msgid "Note: Another active sitemap plugin has been detected. This means that the sitemap functionality has been superseded and these settings have no effect."
2202
  msgstr ""
2203
 
2204
+ #: inc/views/admin/metaboxes/sitemaps-metabox.php:74
2205
  msgid "Note: A sitemap has been detected in the root folder of your website. This means that these settings have no effect."
2206
  msgstr ""
2207
 
2378
  msgid "Sitemap title and lines color"
2379
  msgstr ""
2380
 
2381
+ #: inc/views/admin/metaboxes/social-metabox.php:40
2382
  msgid "Post Dates"
2383
  msgstr ""
2384
 
2385
+ #: inc/views/admin/metaboxes/social-metabox.php:60
2386
  msgid "Social Meta Tags Settings"
2387
  msgstr ""
2388
 
2389
+ #: inc/views/admin/metaboxes/social-metabox.php:62
2390
  msgid "Output various meta tags for social site integration, among other 3rd party services."
2391
  msgstr ""
2392
 
2393
+ #: inc/views/admin/metaboxes/social-metabox.php:72
2394
  msgid "Output Open Graph meta tags?"
2395
  msgstr ""
2396
 
2397
+ #: inc/views/admin/metaboxes/social-metabox.php:73
2398
  msgid "Facebook, Twitter, Pinterest and many other social sites make use of these meta tags."
2399
  msgstr ""
2400
 
2401
+ #: inc/views/admin/metaboxes/social-metabox.php:79
2402
  msgid "Note: Another Open Graph plugin has been detected. These meta tags might conflict."
2403
  msgstr ""
2404
 
2405
+ #: inc/views/admin/metaboxes/social-metabox.php:85
2406
  msgid "Output Facebook meta tags?"
2407
  msgstr ""
2408
 
2409
+ #: inc/views/admin/metaboxes/social-metabox.php:86
2410
  msgid "Output various meta tags targeted at Facebook."
2411
  msgstr ""
2412
 
2413
+ #: inc/views/admin/metaboxes/social-metabox.php:96
2414
  msgid "Output Twitter meta tags?"
2415
  msgstr ""
2416
 
2417
+ #: inc/views/admin/metaboxes/social-metabox.php:97
2418
  msgid "Output various meta tags targeted at Twitter."
2419
  msgstr ""
2420
 
2421
+ #: inc/views/admin/metaboxes/social-metabox.php:103
2422
  msgid "Note: Another Twitter Card plugin has been detected. These meta tags might conflict."
2423
  msgstr ""
2424
 
2425
+ #: inc/views/admin/metaboxes/social-metabox.php:109
2426
+ msgid "Output oEmbed scripts?"
2427
+ msgstr ""
2428
+
2429
+ #: inc/views/admin/metaboxes/social-metabox.php:110
2430
+ msgid "WordPress, Discord, Drupal, Squarespace, and many other clients can make use of these scripts."
2431
+ msgstr ""
2432
+
2433
+ #: inc/views/admin/metaboxes/social-metabox.php:120
2434
  msgid "A social image can be displayed when your website is shared. It is a great way to grab attention."
2435
  msgstr ""
2436
 
2437
+ #: inc/views/admin/metaboxes/social-metabox.php:126
2438
  msgid "Output multiple Open Graph image tags?"
2439
  msgstr ""
2440
 
2441
+ #: inc/views/admin/metaboxes/social-metabox.php:127
2442
  msgid "This enables users to select any image attached to the page shared on social networks, like Facebook."
2443
  msgstr ""
2444
 
2445
+ #: inc/views/admin/metaboxes/social-metabox.php:135
2446
  msgid "Social Image Fallback URL"
2447
  msgstr ""
2448
 
2449
+ #: inc/views/admin/metaboxes/social-metabox.php:136
2450
  msgid "When no image is available from the page or term, this fallback image will be used instead."
2451
  msgstr ""
2452
 
2453
+ #: inc/views/admin/metaboxes/social-metabox.php:151
2454
+ msgid "Theme Color Settings"
2455
+ msgstr ""
2456
+
2457
+ #: inc/views/admin/metaboxes/social-metabox.php:153
2458
+ msgid "Discord styles embeds with the theme color. The theme color can also affect the tab-color in some browsers."
2459
+ msgstr ""
2460
+
2461
+ #: inc/views/admin/metaboxes/social-metabox.php:157
2462
+ msgid "Theme color"
2463
+ msgstr ""
2464
+
2465
+ #: inc/views/admin/metaboxes/social-metabox.php:165
2466
  msgid "Site Shortlink Settings"
2467
  msgstr ""
2468
 
2469
+ #: inc/views/admin/metaboxes/social-metabox.php:167
2470
  msgid "The shortlink tag can be manually used for microblogging services like Twitter, but it has no SEO value whatsoever."
2471
  msgstr ""
2472
 
2473
+ #: inc/views/admin/metaboxes/social-metabox.php:172
2474
  msgid "Output shortlink tag?"
2475
  msgstr ""
2476
 
2477
+ #: inc/views/admin/metaboxes/social-metabox.php:185
2478
  msgctxt "Example Facebook Business URL"
2479
  msgid "https://www.facebook.com/YourBusinessProfile"
2480
  msgstr ""
2481
 
2482
+ #: inc/views/admin/metaboxes/social-metabox.php:191
2483
+ msgid "Facebook Integration Settings"
2484
  msgstr ""
2485
 
2486
+ #: inc/views/admin/metaboxes/social-metabox.php:193
2487
  msgid "Facebook post sharing works mostly through Open Graph. However, you can also link your Business and Personal Facebook pages, among various other options."
2488
  msgstr ""
2489
 
2490
+ #: inc/views/admin/metaboxes/social-metabox.php:194
2491
  msgid "When these options are filled in, Facebook might link the Facebook profile to be followed and liked when your post or page is shared."
2492
  msgstr ""
2493
 
2494
+ #: inc/views/admin/metaboxes/social-metabox.php:200
2495
  msgid "Facebook App ID"
2496
  msgstr ""
2497
 
2498
+ #: inc/views/admin/metaboxes/social-metabox.php:204
2499
  msgid "Get Facebook App ID."
2500
  msgstr ""
2501
 
2502
+ #: inc/views/admin/metaboxes/social-metabox.php:216
2503
  msgid "Facebook Publisher page"
2504
  msgstr ""
2505
 
2506
+ #: inc/views/admin/metaboxes/social-metabox.php:220
2507
  msgid "Only Facebook Business Pages are accepted."
2508
  msgstr ""
2509
 
2510
+ #: inc/views/admin/metaboxes/social-metabox.php:232
2511
  msgid "Facebook Author Fallback Page"
2512
  msgstr ""
2513
 
2514
+ #: inc/views/admin/metaboxes/social-metabox.php:236
2515
  msgid "Your Facebook profile."
2516
  msgstr ""
2517
 
2518
+ #: inc/views/admin/metaboxes/social-metabox.php:242
2519
+ #: inc/views/admin/metaboxes/social-metabox.php:334
2520
  msgid "Authors can override this option on their profile page."
2521
  msgstr ""
2522
 
2523
+ #: inc/views/admin/metaboxes/social-metabox.php:251
2524
  msgctxt "Twitter @username"
2525
  msgid "@your-site-username"
2526
  msgstr ""
2527
 
2528
+ #: inc/views/admin/metaboxes/social-metabox.php:259
2529
+ msgid "Twitter Integration Settings"
2530
  msgstr ""
2531
 
2532
+ #: inc/views/admin/metaboxes/social-metabox.php:261
2533
  msgid "Twitter post sharing works mostly through Twitter Cards, and may fall back to use Open Graph. However, you can also link your Business and Personal Twitter pages, among various other options."
2534
  msgstr ""
2535
 
2536
+ #: inc/views/admin/metaboxes/social-metabox.php:267
2537
  msgid "Twitter Card Type"
2538
  msgstr ""
2539
 
2540
+ #: inc/views/admin/metaboxes/social-metabox.php:270
2541
  msgid "The Twitter Card type may have the image highlighted, either small at the side or large above."
2542
  msgstr ""
2543
 
2544
+ #: inc/views/admin/metaboxes/social-metabox.php:303
2545
  msgid "When the following options are filled in, Twitter might link your Twitter Site or Author Profile when your post or page is shared."
2546
  msgstr ""
2547
 
2548
+ #: inc/views/admin/metaboxes/social-metabox.php:308
2549
  msgid "Website Twitter Profile"
2550
  msgstr ""
2551
 
2552
+ #: inc/views/admin/metaboxes/social-metabox.php:312
2553
+ #: inc/views/admin/metaboxes/social-metabox.php:328
2554
  msgid "Find your @username."
2555
  msgstr ""
2556
 
2557
+ #: inc/views/admin/metaboxes/social-metabox.php:324
2558
  msgid "Twitter Author Fallback Profile"
2559
  msgstr ""
2560
 
2561
+ #: inc/views/admin/metaboxes/social-metabox.php:343
2562
+ msgid "oEmbed Settings"
2563
+ msgstr ""
2564
+
2565
+ #: inc/views/admin/metaboxes/social-metabox.php:345
2566
+ msgid "Some social sharing services and clients, like WordPress and Discord, obtain the linked page information via oEmbed."
2567
+ msgstr ""
2568
+
2569
+ #: inc/views/admin/metaboxes/social-metabox.php:353
2570
+ msgid "Remove author name?"
2571
+ msgstr ""
2572
+
2573
+ #: inc/views/admin/metaboxes/social-metabox.php:354
2574
+ msgid "Discord shows the page author name above the sharing embed. Check this options if you find this undesirable."
2575
+ msgstr ""
2576
+
2577
+ #: inc/views/admin/metaboxes/social-metabox.php:362
2578
  msgid "Posts"
2579
  msgstr ""
2580
 
2581
+ #: inc/views/admin/metaboxes/social-metabox.php:365
2582
  msgid "Post Date Settings"
2583
  msgstr ""
2584
 
2585
+ #: inc/views/admin/metaboxes/social-metabox.php:367
2586
  msgid "Some social sites output the shared post's publishing and modified data in the sharing snippet."
2587
  msgstr ""
2588
 
2589
  #. translators: the backticks are Markdown! Preserve them as-is!
2590
 
2591
+ #: inc/views/admin/metaboxes/social-metabox.php:378
2592
  msgid "Add `article:published_time` to posts?"
2593
  msgstr ""
2594
 
2595
  #. translators: the backticks are Markdown! Preserve them as-is!
2596
 
2597
+ #: inc/views/admin/metaboxes/social-metabox.php:388
2598
  msgid "Add `article:modified_time` to posts?"
2599
  msgstr ""
2600
 
2697
  msgid "Remove term type prefixes from title?"
2698
  msgstr ""
2699
 
 
 
 
 
2700
  #: inc/views/admin/metaboxes/webmaster-metabox.php:26
 
 
 
 
 
 
 
 
2701
  msgid "Google Search Console Verification Code"
2702
  msgstr ""
2703
 
2704
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:28
2705
  msgid "Get the Google verification code."
2706
  msgstr ""
2707
 
2708
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:36
2709
  msgid "Bing Webmaster Verification Code"
2710
  msgstr ""
2711
 
2712
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:38
2713
  msgid "Get the Bing verification code."
2714
  msgstr ""
2715
 
2716
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:46
2717
  msgid "Yandex Webmaster Verification Code"
2718
  msgstr ""
2719
 
2720
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:48
2721
  msgid "Get the Yandex verification code."
2722
  msgstr ""
2723
 
2724
+ #. translators: literal translation from '百度搜索资源平台'-Code
2725
+
2726
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:57
2727
+ msgid "Baidu Search Resource Platform Code"
2728
+ msgstr ""
2729
+
2730
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:59
2731
+ msgid "Get the Baidu verification code."
2732
+ msgstr ""
2733
+
2734
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:67
2735
  msgid "Pinterest Analytics Verification Code"
2736
  msgstr ""
2737
 
2738
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:69
2739
  msgid "Get the Pinterest verification code."
2740
  msgstr ""
2741
 
2742
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:78
2743
+ msgid "Webmaster Integration Settings"
2744
+ msgstr ""
2745
+
2746
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:80
2747
+ msgid "When adding your website to Google, Bing and other Webmaster Tools, you'll be asked to add a code or file to your website for verification purposes. These options will help you easily integrate those codes."
2748
+ msgstr ""
2749
+
2750
+ #: inc/views/admin/metaboxes/webmaster-metabox.php:81
2751
+ msgid "Verifying your website has no SEO value whatsoever. But you might gain added benefits such as search ranking insights to help you improve your website's content."
2752
+ msgstr ""
2753
+
2754
  #: inc/views/admin/seo-settings-wrap.php:20
2755
  #: inc/views/admin/seo-settings-wrap.php:38
2756
  msgid "Save Settings"
2777
  msgstr ""
2778
 
2779
  #: inc/views/edit/seo-settings-singular.php:136
2780
+ msgid "This option must be managed on the SEO Settings page for the homepage."
2781
  msgstr ""
2782
 
2783
  #: inc/views/edit/seo-settings-singular.php:143
2792
  msgstr ""
2793
 
2794
  #: inc/views/edit/seo-settings-singular.php:222
2795
+ #: inc/views/edit/seo-settings-tt.php:279 inc/views/list/quick-post.php:57
2796
+ #: inc/views/list/quick-term.php:57
2797
  msgid "Canonical URL"
2798
  msgstr ""
2799
 
2813
  #. translators: %s = default option value
2814
 
2815
  #: inc/views/edit/seo-settings-singular.php:289
2816
+ #: inc/views/edit/seo-settings-tt.php:316 inc/views/list/quick-post.php:74
2817
+ #: inc/views/list/quick-term.php:74
2818
  msgid "Default (%s)"
2819
  msgstr ""
2820
 
2831
  msgstr ""
2832
 
2833
  #: inc/views/edit/seo-settings-singular.php:347
2834
+ #: inc/views/edit/seo-settings-tt.php:332 inc/views/list/quick-post.php:87
2835
+ #: inc/views/list/quick-term.php:87
2836
  msgid "301 Redirect URL"
2837
  msgstr ""
2838
 
2861
  msgid "Social SEO Settings"
2862
  msgstr ""
2863
 
2864
+ #: inc/views/edit/seo-settings-tt.php:272 inc/views/list/bulk-post.php:54
2865
+ #: inc/views/list/quick-post.php:54 inc/views/list/quick-term.php:54
2866
  msgid "Visibility SEO Settings"
2867
  msgstr ""
2868
 
2870
  msgid "These directives may urge robots not to display, follow links on, or create a cached copy of this term."
2871
  msgstr ""
2872
 
2873
+ #: inc/views/list/bulk-post.php:67
2874
  msgid "&mdash; No Change &mdash;"
2875
  msgstr ""
2876
 
2877
+ #: inc/views/list/bulk-post.php:68
2878
  msgid "Default (unknown)"
2879
  msgstr ""
2880
 
2934
  #: inc/views/templates/inpost/primary-term-selector.php:28
2935
  msgid "The buttons below are for primary %s selection."
2936
  msgstr ""
2937
+
2938
+ #: inc/views/templates/settings/settings.php:14
2939
+ msgid "This post type is disabled, so this option won't work."
2940
+ msgstr ""
2941
  #. Plugin Name of the plugin/theme
2942
  msgid "The SEO Framework"
2943
  msgstr ""
lib/css/post.css CHANGED
@@ -1,22 +1,12 @@
1
- #tsf-inpost-box .inside select {
2
- width: 100%;
3
- max-width: 99%;
4
- text-overflow: ellipsis;
5
- }
6
-
7
  #tsf-inpost-box .inside {
8
- box-sizing: border-box;
9
- display: flex;
10
- flex: 1 1 auto;
11
- flex-flow: column wrap;
12
- justify-content: flex-start;
13
  }
14
 
15
- #tsf-inpost-box .inside {
16
- margin: 0;
 
17
  padding: 0;
18
- flex: 1 0 100%;
19
- flex-wrap: nowrap;
20
  }
21
 
22
  #tsf-inpost-box.closed .inside {
@@ -24,14 +14,47 @@
24
  }
25
 
26
  .tsf-flex-inside-wrap {
27
- /* IE11 wrapper fix */
28
  flex-direction: row;
29
- flex: 1 1 auto;
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  .tsf-flex-setting {
33
  width: 100%;
34
  flex-direction: row;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
 
37
  .tsf-flex-setting-label,
@@ -39,7 +62,6 @@
39
  background-color: #fff;
40
  padding: 15px 12px;
41
  flex: 10 1 350px;
42
- box-shadow: 0 0 0 1px #e9e9e9;
43
  }
44
 
45
  .tsf-flex-setting-label {
@@ -104,26 +126,28 @@ input.tsf-flex-nav-tab-radio {
104
  }
105
 
106
  .tsf-flex-nav-tab-wrapper {
107
- background-color: #fcfcfc;
108
- border-bottom: 2px solid #dadada;
109
  align-items: baseline;
110
  flex-flow: row nowrap;
111
- /* IE11 fix */
112
- flex: 1 1 100%;
113
  max-width: 100%;
114
  overflow: hidden;
 
 
 
 
 
 
115
  }
116
 
117
  .tsf-flex-nav-tab-inner {
118
  flex-flow: row nowrap;
119
- /* IE11 reverse fix for newer browsers */
120
- flex: 1 0 auto;
121
  }
122
 
123
  .tsf-flex-nav-tab {
124
  flex-direction: row;
125
  flex: 1 1 auto;
126
- max-width: 125px; /* I wanted this to be flex-basis */
127
  }
128
 
129
  .tsf-flex-nav-tab-label {
@@ -141,6 +165,7 @@ input.tsf-flex-nav-tab-radio {
141
  .tsf-flex-nav-name {
142
  align-items: center;
143
  justify-content: center;
 
144
  }
145
 
146
  .tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked + .tsf-flex-nav-tab-label {
 
 
 
 
 
 
1
  #tsf-inpost-box .inside {
2
+ margin: 0;
3
+ padding: 14px;
 
 
 
4
  }
5
 
6
+ #tsf-inpost-box:not(.tsf-is-block-editor) .inside,
7
+ .edit-post-sidebar #tsf-inpost-box .inside { /* .edit-post-sidebar is Gutenberg-only */
8
+ width: 100%;
9
  padding: 0;
 
 
10
  }
11
 
12
  #tsf-inpost-box.closed .inside {
14
  }
15
 
16
  .tsf-flex-inside-wrap {
 
17
  flex-direction: row;
18
+ width: 100%; /* WP 5.4+ fix */
19
+ }
20
+
21
+ .tsf-is-block-editor .tsf-flex-inside-wrap {
22
+ border: 1px solid #ddd;
23
+ }
24
+
25
+ /* .edit-post-sidebar is Gutenberg-only. .tsf-is-block-editor is used to override specifity */
26
+ .edit-post-sidebar .tsf-is-block-editor .tsf-flex-inside-wrap {
27
+ border: 0;
28
  }
29
 
30
  .tsf-flex-setting {
31
  width: 100%;
32
  flex-direction: row;
33
+ border-bottom: 1px solid #e2e4e7;
34
+ }
35
+
36
+ .tsf-flex-setting:last-of-type {
37
+ border-bottom: 0;
38
+ }
39
+
40
+ /* sub-flex-setting boxes. */
41
+ .tsf-flex-setting-input .tsf-flex-setting {
42
+ border-left: 1px solid #e2e4e7;
43
+ border-right: 1px solid #e2e4e7;
44
+ }
45
+
46
+ .tsf-flex-setting-input .tsf-flex-setting:first-of-type {
47
+ border-top: 1px solid #e2e4e7;
48
+ }
49
+
50
+ .tsf-flex-setting-input .tsf-flex-setting:last-of-type {
51
+ border-bottom: 1px solid #e2e4e7;
52
+ }
53
+
54
+ #tsf-inpost-box .inside select {
55
+ width: 100%;
56
+ max-width: 99%;
57
+ text-overflow: ellipsis;
58
  }
59
 
60
  .tsf-flex-setting-label,
62
  background-color: #fff;
63
  padding: 15px 12px;
64
  flex: 10 1 350px;
 
65
  }
66
 
67
  .tsf-flex-setting-label {
126
  }
127
 
128
  .tsf-flex-nav-tab-wrapper {
129
+ background-color: #f5f5f5;
130
+ border-bottom: 1px solid #dadada;
131
  align-items: baseline;
132
  flex-flow: row nowrap;
 
 
133
  max-width: 100%;
134
  overflow: hidden;
135
+ font-weight: 600;
136
+ }
137
+
138
+ .tsf-is-block-editor .tsf-flex-nav-tab-wrapper {
139
+ background-color: #f3f4f5;
140
+ border-bottom-color: #e2e4e7;
141
  }
142
 
143
  .tsf-flex-nav-tab-inner {
144
  flex-flow: row nowrap;
 
 
145
  }
146
 
147
  .tsf-flex-nav-tab {
148
  flex-direction: row;
149
  flex: 1 1 auto;
150
+ max-width: 125px;
151
  }
152
 
153
  .tsf-flex-nav-tab-label {
165
  .tsf-flex-nav-name {
166
  align-items: center;
167
  justify-content: center;
168
+ margin: 0 2px;
169
  }
170
 
171
  .tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked + .tsf-flex-nav-tab-label {
lib/css/post.min.css CHANGED
@@ -1 +1 @@
1
- #tsf-inpost-box .inside select{width:100%;max-width:99%;text-overflow:ellipsis}#tsf-inpost-box .inside{box-sizing:border-box;display:flex;flex:1 1 auto;flex-flow:column wrap;justify-content:flex-start}#tsf-inpost-box .inside{margin:0;padding:0;flex:1 0 100%;flex-wrap:nowrap}#tsf-inpost-box.closed .inside{display:none}.tsf-flex-inside-wrap{flex-direction:row;flex:1 1 auto}.tsf-flex-setting{width:100%;flex-direction:row}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;flex:10 1 350px;box-shadow:0 0 0 1px #e9e9e9}.tsf-flex-setting-label{background-color:#f9f9f9;flex:1 1 200px}.tsf-flex-setting-input{justify-content:center;flex-wrap:nowrap}.tsf-flex-setting-label-item{flex-flow:row nowrap;justify-content:space-between;flex-grow:0}.tsf-flex-setting-label-inner-wrap{justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label-sub-item{margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}body.rtl .tsf-social-image-buttons{margin-right:1px;margin-left:0}.tsf-flex-setting-input textarea{max-height:250px}input.tsf-flex-nav-tab-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-flex-nav-tab-wrapper{background-color:#fcfcfc;border-bottom:2px solid #dadada;align-items:baseline;flex-flow:row nowrap;flex:1 1 100%;max-width:100%;overflow:hidden}.tsf-flex-nav-tab-inner{flex-flow:row nowrap;flex:1 0 auto}.tsf-flex-nav-tab{flex-direction:row;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;flex-direction:row;box-shadow:0 0 0 0 transparent inset;transition:box-shadow .15s ease-out;align-items:center;align-content:space-around;position:relative}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{align-items:center;justify-content:center}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset,0 0 0 0 #007bd2 inset;transition:box-shadow .25s ease-in}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus+.tsf-flex-nav-tab-label:not(.tsf-no-focus-ring){box-shadow:0 0 0 0 #007bd2 inset,0 0 0 1px #007bd2 inset}.tsf-flex-tab-content{flex:1 0 100%;max-width:100%;flex-wrap:nowrap}body.js .tsf-flex-tab-content{display:none}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{align-items:baseline;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;flex-direction:row;flex:0 1 auto}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-js .tsf-flex-hide-if-js,.tsf-no-js .tsf-flex-hide-if-no-js{display:none}
1
+ #tsf-inpost-box .inside{margin:0;padding:14px}#tsf-inpost-box:not(.tsf-is-block-editor) .inside,.edit-post-sidebar #tsf-inpost-box .inside{width:100%;padding:0}#tsf-inpost-box.closed .inside{display:none}.tsf-flex-inside-wrap{flex-direction:row;width:100%}.tsf-is-block-editor .tsf-flex-inside-wrap{border:1px solid #ddd}.edit-post-sidebar .tsf-is-block-editor .tsf-flex-inside-wrap{border:0}.tsf-flex-setting{width:100%;flex-direction:row;border-bottom:1px solid #e2e4e7}.tsf-flex-setting:last-of-type{border-bottom:0}.tsf-flex-setting-input .tsf-flex-setting{border-left:1px solid #e2e4e7;border-right:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:first-of-type{border-top:1px solid #e2e4e7}.tsf-flex-setting-input .tsf-flex-setting:last-of-type{border-bottom:1px solid #e2e4e7}#tsf-inpost-box .inside select{width:100%;max-width:99%;text-overflow:ellipsis}.tsf-flex-setting-input,.tsf-flex-setting-label{background-color:#fff;padding:15px 12px;flex:10 1 350px}.tsf-flex-setting-label{background-color:#f9f9f9;flex:1 1 200px}.tsf-flex-setting-input{justify-content:center;flex-wrap:nowrap}.tsf-flex-setting-label-item{flex-flow:row nowrap;justify-content:space-between;flex-grow:0}.tsf-flex-setting-label-inner-wrap{justify-content:center}.tsf-flex-setting-label-item>*{margin-right:4px}.tsf-flex-setting-label-item>:last-child{margin-right:0}.tsf-flex-setting-label-sub-item{margin-top:15px}.tsf-social-image-buttons{margin-top:15px;margin-left:1px}body.rtl .tsf-social-image-buttons{margin-right:1px;margin-left:0}.tsf-flex-setting-input textarea{max-height:250px}input.tsf-flex-nav-tab-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-flex-nav-tab-wrapper{background-color:#f5f5f5;border-bottom:1px solid #dadada;align-items:baseline;flex-flow:row nowrap;max-width:100%;overflow:hidden;font-weight:600}.tsf-is-block-editor .tsf-flex-nav-tab-wrapper{background-color:#f3f4f5;border-bottom-color:#e2e4e7}.tsf-flex-nav-tab-inner{flex-flow:row nowrap}.tsf-flex-nav-tab{flex-direction:row;flex:1 1 auto;max-width:125px}.tsf-flex-nav-tab-label{padding:12px;text-align:center;flex-direction:row;box-shadow:0 0 0 0 transparent inset;transition:box-shadow .15s ease-out;align-items:center;align-content:space-around;position:relative}.tsf-flex-nav-dashicon,.tsf-flex-nav-name{align-items:center;justify-content:center;margin:0 2px}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:checked+.tsf-flex-nav-tab-label{box-shadow:0 -2px 0 0 #007bd2 inset,0 0 0 0 #007bd2 inset;transition:box-shadow .25s ease-in}.tsf-flex-nav-tab .tsf-flex-nav-tab-radio:focus+.tsf-flex-nav-tab-label:not(.tsf-no-focus-ring){box-shadow:0 0 0 0 #007bd2 inset,0 0 0 1px #007bd2 inset}.tsf-flex-tab-content{flex:1 0 100%;max-width:100%;flex-wrap:nowrap}body.js .tsf-flex-tab-content{display:none}body.js .tsf-flex-tab-content.tsf-flex-tab-content-active{display:flex}.tsf-flex-tabs-content-no-js{background-color:#f3f3f3;border-bottom:1px solid #dadada;box-shadow:0 2px 0 0 #dadada inset}.tsf-flex-tab-no-js{align-items:baseline;flex-direction:row;flex:1 1 100%}.tsf-flex-tab-no-js .tsf-flex-nav-tab{padding:12px;min-width:125px;box-shadow:0 -2px 0 0 #007bd2 inset;flex-direction:row;flex:0 1 auto}#tsf-inpost-box .hndle .tsf-tooltip-wrap a{font-size:14px;line-height:1em}.tsf-js .tsf-flex-hide-if-js,.tsf-no-js .tsf-flex-hide-if-no-js{display:none}
lib/css/settings.css CHANGED
@@ -218,3 +218,35 @@ body.js .tsf-tabs-content.tsf-active-tab-content {
218
  /**
219
  * End tabs.
220
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  /**
219
  * End tabs.
220
  */
221
+
222
+ /**
223
+ * TEMP
224
+ * @see https://core.trac.wordpress.org/ticket/49543
225
+ */
226
+
227
+ .wp-picker-input-wrap .button.wp-picker-clear {
228
+ margin-left: 6px;
229
+ padding: 0 8px;
230
+ line-height: 2.54545455; /* 28px */
231
+ min-height: 30px;
232
+ }
233
+
234
+ body.rtl .wp-picker-input-wrap .button.wp-picker-clear {
235
+ margin-right: 6px;
236
+ padding: 0 8px;
237
+ line-height: 2.54545455; /* 28px */
238
+ min-height: 30px;
239
+ }
240
+
241
+ @media screen and (max-width: 782px) {
242
+ .wp-picker-input-wrap .button.wp-picker-clear,
243
+ body.rtl .wp-picker-input-wrap .button.wp-picker-clear {
244
+ padding: 0 8px;
245
+ line-height: 2.14285714; /* 30px */
246
+ min-height: 32px;
247
+ }
248
+ }
249
+
250
+ /**
251
+ * End TEMP.
252
+ */
lib/css/settings.min.css CHANGED
@@ -1 +1 @@
1
- .tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-top-wrap>h1{float:left}body.rtl .tsf-top-wrap>h1{float:right}.tsf-metaboxes .metabox-holder{clear:both}.tsf-top-buttons{float:right}body.rtl .tsf-top-buttons{float:left}.tsf-bottom-buttons{text-align:right}body.rtl .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}#tsf-description-separator,#tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}#tsf-description-separator{margin-bottom:0}#tsf-description-separator input,#tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}#tsf-description-separator label,#tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}#tsf-description-separator input:hover+label,#tsf-description-separator label:hover,#tsf-title-separator input:hover+label,#tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}#tsf-description-separator input:checked+label,#tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}#tsf-home-title-location,#tsf-title-location{display:block}#tsf-home-title-location label span,#tsf-title-location label span{display:inline-block;min-width:60px;vertical-align:baseline}#tsf-home-title-location label .tsf-custom-blogname-js,#tsf-home-title-location label .tsf-custom-tagline-js,#tsf-home-title-location label .tsf-custom-title-js,#tsf-home-title-location label .tsf-sep-js,#tsf-title-location label .tsf-sep-js,#tsf-title-location label .tsf-title-additions-js{display:inline;min-width:0;white-space:pre}.tsf-nav-tab-wrapper,.tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-nav-tab{float:left;border:1px solid #ccc;margin-left:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600;border-radius:3px 3px 0 0}body.rtl .tsf-nav-tab{float:right;margin-left:0;margin-right:.5em}.tsf-nav-desktop{margin-left:7px}.tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}input.tsf-tabs-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-active-tab,.tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-tabs-radio:focus+label:not(.tsf-no-focus-ring){box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);border-color:#fff}.tsf-tabs-content{margin:1.33em auto 0}.tsf-tabs-content select{width:100%;max-width:max-content;text-overflow:ellipsis}.tsf-content-no-js{margin:1.33em auto}body.js .tsf-tabs-content{display:none}body.js .tsf-tabs-content.tsf-active-tab-content{display:block}
1
+ .tsf-metaboxes{box-sizing:border-box;max-width:690px;padding-bottom:20px}.tsf-top-wrap{width:100%;display:inline-block;vertical-align:top}.tsf-top-wrap>h1{float:left}body.rtl .tsf-top-wrap>h1{float:right}.tsf-metaboxes .metabox-holder{clear:both}.tsf-top-buttons{float:right}body.rtl .tsf-top-buttons{float:left}.tsf-bottom-buttons{text-align:right}body.rtl .tsf-bottom-buttons{text-align:left}.tsf-metaboxes .tsf-bottom-buttons input,.tsf-metaboxes .tsf-top-buttons input{margin-left:10px}#tsf-description-separator,#tsf-title-separator{display:table;width:100%;border-collapse:collapse;border-spacing:0}#tsf-description-separator{margin-bottom:0}#tsf-description-separator input,#tsf-title-separator input{display:none;float:left;width:0;min-width:0;opacity:0}#tsf-description-separator label,#tsf-title-separator label{display:inline-block;width:auto;min-width:28px;min-height:28px;margin:3px;-moz-margin-end:1.5px;-moz-margin-start:1.5px;padding:0 4px;border:1px solid #ccc;line-height:28px;text-align:center;cursor:pointer;box-shadow:-1px -1px 1px #aaa inset;font-size:16px}#tsf-description-separator input:hover+label,#tsf-description-separator label:hover,#tsf-title-separator input:hover+label,#tsf-title-separator label:hover{box-shadow:1px 1px 1px #aaa inset;background-color:#fff}#tsf-description-separator input:checked+label,#tsf-title-separator input:checked+label{box-shadow:1px 1px 1px #333 inset;background-color:#fff}#tsf-home-title-location,#tsf-title-location{display:block}#tsf-home-title-location label span,#tsf-title-location label span{display:inline-block;min-width:60px;vertical-align:baseline}#tsf-home-title-location label .tsf-custom-blogname-js,#tsf-home-title-location label .tsf-custom-tagline-js,#tsf-home-title-location label .tsf-custom-title-js,#tsf-home-title-location label .tsf-sep-js,#tsf-title-location label .tsf-sep-js,#tsf-title-location label .tsf-title-additions-js{display:inline;min-width:0;white-space:pre}.tsf-nav-tab-wrapper,.tsf-tab-no-js{position:relative;clear:both;width:100%;display:inline-block;border-bottom:1px solid #ccc;line-height:inherit;padding:8px 12px 0;margin:-4px -12px}.tsf-nav-tab{float:left;border:1px solid #ccc;margin-left:.5em;margin-bottom:-1px;padding:5px 14px;font-size:12px;line-height:16px;background:#f1f1f1;color:#555;font-weight:600;border-radius:3px 3px 0 0}body.rtl .tsf-nav-tab{float:right;margin-left:0;margin-right:.5em}.tsf-nav-desktop{margin-left:7px}.tsf-dashicons-tabs{font-size:initial;display:inline;vertical-align:text-bottom}input.tsf-tabs-radio{position:absolute;width:0;height:0;opacity:0;margin:0;padding:0;border:0;z-index:-1;-webkit-appearance:none;-moz-appearance:none;appearance:none}.tsf-active-tab,.tsf-tabs-radio:checked+label{background-color:inherit;border-bottom-color:#fff;color:#000}.tsf-tabs-radio:focus+label:not(.tsf-no-focus-ring){box-shadow:0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8);border-color:#fff}.tsf-tabs-content{margin:1.33em auto 0}.tsf-tabs-content select{width:100%;max-width:max-content;text-overflow:ellipsis}.tsf-content-no-js{margin:1.33em auto}body.js .tsf-tabs-content{display:none}body.js .tsf-tabs-content.tsf-active-tab-content{display:block}.wp-picker-input-wrap .button.wp-picker-clear{margin-left:6px;padding:0 8px;line-height:2.54545455;min-height:30px}body.rtl .wp-picker-input-wrap .button.wp-picker-clear{margin-right:6px;padding:0 8px;line-height:2.54545455;min-height:30px}@media screen and (max-width:782px){.wp-picker-input-wrap .button.wp-picker-clear,body.rtl .wp-picker-input-wrap .button.wp-picker-clear{padding:0 8px;line-height:2.14285714;min-height:32px}}
lib/js/ays.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/c.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -229,12 +229,9 @@ window.tsfC = function( $ ) {
229
  label = l10n.i18n.pixelsUsed.replace( /%1\$d/g, testWidth );
230
  label = label.replace( /%2\$d/g, guidelines.goodUpper );
231
 
232
- label = label + '<br>' + guidelineHelper;
233
 
234
- //= IE11 compat... great. Spread syntax please :)
235
- for ( let _c in classes ) {
236
- bar.classList.remove( classes[ _c ] );
237
- }
238
 
239
  // Set visuals.
240
  bar.classList.add( newClass );
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
229
  label = l10n.i18n.pixelsUsed.replace( /%1\$d/g, testWidth );
230
  label = label.replace( /%2\$d/g, guidelines.goodUpper );
231
 
232
+ label += '<br>' + guidelineHelper;
233
 
234
+ bar.classList.remove( ...Object.values( classes ) );
 
 
 
235
 
236
  // Set visuals.
237
  bar.classList.add( newClass );
lib/js/c.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfC=function(a){const b="undefined"!=typeof tsfCL10n&&tsfCL10n;let c=+(b.counterType||0);const d=()=>c,e={0:"tsf-counter-zero",1:"tsf-counter-one",2:"tsf-counter-two",3:"tsf-counter-three"},f=a=>{let d=a.e,f=tsf.decodeEntities(a.text),g=b.guidelines[a.field][a.type].chars,h=tsf.getStringLength(f),i="",j="",k={bad:"tsf-count-bad",okay:"tsf-count-okay",good:"tsf-count-good",unknown:"tsf-count-unknown"};switch(h?h<g.lower?(i=k.bad,j=b.i18n.guidelines.short.farTooShort):h<g.goodLower?(i=k.okay,j=b.i18n.guidelines.short.tooShort):h>g.upper?(i=k.bad,j=b.i18n.guidelines.short.farTooLong):h>g.goodUpper?(i=k.okay,j=b.i18n.guidelines.short.tooLong):(i=k.good,j=b.i18n.guidelines.short.good):(i=k.unknown,j=b.i18n.guidelines.short.empty),c){case 3:j=h.toString()+" - "+j;break;case 2:break;case 1:default:j=h.toString();}for(let b in d.innerHTML=j,k)d.classList.remove(k[b]);for(let b in e)d.classList.remove(e[b]);d.classList.add(i),d.classList.add(e[c])},g=()=>{a(window).trigger("tsf-counter-updated")},h=a=>{a&&++c,3<c&&(c=0),g()},i=()=>{h(!0);let b=".tsf-counter-wrap .tsf-ajax",d=0;tsf.resetAjaxLoader(".tsf-counter-wrap .tsf-ajax"),tsf.setAjaxLoader(".tsf-counter-wrap .tsf-ajax");let e={method:"POST",url:ajaxurl,datatype:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.l10n.nonces.edit_posts,val:c},async:!0,success:a=>{switch(a=tsf.convertJSONResponse(a),"success"===a.type&&(d=1),d){case 0:tsf.unsetAjaxLoader(b,!1);break;case 1:tsf.unsetAjaxLoader(b,!0);break;default:tsf.resetAjaxLoader(b);}},error:()=>{tsf.unsetAjaxLoader(b,!1)}};a.ajax(e)},j=()=>a(".tsf-counter").off("click.tsfC").on("click.tsfC",i),k=()=>{j()};return Object.assign({load:()=>{a(document.body).on("tsf-onload",k)}},{updatePixelCounter:a=>{let c=a.e,d=tsf.decodeEntities(a.text),e=b.guidelines[a.field][a.type].pixels,f=c.parentElement;if(!f)return;let g=f.querySelector(".tsf-pixel-counter-bar"),h=f.querySelector(".tsf-pixel-counter-shadow");if(!g||!h)return;h.innerHTML=tsf.escapeString(d);let i=h.offsetWidth,j="",k="",l="",m={bad:"tsf-pixel-counter-bad",okay:"tsf-pixel-counter-okay",good:"tsf-pixel-counter-good",unknown:"tsf-pixel-counter-unknown"};k=100*(i/e.goodUpper)+"%",i?i<e.lower?(j=m.bad,l=b.i18n.guidelines.long.farTooShort):i<e.goodLower?(j=m.okay,l=b.i18n.guidelines.long.tooShort):i>e.upper?(k=100*(e.upper/(i+2*(i-e.upper)/3))+"%",j=m.bad,l=b.i18n.guidelines.long.farTooLong):i>e.goodUpper?(j=m.okay,l=b.i18n.guidelines.long.tooLong,k="100%"):(j=m.good,l=b.i18n.guidelines.long.good):(j=m.unknown,k="100%",l=b.i18n.guidelines.long.empty);let n,o=g.querySelector(".tsf-pixel-counter-fluid");for(let c in n=b.i18n.pixelsUsed.replace(/%1\$d/g,i),n=n.replace(/%2\$d/g,e.goodUpper),n=n+"<br>"+l,m)g.classList.remove(m[c]);g.classList.add(j),o.style.width=k,g.dataset.desc=n,g.setAttribute("aria-label",tsf.escapeString(n.replace(/(<([^>]+)?>?)/ig," "))),tsfTT.triggerUpdate(g)},updateCharacterCounter:f,triggerCounterUpdate:g,resetCounterListener:j,getCounterType:d},{counterClasses:e,l10n:b})}(jQuery),jQuery(window.tsfC.load);
1
+ 'use strict';window.tsfC=function(a){const b="undefined"!=typeof tsfCL10n&&tsfCL10n;let c=+(b.counterType||0);const d=()=>c,e={0:"tsf-counter-zero",1:"tsf-counter-one",2:"tsf-counter-two",3:"tsf-counter-three"},f=a=>{let d=a.e,f=tsf.decodeEntities(a.text),g=b.guidelines[a.field][a.type].chars,h=tsf.getStringLength(f),i="",j="",k={bad:"tsf-count-bad",okay:"tsf-count-okay",good:"tsf-count-good",unknown:"tsf-count-unknown"};switch(h?h<g.lower?(i=k.bad,j=b.i18n.guidelines.short.farTooShort):h<g.goodLower?(i=k.okay,j=b.i18n.guidelines.short.tooShort):h>g.upper?(i=k.bad,j=b.i18n.guidelines.short.farTooLong):h>g.goodUpper?(i=k.okay,j=b.i18n.guidelines.short.tooLong):(i=k.good,j=b.i18n.guidelines.short.good):(i=k.unknown,j=b.i18n.guidelines.short.empty),c){case 3:j=h.toString()+" - "+j;break;case 2:break;case 1:default:j=h.toString();}for(let b in d.innerHTML=j,k)d.classList.remove(k[b]);for(let b in e)d.classList.remove(e[b]);d.classList.add(i),d.classList.add(e[c])},g=()=>{a(window).trigger("tsf-counter-updated")},h=a=>{a&&++c,3<c&&(c=0),g()},i=()=>{h(!0);let b=".tsf-counter-wrap .tsf-ajax",d=0;tsf.resetAjaxLoader(".tsf-counter-wrap .tsf-ajax"),tsf.setAjaxLoader(".tsf-counter-wrap .tsf-ajax");let e={method:"POST",url:ajaxurl,datatype:"json",data:{action:"the_seo_framework_update_counter",nonce:tsf.l10n.nonces.edit_posts,val:c},async:!0,success:a=>{switch(a=tsf.convertJSONResponse(a),"success"===a.type&&(d=1),d){case 0:tsf.unsetAjaxLoader(b,!1);break;case 1:tsf.unsetAjaxLoader(b,!0);break;default:tsf.resetAjaxLoader(b);}},error:()=>{tsf.unsetAjaxLoader(b,!1)}};a.ajax(e)},j=()=>a(".tsf-counter").off("click.tsfC").on("click.tsfC",i),k=()=>{j()};return Object.assign({load:()=>{a(document.body).on("tsf-onload",k)}},{updatePixelCounter:a=>{let c=a.e,d=tsf.decodeEntities(a.text),e=b.guidelines[a.field][a.type].pixels,f=c.parentElement;if(!f)return;let g=f.querySelector(".tsf-pixel-counter-bar"),h=f.querySelector(".tsf-pixel-counter-shadow");if(!g||!h)return;h.innerHTML=tsf.escapeString(d);let i=h.offsetWidth,j="",k="",l="",m={bad:"tsf-pixel-counter-bad",okay:"tsf-pixel-counter-okay",good:"tsf-pixel-counter-good",unknown:"tsf-pixel-counter-unknown"};k=100*(i/e.goodUpper)+"%",i?i<e.lower?(j=m.bad,l=b.i18n.guidelines.long.farTooShort):i<e.goodLower?(j=m.okay,l=b.i18n.guidelines.long.tooShort):i>e.upper?(k=100*(e.upper/(i+2*(i-e.upper)/3))+"%",j=m.bad,l=b.i18n.guidelines.long.farTooLong):i>e.goodUpper?(j=m.okay,l=b.i18n.guidelines.long.tooLong,k="100%"):(j=m.good,l=b.i18n.guidelines.long.good):(j=m.unknown,k="100%",l=b.i18n.guidelines.long.empty);let n,o=g.querySelector(".tsf-pixel-counter-fluid");n=b.i18n.pixelsUsed.replace(/%1\$d/g,i),n=n.replace(/%2\$d/g,e.goodUpper),n+="<br>"+l,g.classList.remove(...Object.values(m)),g.classList.add(j),o.style.width=k,g.dataset.desc=n,g.setAttribute("aria-label",tsf.escapeString(n.replace(/(<([^>]+)?>?)/ig," "))),tsfTT.triggerUpdate(g)},updateCharacterCounter:f,triggerCounterUpdate:g,resetCounterListener:j,getCounterType:d},{counterClasses:e,l10n:b})}(jQuery),jQuery(window.tsfC.load);
lib/js/description.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/gbc.js CHANGED
@@ -11,7 +11,7 @@
11
 
12
  /**
13
  * The SEO Framework plugin
14
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
15
  *
16
  * This program is free software: you can redistribute it and/or modify
17
  * it under the terms of the GNU General Public License version 3 as published
11
 
12
  /**
13
  * The SEO Framework plugin
14
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
15
  *
16
  * This program is free software: you can redistribute it and/or modify
17
  * it under the terms of the GNU General Public License version 3 as published
lib/js/le.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -44,25 +44,38 @@ window.tsfLe = function( $ ) {
44
  */
45
  const l10n = 'undefined' !== typeof tsfLeL10n && tsfLeL10n;
46
 
47
- let updateTimeout;
48
  /**
49
- * Runs after a list edit item has been updated.
50
  *
51
- * @since 4.0.0
52
  * @access private
53
  *
54
  * @function
55
  * @return {undefined}
56
  */
57
- const _updated = () => {
58
 
59
- clearTimeout( updateTimeout );
60
 
61
- updateTimeout = setTimeout( () => {
62
- tsfTT.triggerReset();
63
  }, 50 ); // 20fps
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  /**
67
  * Sets inline post values for quick-edit.
68
  *
@@ -153,25 +166,15 @@ window.tsfLe = function( $ ) {
153
  element = document.getElementById( 'autodescription-quick[%s]'.replace( '%s', index ) );
154
  if ( ! element ) continue;
155
 
156
- switch ( index ) {
157
- case 'noindex':
158
- case 'nofollow':
159
- case 'noarchive':
160
- tsf.selectByValue( element, data[ index ].value );
161
-
162
- // Do `sprintf( 'Default (%s)', x.default )`.
163
- let _default = element.querySelector( '[value="0"]' );
164
- if ( _default )
165
- _default.innerHTML = _default.innerHTML.replace( '%s', tsf.decodeEntities( data[ index ].default ) );
166
- break;
167
-
168
- case 'canonical':
169
- case 'redirect':
170
- element.value = tsf.decodeEntities( data[ index ].value );
171
- break;
172
 
173
- default:
174
- break;
 
 
 
 
175
  }
176
  }
177
  }
@@ -186,6 +189,7 @@ window.tsfLe = function( $ ) {
186
  * @return {undefined}
187
  */
188
  const _setListeners = () => {
 
189
  document.addEventListener( 'tsfLeUpdated', _updated );
190
  }
191
 
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
44
  */
45
  const l10n = 'undefined' !== typeof tsfLeL10n && tsfLeL10n;
46
 
47
+ let dispatchTimeout;
48
  /**
49
+ * Dispatches Le update event.
50
  *
51
+ * @since 4.0.5
52
  * @access private
53
  *
54
  * @function
55
  * @return {undefined}
56
  */
57
+ const _dispatchUpdate = () => {
58
 
59
+ clearTimeout( dispatchTimeout );
60
 
61
+ dispatchTimeout = setTimeout( () => {
62
+ document.dispatchEvent( new Event( 'tsfLeUpdated' ) );
63
  }, 50 ); // 20fps
64
  }
65
 
66
+ /**
67
+ * Runs after a list edit item has been updated.
68
+ *
69
+ * @since 4.0.0
70
+ * @access private
71
+ *
72
+ * @function
73
+ * @return {undefined}
74
+ */
75
+ const _updated = () => {
76
+ tsfTT && tsfTT.triggerReset();
77
+ }
78
+
79
  /**
80
  * Sets inline post values for quick-edit.
81
  *
166
  element = document.getElementById( 'autodescription-quick[%s]'.replace( '%s', index ) );
167
  if ( ! element ) continue;
168
 
169
+ if ( data[ index ].isSelect ) {
170
+ tsf.selectByValue( element, data[ index ].value );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ // Do `sprintf( 'Default (%s)', x.default )`.
173
+ let _default = element.querySelector( '[value="0"]' );
174
+ if ( _default )
175
+ _default.innerHTML = _default.innerHTML.replace( '%s', tsf.decodeEntities( data[ index ].default ) );
176
+ } else {
177
+ element.value = tsf.decodeEntities( data[ index ].value );
178
  }
179
  }
180
  }
189
  * @return {undefined}
190
  */
191
  const _setListeners = () => {
192
+ document.addEventListener( 'tsfLeDispatchUpdate', _dispatchUpdate );
193
  document.addEventListener( 'tsfLeUpdated', _updated );
194
  }
195
 
lib/js/le.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfLe=function(a){const b="undefined"!=typeof tsfLeL10n&&tsfLeL10n;let c;const d=()=>{clearTimeout(c),c=setTimeout(()=>{tsfTT.triggerReset()},50)},e=a=>{if("object"==typeof a&&(a=window.inlineEditPost.getId(a)),!a)return;let b,c=document.getElementById("tsfLeData["+a+"]");try{b=JSON.parse(c.dataset.le)||void 0}catch(a){}if(!b)return;let d;for(let c in b)if(d=document.getElementById("autodescription-quick[%s]".replace("%s",c)),d)switch(c){case"noindex":case"nofollow":case"noarchive":tsf.selectByValue(d,b[c].value);let a=d.querySelector("[value=\"0\"]");a&&(a.innerHTML=a.innerHTML.replace("%s",tsf.decodeEntities(b[c].default)));break;case"canonical":case"redirect":d.value=tsf.decodeEntities(b[c].value);break;default:}},f=a=>{if("object"==typeof a&&(a=window.inlineEditTax.getId(a)),!a)return;let b,c=document.getElementById("tsfLeData["+a+"]");try{b=JSON.parse(c.dataset.le)||void 0}catch(a){}if(!b)return;let d;for(let c in b)if(d=document.getElementById("autodescription-quick[%s]".replace("%s",c)),d)switch(c){case"noindex":case"nofollow":case"noarchive":tsf.selectByValue(d,b[c].value);let a=d.querySelector("[value=\"0\"]");a&&(a.innerHTML=a.innerHTML.replace("%s",tsf.decodeEntities(b[c].default)));break;case"canonical":case"redirect":d.value=tsf.decodeEntities(b[c].value);break;default:}},g=()=>{document.addEventListener("tsfLeUpdated",d)},h=()=>{let a;window.inlineEditPost&&(a="edit"in window.inlineEditPost&&window.inlineEditPost.edit,a&&(window.inlineEditPost.edit=function(b){let c=a.apply(this,arguments);return e(b),c})),window.inlineEditTax&&(a="edit"in window.inlineEditTax&&window.inlineEditTax.edit,a&&(window.inlineEditTax.edit=function(b){let c=a.apply(this,arguments);return f(b),c}))};return Object.assign({load:()=>{a(document.body).ready(g),a(document.body).ready(h)}},{},{l10n:b})}(jQuery),jQuery(window.tsfLe.load);
1
+ 'use strict';window.tsfLe=function(a){const b="undefined"!=typeof tsfLeL10n&&tsfLeL10n;let c;const d=()=>{clearTimeout(c),c=setTimeout(()=>{document.dispatchEvent(new Event("tsfLeUpdated"))},50)},e=()=>{tsfTT&&tsfTT.triggerReset()},f=a=>{if("object"==typeof a&&(a=window.inlineEditPost.getId(a)),!a)return;let b,c=document.getElementById("tsfLeData["+a+"]");try{b=JSON.parse(c.dataset.le)||void 0}catch(a){}if(!b)return;let d;for(let c in b)if(d=document.getElementById("autodescription-quick[%s]".replace("%s",c)),d)switch(c){case"noindex":case"nofollow":case"noarchive":tsf.selectByValue(d,b[c].value);let a=d.querySelector("[value=\"0\"]");a&&(a.innerHTML=a.innerHTML.replace("%s",tsf.decodeEntities(b[c].default)));break;case"canonical":case"redirect":d.value=tsf.decodeEntities(b[c].value);break;default:}},g=a=>{if("object"==typeof a&&(a=window.inlineEditTax.getId(a)),!a)return;let b,c=document.getElementById("tsfLeData["+a+"]");try{b=JSON.parse(c.dataset.le)||void 0}catch(a){}if(!b)return;let d;for(let c in b)if(d=document.getElementById("autodescription-quick[%s]".replace("%s",c)),d)if(b[c].isSelect){tsf.selectByValue(d,b[c].value);let a=d.querySelector("[value=\"0\"]");a&&(a.innerHTML=a.innerHTML.replace("%s",tsf.decodeEntities(b[c].default)))}else d.value=tsf.decodeEntities(b[c].value)},h=()=>{document.addEventListener("tsfLeDispatchUpdate",d),document.addEventListener("tsfLeUpdated",e)},i=()=>{let a;window.inlineEditPost&&(a="edit"in window.inlineEditPost&&window.inlineEditPost.edit,a&&(window.inlineEditPost.edit=function(b){let c=a.apply(this,arguments);return f(b),c})),window.inlineEditTax&&(a="edit"in window.inlineEditTax&&window.inlineEditTax.edit,a&&(window.inlineEditTax.edit=function(b){let c=a.apply(this,arguments);return g(b),c}))};return Object.assign({load:()=>{a(document.body).ready(h),a(document.body).ready(i)}},{},{l10n:b})}(jQuery),jQuery(window.tsfLe.load);
lib/js/post.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/pt-gb.js CHANGED
@@ -7,7 +7,7 @@
7
 
8
  /**
9
  * The SEO Framework plugin
10
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
11
  *
12
  * This program is free software: you can redistribute it and/or modify
13
  * it under the terms of the GNU General Public License version 3 as published
7
 
8
  /**
9
  * The SEO Framework plugin
10
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
11
  *
12
  * This program is free software: you can redistribute it and/or modify
13
  * it under the terms of the GNU General Public License version 3 as published
lib/js/pt.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/settings.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -76,6 +76,82 @@ window.tsfSettings = function( $ ) {
76
 
77
  $( '#autodescription-site-settings\\[display_character_counter\\]' ).on( 'click', togglePixelCounterDisplay );
78
  $( '#autodescription-site-settings\\[display_pixel_counter\\]' ).on( 'click', togglePixelCounterDisplay );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
  /**
@@ -129,6 +205,7 @@ window.tsfSettings = function( $ ) {
129
  * Initializes Titles' meta input.
130
  *
131
  * @since 4.0.0
 
132
  * @access private
133
  *
134
  * @function
@@ -136,7 +213,7 @@ window.tsfSettings = function( $ ) {
136
  */
137
  const _initTitleSettings = () => {
138
 
139
- let additionsToggle = document.getElementById( '#autodescription-site-settings[title_rem_additions]' );
140
 
141
  /**
142
  * Toggles example on Left/Right selection of global title options.
@@ -205,19 +282,11 @@ window.tsfSettings = function( $ ) {
205
  * @return {undefined}
206
  */
207
  const updateSeparator = ( event ) => {
208
- let val = event.target.value,
209
  separator = '';
210
 
211
- switch ( val ) {
212
- case 'pipe':
213
- separator = '|';
214
- break;
215
 
216
- default:
217
- // XSS ok: val is sanitized by PHP: s_title_separator().
218
- separator = $( '<div/>' ).html( "&" + val + ";" ).text();
219
- break;
220
- }
221
  $( ".tsf-sep-js" ).text( ' ' + separator + ' ' );
222
 
223
  $( window ).trigger( 'tsf-title-sep-updated', [ separator ] );
@@ -549,6 +618,7 @@ window.tsfSettings = function( $ ) {
549
  "#autodescription-site-settings\\[google_verification\\]",
550
  "#autodescription-site-settings\\[bing_verification\\]",
551
  "#autodescription-site-settings\\[yandex_verification\\]",
 
552
  "#autodescription-site-settings\\[pint_verification\\]",
553
  ].join( ', ' ) );
554
 
@@ -762,7 +832,7 @@ window.tsfSettings = function( $ ) {
762
  * @return {undefined}
763
  */
764
  load: () => {
765
- $( 'div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info' ).insertAfter( '.tsf-top-wrap' )
766
 
767
  $( document.body ).on( 'tsf-onload', _loadSettings );
768
  $( document.body ).on( 'tsf-ready', _readySettings );
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
76
 
77
  $( '#autodescription-site-settings\\[display_character_counter\\]' ).on( 'click', togglePixelCounterDisplay );
78
  $( '#autodescription-site-settings\\[display_pixel_counter\\]' ).on( 'click', togglePixelCounterDisplay );
79
+
80
+ // This prevents notice-removal checks before they're added.
81
+ let init = false;
82
+ /**
83
+ * Triggers displaying/hiding of post type warnings on the settings page.
84
+ *
85
+ * @since 4.0.5
86
+ * @access private
87
+ *
88
+ * @function
89
+ * @param {!jQuery.Event} event
90
+ * @return {undefined}
91
+ */
92
+ const checkDisabledPT = ( event ) => {
93
+
94
+ if ( ! event.target.name ) return;
95
+
96
+ let postType = event.target.name.split( /(?:.+\[)(.+?)(?:])/ ).join('');
97
+ if ( $( event.target ).is( ':checked' ) ) {
98
+ setDisabledPT( postType );
99
+ } else {
100
+ init && unsetDisabledPT( postType );
101
+ }
102
+ }
103
+ const helpTemplate = wp.template( 'tsf-disabled-post-type-help' )();
104
+ /**
105
+ * @param {string} postType
106
+ * @return {string} The cloned input class used to send POST data.
107
+ */
108
+ const getCloneClass = postType => 'tsf-disabled-post-type-input-clone-' + postType;
109
+ /**
110
+ * @param {string} postType
111
+ * @return {array} A list of affected post type settings.
112
+ */
113
+ const getPostTypeSettings = ( postType ) => [
114
+ document.getElementById( 'autodescription-site-settings[noindex_post_types][' + postType + ']' ),
115
+ document.getElementById( 'autodescription-site-settings[nofollow_post_types][' + postType + ']' ),
116
+ document.getElementById( 'autodescription-site-settings[noarchive_post_types][' + postType + ']' ),
117
+ ].filter( el => el );
118
+ const setDisabledPT = ( postType ) => {
119
+ getPostTypeSettings( postType ).forEach( element => {
120
+ let clone = element.cloneNode( true );
121
+ clone.type = 'hidden';
122
+ // Note that this might cause inconsistencies when other JS elements try to amend the data via ID.
123
+ // However, they should use 'getElementsByName', anyway.
124
+ clone.id += '-cloned' ;
125
+ clone.classList.add( getCloneClass( postType ) );
126
+
127
+ element.disabled = true;
128
+ element.dataset.hasWarning = true;
129
+
130
+ $( element.closest( 'label' ) ).append( helpTemplate ).append( clone );
131
+ } );
132
+
133
+ tsfTT.triggerReset();
134
+ }
135
+ const unsetDisabledPT = ( postType ) => {
136
+ getPostTypeSettings( postType ).forEach( element => {
137
+ if ( ! element.dataset.hasWarning ) return;
138
+
139
+ // 'tsf-post-type-warning' is defined at `../inc/views/templates/settings/settings.php`
140
+ element.closest( 'label' ).querySelector( '.tsf-post-type-warning' ).remove();
141
+
142
+ document.querySelectorAll( '.' + getCloneClass( postType ) ).forEach( ( clone ) => {
143
+ clone.remove();
144
+ } );
145
+
146
+ element.disabled = false;
147
+ element.dataset.hasWarning = false;
148
+ } );
149
+ }
150
+ $( '.tsf-disabled-post-types' )
151
+ .on( 'change.tsfSetPostType', checkDisabledPT )
152
+ .trigger( 'change.tsfSetPostType' );
153
+
154
+ init = true;
155
  }
156
 
157
  /**
205
  * Initializes Titles' meta input.
206
  *
207
  * @since 4.0.0
208
+ * @since 4.0.5 Fixed the additionsToggle getter.
209
  * @access private
210
  *
211
  * @function
213
  */
214
  const _initTitleSettings = () => {
215
 
216
+ let additionsToggle = document.getElementById( 'autodescription-site-settings[title_rem_additions]' );
217
 
218
  /**
219
  * Toggles example on Left/Right selection of global title options.
282
  * @return {undefined}
283
  */
284
  const updateSeparator = ( event ) => {
285
+ let entity = event.target.dataset.entity,
286
  separator = '';
287
 
288
+ separator = $( '<div/>' ).html( entity ).text();
 
 
 
289
 
 
 
 
 
 
290
  $( ".tsf-sep-js" ).text( ' ' + separator + ' ' );
291
 
292
  $( window ).trigger( 'tsf-title-sep-updated', [ separator ] );
618
  "#autodescription-site-settings\\[google_verification\\]",
619
  "#autodescription-site-settings\\[bing_verification\\]",
620
  "#autodescription-site-settings\\[yandex_verification\\]",
621
+ "#autodescription-site-settings\\[baidu_verification\\]",
622
  "#autodescription-site-settings\\[pint_verification\\]",
623
  ].join( ', ' ) );
624
 
832
  * @return {undefined}
833
  */
834
  load: () => {
835
+ $( 'div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info' ).insertAfter( '.tsf-top-wrap' );
836
 
837
  $( document.body ).on( 'tsf-onload', _loadSettings );
838
  $( document.body ).on( 'tsf-ready', _readySettings );
lib/js/settings.min.js CHANGED
@@ -1 +1 @@
1
- 'use strict';window.tsfSettings=function(a){const b="undefined"!=typeof tsfSettingsL10n&&tsfSettingsL10n,c=()=>{const b=b=>{a(b.target).is(":checked")?(a(".tsf-pixel-counter-wrap").show(),tsfC.triggerCounterUpdate()):a(".tsf-pixel-counter-wrap").hide()};a("#autodescription-site-settings\\[display_character_counter\\]").on("click",b),a("#autodescription-site-settings\\[display_pixel_counter\\]").on("click",b)},d=()=>{let b=a(".tsf-color-picker");b.length&&a.each(b,(b,c)=>{let d=a(c),e="",f=d.data("tsf-default-color");d.wpColorPicker({defaultColor:f,width:238,change:()=>{e=d.wpColorPicker("color"),""===e&&(e=f),d.val(e),tsfAys.registerChange()},clear:()=>{f.length&&(d.val(f),d.closest(".wp-picker-container").find(".wp-color-result").css("backgroundColor",f)),tsfAys.registerChange()},palettes:!1})})},e=()=>{let b=document.getElementById("#autodescription-site-settings[title_rem_additions]");a(b).on("change",()=>{let c=a(".tsf-title-additions-js");a(b).is(":checked")?c.css("display","none"):c.css("display","inline")}),a(b).trigger("change");a("#tsf-title-location input").on("click",b=>{let c=a(".tsf-title-additions-example-left"),d=a(".tsf-title-additions-example-right");"right"===a(b.target).val()?(c.css("display","none"),d.css("display","inline")):(c.css("display","inline"),d.css("display","none"))});a("#tsf-title-prefixes-toggle :input").on("click",b=>{let c=a(b.target),d=a(".tsf-title-prefix-example");c.is(":checked")?d.css("display","none"):d.css("display","inline")});a("#tsf-title-separator :input").on("click",b=>{let c=b.target.value,d="";switch(c){case"pipe":d="|";break;default:d=a("<div/>").html("&"+c+";").text();}a(".tsf-sep-js").text(" "+d+" "),a(window).trigger("tsf-title-sep-updated",[d])})},f=()=>{const c=document.getElementById("autodescription-site-settings[homepage_title]"),d=document.getElementById("autodescription-site-settings[homepage_title_tagline]"),e=document.getElementById("autodescription-site-settings[homepage_tagline]"),f=tsf.escapeString(b.i18n.protectedTitle),g=tsf.escapeString(b.i18n.privateTitle);tsfTitle.setInputElement(c);const h=()=>{let b=tsfTitle.getState("additionPlacement"),c="after";tsf.l10n.states.isRTL?"right"===a("#tsf-home-title-location input:checked").val()&&(c="before"):"left"===a("#tsf-home-title-location input:checked").val()&&(c="before"),c!==b&&tsfTitle.updateState("additionPlacement",c)};h(),a("#tsf-home-title-location").on("click",":input",h);const i=a=>{let b=tsfTitle.getState("prefixValue"),c="";switch(a){case"password":c=f;break;case"private":c=g;break;default:case"public":c="";}c!==b&&tsfTitle.updateState("prefixValue",c)};b.states.isFrontPrivate?i("private"):b.states.isFrontProtected&&i("password");a(c).on("input.tsfInputTitle",b=>{let c=a(".tsf-custom-title-js"),d=tsf.decodeEntities(tsf.sDoubleSpace(b.target.value.trim()));d.length?c.html(tsf.escapeString(d)):c.html(tsf.escapeString(tsf.decodeEntities(tsfTitle.getState("defaultTitle"))))}),a(c).trigger("input.tsfInputTitle");let j,k=a(".tsf-custom-tagline-js");const l=()=>{clearTimeout(j),j=setTimeout(()=>{let b=tsfTitle.getState("additionValue");b=tsf.decodeEntities(tsf.sDoubleSpace(b.trim())),b.length&&tsfTitle.getState("useTagline")?(k.html(tsf.escapeString(b)),a(".tsf-custom-blogname-js").show()):a(".tsf-custom-blogname-js").hide()})};a(d).on("input.tsfInputTagline",()=>{let a=tsfTitle.getState("additionValue"),b=d.value.trim();b.length||(b=d.placeholder||""),b=tsf.escapeString(tsf.decodeEntities(b.trim())),a!==b&&(tsfTitle.updateState("additionValue",b),l())}),a(d).trigger("input.tsfInputTagline");a(e).on("change.tsfToggleTagline",a=>{let b=!1;a.target.checked?(b=!0,d.readOnly=!1):(b=!1,d.readOnly=!0),tsfTitle.updateState("useTagline",b),l()}),a(e).trigger("change.tsfToggleTagline");a(window).on("tsf-title-sep-updated",(a,b)=>{tsfTitle.updateState("separator",b)}),tsfTitle.enqueueUnregisteredInputTrigger()},g=()=>{tsfDescription.setInputElement(document.getElementById("autodescription-site-settings[homepage_description]")),tsfDescription.enqueueUnregisteredInputTrigger()},h=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(),tsfDescription.enqueueUnregisteredInputTrigger()};a(document).on("postbox-toggled",function(a,c){if("autodescription-homepage-settings"===c.id){let a=c.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&b()}}),a("#tsf-homepage-tab-general").on("tsf-tab-toggled",tsfTitle.enqueueUnregisteredInputTrigger)},i=()=>{const b=a("#autodescription-site-settings\\[set_copyright_directives\\]"),c=a("#autodescription-site-settings\\[max_snippet_length\\], #autodescription-site-settings\\[max_image_preview\\], #autodescription-site-settings\\[max_video_preview\\]");if(b.length&&c.length){b.on("change.tsfToggleDirectives",b=>{b.target.checked?(c.prop("disabled",!1),a(".tsf-toggle-directives-surrogate").remove()):(c.prop("disabled",!0),c.each((b,c)=>{a("<input />").attr("type","hidden").attr("name",c.name||"").val(c.value||0).addClass("tsf-toggle-directives-surrogate").insertAfter(c)}))}),b.trigger("change.tsfToggleDirectives")}},j=()=>{const b=a("#autodescription-site-settings\\[google_verification\\], #autodescription-site-settings\\[bing_verification\\], #autodescription-site-settings\\[yandex_verification\\], #autodescription-site-settings\\[pint_verification\\]");if(b.length){const a=a=>{let b=a.originalEvent.clipboardData&&a.originalEvent.clipboardData.getData("text")||void 0;if(b){let c=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(b);c&&2 in c&&"string"==typeof c[2]&&c[2].length&&(a.stopPropagation(),a.preventDefault(),a.target.value=c[2],tsfAys.registerChange())}};b.on("paste",a)}},k=()=>{c(),e(),f(),g(),h(),i(),j(),d()},l=()=>{tsfSocial.initTitleInputs({ref:document.getElementById("tsf-title-reference"),meta:document.getElementById("autodescription-site-settings[homepage_title]"),og:document.getElementById("autodescription-site-settings[homepage_og_title]"),tw:document.getElementById("autodescription-site-settings[homepage_twitter_title]")}),tsfSocial.initDescriptionInputs({ref:document.getElementById("tsf-description-reference"),meta:document.getElementById("autodescription-site-settings[homepage_description]"),og:document.getElementById("autodescription-site-settings[homepage_og_description]"),tw:document.getElementById("autodescription-site-settings[homepage_twitter_description]")})},m=()=>confirm(b.i18n.confirmReset),n=()=>{a(".tsf-tabs-radio").on("change",(b,c)=>{let d=a(b.target);if(!d.is(":checked"))return;c="boolean"==typeof c&&c;let e=b.target.id,f=b.target.name,g="tsf-active-tab-content",h="tsf-tab-active",i=a("."+g),j=d.closest(".tsf-nav-tab-wrapper").find("."+h),k=i.find("input:invalid, select:invalid, textarea:invalid");if(k.length)return k[0].reportValidity(),j.prop("checked",!0),d.prop("checked",!1),b.stopPropagation(),b.preventDefault(),!1;let l=a("#"+e+"-content");if(j.removeClass(h),j.siblings("label").removeClass("tsf-no-focus-ring"),d.addClass(h),c){let b=a("."+f+"-content");b.removeClass(g).hide(),l.addClass(g).show(),a("#"+e).trigger("tsf-tab-toggled")}else if(l.length&&!l.is(i)){let b=a("."+f+"-content");b.fadeOut(150,function(){a(this).removeClass(g)}),setTimeout(()=>{l.addClass(g).fadeIn(250)},150),setTimeout(()=>{a("#"+e).trigger("tsf-tab-toggled")},175)}});a(".tsf-nav-tab-wrapper").on("click.tsfNavTab",".tsf-nav-tab",a=>{a.currentTarget.classList.add("tsf-no-focus-ring")});a(document.body).on("tsf-ready",()=>{a(".tsf-tabs-radio:checked").each((b,c)=>{a(c).trigger("change",[!0])})})};return Object.assign({load:()=>{a("div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info").insertAfter(".tsf-top-wrap"),a(document.body).on("tsf-onload",k),a(document.body).on("tsf-ready",l),a(".tsf-js-confirm-reset").on("click",m),n()}},{},{l10n:b})}(jQuery),jQuery(window.tsfSettings.load);
1
+ 'use strict';window.tsfSettings=function(a){const b="undefined"!=typeof tsfSettingsL10n&&tsfSettingsL10n,c=()=>{const b=b=>{a(b.target).is(":checked")?(a(".tsf-pixel-counter-wrap").show(),tsfC.triggerCounterUpdate()):a(".tsf-pixel-counter-wrap").hide()};a("#autodescription-site-settings\\[display_character_counter\\]").on("click",b),a("#autodescription-site-settings\\[display_pixel_counter\\]").on("click",b);let c=!1;const d=b=>{if(b.target.name){let d=b.target.name.split(/(?:.+\[)(.+?)(?:])/).join("");a(b.target).is(":checked")?h(d):c&&i(d)}},e=wp.template("tsf-disabled-post-type-help")(),f=a=>"tsf-disabled-post-type-input-clone-"+a,g=a=>[document.getElementById("autodescription-site-settings[noindex_post_types]["+a+"]"),document.getElementById("autodescription-site-settings[nofollow_post_types]["+a+"]"),document.getElementById("autodescription-site-settings[noarchive_post_types]["+a+"]")].filter(a=>a),h=b=>{g(b).forEach(c=>{let d=c.cloneNode(!0);d.type="hidden",d.id+="-cloned",d.classList.add(f(b)),c.disabled=!0,c.dataset.hasWarning=!0,a(c.closest("label")).append(e).append(d)}),tsfTT.triggerReset()},i=a=>{g(a).forEach(b=>{b.dataset.hasWarning&&(b.closest("label").querySelector(".tsf-post-type-warning").remove(),document.querySelectorAll("."+f(a)).forEach(a=>{a.remove()}),b.disabled=!1,b.dataset.hasWarning=!1)})};a(".tsf-disabled-post-types").on("change.tsfSetPostType",d).trigger("change.tsfSetPostType"),c=!0},d=()=>{let b=a(".tsf-color-picker");b.length&&a.each(b,(b,c)=>{let d=a(c),e="",f=d.data("tsf-default-color");d.wpColorPicker({defaultColor:f,width:238,change:()=>{e=d.wpColorPicker("color"),""===e&&(e=f),d.val(e),tsfAys.registerChange()},clear:()=>{f.length&&(d.val(f),d.closest(".wp-picker-container").find(".wp-color-result").css("backgroundColor",f)),tsfAys.registerChange()},palettes:!1})})},e=()=>{let b=document.getElementById("autodescription-site-settings[title_rem_additions]");a(b).on("change",()=>{let c=a(".tsf-title-additions-js");a(b).is(":checked")?c.css("display","none"):c.css("display","inline")}),a(b).trigger("change");a("#tsf-title-location input").on("click",b=>{let c=a(".tsf-title-additions-example-left"),d=a(".tsf-title-additions-example-right");"right"===a(b.target).val()?(c.css("display","none"),d.css("display","inline")):(c.css("display","inline"),d.css("display","none"))});a("#tsf-title-prefixes-toggle :input").on("click",b=>{let c=a(b.target),d=a(".tsf-title-prefix-example");c.is(":checked")?d.css("display","none"):d.css("display","inline")});a("#tsf-title-separator :input").on("click",b=>{let c=b.target.dataset.entity,d="";d=a("<div/>").html(c).text(),a(".tsf-sep-js").text(" "+d+" "),a(window).trigger("tsf-title-sep-updated",[d])})},f=()=>{const c=document.getElementById("autodescription-site-settings[homepage_title]"),d=document.getElementById("autodescription-site-settings[homepage_title_tagline]"),e=document.getElementById("autodescription-site-settings[homepage_tagline]"),f=tsf.escapeString(b.i18n.protectedTitle),g=tsf.escapeString(b.i18n.privateTitle);tsfTitle.setInputElement(c);const h=()=>{let b=tsfTitle.getState("additionPlacement"),c="after";tsf.l10n.states.isRTL?"right"===a("#tsf-home-title-location input:checked").val()&&(c="before"):"left"===a("#tsf-home-title-location input:checked").val()&&(c="before"),c!==b&&tsfTitle.updateState("additionPlacement",c)};h(),a("#tsf-home-title-location").on("click",":input",h);const i=a=>{let b=tsfTitle.getState("prefixValue"),c="";switch(a){case"password":c=f;break;case"private":c=g;break;default:case"public":c="";}c!==b&&tsfTitle.updateState("prefixValue",c)};b.states.isFrontPrivate?i("private"):b.states.isFrontProtected&&i("password");a(c).on("input.tsfInputTitle",b=>{let c=a(".tsf-custom-title-js"),d=tsf.decodeEntities(tsf.sDoubleSpace(b.target.value.trim()));d.length?c.html(tsf.escapeString(d)):c.html(tsf.escapeString(tsf.decodeEntities(tsfTitle.getState("defaultTitle"))))}),a(c).trigger("input.tsfInputTitle");let j,k=a(".tsf-custom-tagline-js");const l=()=>{clearTimeout(j),j=setTimeout(()=>{let b=tsfTitle.getState("additionValue");b=tsf.decodeEntities(tsf.sDoubleSpace(b.trim())),b.length&&tsfTitle.getState("useTagline")?(k.html(tsf.escapeString(b)),a(".tsf-custom-blogname-js").show()):a(".tsf-custom-blogname-js").hide()})};a(d).on("input.tsfInputTagline",()=>{let a=tsfTitle.getState("additionValue"),b=d.value.trim();b.length||(b=d.placeholder||""),b=tsf.escapeString(tsf.decodeEntities(b.trim())),a!==b&&(tsfTitle.updateState("additionValue",b),l())}),a(d).trigger("input.tsfInputTagline");a(e).on("change.tsfToggleTagline",a=>{let b=!1;a.target.checked?(b=!0,d.readOnly=!1):(b=!1,d.readOnly=!0),tsfTitle.updateState("useTagline",b),l()}),a(e).trigger("change.tsfToggleTagline");a(window).on("tsf-title-sep-updated",(a,b)=>{tsfTitle.updateState("separator",b)}),tsfTitle.enqueueUnregisteredInputTrigger()},g=()=>{tsfDescription.setInputElement(document.getElementById("autodescription-site-settings[homepage_description]")),tsfDescription.enqueueUnregisteredInputTrigger()},h=()=>{const b=()=>{tsfTitle.enqueueUnregisteredInputTrigger(),tsfDescription.enqueueUnregisteredInputTrigger()};a(document).on("postbox-toggled",function(a,c){if("autodescription-homepage-settings"===c.id){let a=c.querySelector(".inside");0<a.offsetHeight&&0<a.offsetWidth&&b()}}),a("#tsf-homepage-tab-general").on("tsf-tab-toggled",tsfTitle.enqueueUnregisteredInputTrigger)},i=()=>{const b=a("#autodescription-site-settings\\[set_copyright_directives\\]"),c=a("#autodescription-site-settings\\[max_snippet_length\\], #autodescription-site-settings\\[max_image_preview\\], #autodescription-site-settings\\[max_video_preview\\]");if(b.length&&c.length){b.on("change.tsfToggleDirectives",b=>{b.target.checked?(c.prop("disabled",!1),a(".tsf-toggle-directives-surrogate").remove()):(c.prop("disabled",!0),c.each((b,c)=>{a("<input />").attr("type","hidden").attr("name",c.name||"").val(c.value||0).addClass("tsf-toggle-directives-surrogate").insertAfter(c)}))}),b.trigger("change.tsfToggleDirectives")}},j=()=>{const b=a("#autodescription-site-settings\\[google_verification\\], #autodescription-site-settings\\[bing_verification\\], #autodescription-site-settings\\[yandex_verification\\], #autodescription-site-settings\\[baidu_verification\\], #autodescription-site-settings\\[pint_verification\\]");if(b.length){const a=a=>{let b=a.originalEvent.clipboardData&&a.originalEvent.clipboardData.getData("text")||void 0;if(b){let c=/<meta[^>]+content=(\"|\')?([^\"\'>\s]+)\1?.*?>/i.exec(b);c&&2 in c&&"string"==typeof c[2]&&c[2].length&&(a.stopPropagation(),a.preventDefault(),a.target.value=c[2],tsfAys.registerChange())}};b.on("paste",a)}},k=()=>{c(),e(),f(),g(),h(),i(),j(),d()},l=()=>{tsfSocial.initTitleInputs({ref:document.getElementById("tsf-title-reference"),meta:document.getElementById("autodescription-site-settings[homepage_title]"),og:document.getElementById("autodescription-site-settings[homepage_og_title]"),tw:document.getElementById("autodescription-site-settings[homepage_twitter_title]")}),tsfSocial.initDescriptionInputs({ref:document.getElementById("tsf-description-reference"),meta:document.getElementById("autodescription-site-settings[homepage_description]"),og:document.getElementById("autodescription-site-settings[homepage_og_description]"),tw:document.getElementById("autodescription-site-settings[homepage_twitter_description]")})},m=()=>confirm(b.i18n.confirmReset),n=()=>{a(".tsf-tabs-radio").on("change",(b,c)=>{let d=a(b.target);if(!d.is(":checked"))return;c="boolean"==typeof c&&c;let e=b.target.id,f=b.target.name,g="tsf-active-tab-content",h="tsf-tab-active",i=a("."+g),j=d.closest(".tsf-nav-tab-wrapper").find("."+h),k=i.find("input:invalid, select:invalid, textarea:invalid");if(k.length)return k[0].reportValidity(),j.prop("checked",!0),d.prop("checked",!1),b.stopPropagation(),b.preventDefault(),!1;let l=a("#"+e+"-content");if(j.removeClass(h),j.siblings("label").removeClass("tsf-no-focus-ring"),d.addClass(h),c){let b=a("."+f+"-content");b.removeClass(g).hide(),l.addClass(g).show(),a("#"+e).trigger("tsf-tab-toggled")}else if(l.length&&!l.is(i)){let b=a("."+f+"-content");b.fadeOut(150,function(){a(this).removeClass(g)}),setTimeout(()=>{l.addClass(g).fadeIn(250)},150),setTimeout(()=>{a("#"+e).trigger("tsf-tab-toggled")},175)}});a(".tsf-nav-tab-wrapper").on("click.tsfNavTab",".tsf-nav-tab",a=>{a.currentTarget.classList.add("tsf-no-focus-ring")});a(document.body).on("tsf-ready",()=>{a(".tsf-tabs-radio:checked").each((b,c)=>{a(c).trigger("change",[!0])})})};return Object.assign({load:()=>{a("div.updated, div.error, div.notice, .notice-error, .notice-warning, .notice-info").insertAfter(".tsf-top-wrap"),a(document.body).on("tsf-onload",k),a(document.body).on("tsf-ready",l),a(".tsf-js-confirm-reset").on("click",m),n()}},{},{l10n:b})}(jQuery),jQuery(window.tsfSettings.load);
lib/js/social.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/term.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/title.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
lib/js/tsf.js CHANGED
@@ -8,7 +8,7 @@
8
 
9
  /**
10
  * The SEO Framework plugin
11
- * Copyright (C) 2015 - 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
@@ -140,10 +140,10 @@ window.tsf = function( $ ) {
140
  *
141
  * @since 3.0.1
142
  * @since 3.1.2 Now escapes backslashes correctly.
143
- * @since 4.0.0: 1. Now escapes all backslashes, instead of only double.
144
- * 2. Now escapes forward slashes:
145
- * Although unlikely, some HTML parsers may omit the closing " of an attribute,
146
- * which may cause the slash to close the HTML tag.
147
  * @access public
148
  *
149
  * @function
8
 
9
  /**
10
  * The SEO Framework plugin
11
+ * Copyright (C) 2015 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
12
  *
13
  * This program is free software: you can redistribute it and/or modify
14
  * it under the terms of the GNU General Public License version 3 as published
140
  *
141
  * @since 3.0.1
142
  * @since 3.1.2 Now escapes backslashes correctly.
143
+ * @since 4.0.0 : 1. Now escapes all backslashes, instead of only double.
144
+ * 2. Now escapes forward slashes:
145
+ * Although unlikely, some HTML parsers may omit the closing " of an attribute,
146
+ * which may cause the slash to close the HTML tag.
147
  * @access public
148
  *
149
  * @function
lib/js/tt.js CHANGED
@@ -9,7 +9,7 @@
9
 
10
  /**
11
  * The SEO Framework plugin
12
- * Copyright (C) 2019 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
9
 
10
  /**
11
  * The SEO Framework plugin
12
+ * Copyright (C) 2019 - 2020 Sybre Waaijer, CyberWire (https://cyberwire.nl/)
13
  *
14
  * This program is free software: you can redistribute it and/or modify
15
  * it under the terms of the GNU General Public License version 3 as published
readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: Cybr
3
  Tags: seo, xml sitemap, google search, open graph, schema.org, twitter card, performance
4
  Requires at least: 4.9.0
5
- Tested up to: 5.3
6
  Requires PHP: 5.6.0
7
- Stable tag: 4.0.4
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
@@ -20,7 +20,7 @@ To top it off, this is the fastest full-featured SEO plugin, and it blends right
20
 
21
  It's easy to get started. Activate this plugin, and your site's already protected against prominent SEO attacks. The SEO Framework will also prefill all critical meta tags for you. A real time-saver. Ingenious.
22
 
23
- [Migrate](https://theseoframework.com/?p=511) | [Setup](https://theseoframework.com/?p=2428) | [Improve](https://theseoframework.com/?p=2663) | [Extensions](https://theseoframework.com/extensions/) | [API](https://theseoframework.com/?p=82) | [Privacy](https://theseoframework.com/?p=1701#pluginprivacyinformation)
24
 
25
  = We poured over 16,000 hours into this plugin. Here are the results: =
26
 
@@ -58,7 +58,7 @@ We handpicked our color scheme so that people with any medically recognized colo
58
  The SEO Framework steers you from making significant and common SEO mistakes. It leaves little room for you to mess up because the plugin already does everything SEO for you. For example, it automatically prevents duplicated content mistakes by enforcing strict canonical rules.
59
 
60
  * **It follows best-practices and beyond.**
61
- The biggest problems with WordPress plugins are security and compatibility. As part-time security researchers, we focus on making this plugin impenetrable. The SEO Framework also uses WordPress' API whenever possible, making this plugin integrate neatly with every other plugin written with that in mind.
62
 
63
  * **It has developers at heart.**
64
  We encourage other developers to enhance and add functionality to this plugin. We've done so ourselves, already, with our [extensions](https://theseoframework.com/extensions/). Check out [our API](https://theseoframework.com/?p=82), and feel free to [contribute](https://tsf.fyi/contributing)!
@@ -101,7 +101,7 @@ The SEO Framework works on many things without notifying you, because the best s
101
  * It discourages 404 pages and empty categories from being indexed, even when they don't send a 404 response.
102
  * It automatically notifies Google and the Bing network on website updates when sitemaps are enabled.
103
  * It discourages search engines from indexing feeds and the sitemap. This doesn't mean they won't use them, they only won't show them in their search results.
104
- * It directs search engines from the comment pages back to the post holding those comments.
105
 
106
  = Compatibility =
107
 
@@ -116,11 +116,12 @@ The SEO Framework works on many things without notifying you, because the best s
116
  * Better screen-reader accessibility via ARIA labels and title attributes.
117
  * Full keyboard navigation.
118
  * WordPress Multisite setups, this plugin is in fact built upon one.
119
- * Detection of robots.txt and sitemap.xml files.
120
  * Output of structured data via Schema.org JSON-LD scripts.
 
121
  * Detection of various other SEO tools to help you switch graciously.
122
  * Translation plugins like WPML, Polylang, WPGlobus, and MultilingualPress.
123
- * Ecommerce plugins, like WooCommerce and EDD.
124
 
125
  = Copyright legislation notice =
126
 
@@ -227,6 +228,16 @@ If you wish to display breadcrumbs, then your theme should provide this. Alterna
227
 
228
  == Changelog ==
229
 
 
 
 
 
 
 
 
 
 
 
230
  = 4.0.4 =
231
 
232
  WordPress 5.3 has a [bug](https://core.trac.wordpress.org/ticket/48623) where the timezone set in PHP is taken into account when creating permalinks. Since this bug can cause canonical URLs with dates to point to a nonexistent page, we're sending out this patch where TSF sets the timezone to flat UTC for its front-end generation.
@@ -261,10 +272,6 @@ Our users reported some admin scripting issues when updating from v3.2.4 to v4.0
261
 
262
  *It is our choices, Harry, that show what we truly are, far more than our abilities. - [J.K. Rowling](https://www.jkrowling.com/book/harry-potter-chamber-secrets/)*
263
 
264
- **Release date**
265
-
266
- * September 9th, 2019
267
-
268
  **Foreword**
269
 
270
  We wrote a [foreword on 4.0](https://theseoframework.com/about/an-introduction-to-a-thousand-changes/). It's a story on our efforts making this update, and why we're exhilarated bringing you this update... finally.
2
  Contributors: Cybr
3
  Tags: seo, xml sitemap, google search, open graph, schema.org, twitter card, performance
4
  Requires at least: 4.9.0
5
+ Tested up to: 5.4
6
  Requires PHP: 5.6.0
7
+ Stable tag: 4.0.5
8
  License: GPLv3
9
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
10
 
20
 
21
  It's easy to get started. Activate this plugin, and your site's already protected against prominent SEO attacks. The SEO Framework will also prefill all critical meta tags for you. A real time-saver. Ingenious.
22
 
23
+ [Migrate](https://theseoframework.com/?p=511) | [Setup](https://theseoframework.com/?p=2428) | [Improve](https://theseoframework.com/?p=2663) | [Extensions](https://theseoframework.com/extensions/) | [API](https://theseoframework.com/?p=82) | [Support](https://theseoframework.com/?p=3478) | [Privacy](https://theseoframework.com/?p=1701#pluginprivacyinformation)
24
 
25
  = We poured over 16,000 hours into this plugin. Here are the results: =
26
 
58
  The SEO Framework steers you from making significant and common SEO mistakes. It leaves little room for you to mess up because the plugin already does everything SEO for you. For example, it automatically prevents duplicated content mistakes by enforcing strict canonical rules.
59
 
60
  * **It follows best-practices and beyond.**
61
+ The biggest problems with WordPress plugins are security and compatibility. As part-time security researchers, we focus on making this plugin impenetrable. The SEO Framework also uses WordPress's API whenever possible, making this plugin integrate neatly with every other plugin written with that in mind.
62
 
63
  * **It has developers at heart.**
64
  We encourage other developers to enhance and add functionality to this plugin. We've done so ourselves, already, with our [extensions](https://theseoframework.com/extensions/). Check out [our API](https://theseoframework.com/?p=82), and feel free to [contribute](https://tsf.fyi/contributing)!
101
  * It discourages 404 pages and empty categories from being indexed, even when they don't send a 404 response.
102
  * It automatically notifies Google and the Bing network on website updates when sitemaps are enabled.
103
  * It discourages search engines from indexing feeds and the sitemap. This doesn't mean they won't use them, they only won't show them in their search results.
104
+ * It directs search engines from the comment pages back to the post storing those comments.
105
 
106
  = Compatibility =
107
 
116
  * Better screen-reader accessibility via ARIA labels and title attributes.
117
  * Full keyboard navigation.
118
  * WordPress Multisite setups, this plugin is in fact built upon one.
119
+ * Detection and output of robots.txt and sitemap.xml files.
120
  * Output of structured data via Schema.org JSON-LD scripts.
121
+ * Altering oEmbed for improved sharing on Discord.
122
  * Detection of various other SEO tools to help you switch graciously.
123
  * Translation plugins like WPML, Polylang, WPGlobus, and MultilingualPress.
124
+ * E-commerce plugins, like WooCommerce and EDD.
125
 
126
  = Copyright legislation notice =
127
 
228
 
229
  == Changelog ==
230
 
231
+ = 4.0.5 =
232
+
233
+ In WordPress, we found various query endpoints that can be malformed to create broken pages. Backlinks to these pages can harm your site's ranking. In this update, we added advanced query protection, which you can enable via the robots meta settings.
234
+
235
+ The ["Connected Social Pages" input fields will now disappear](https://github.com/sybrew/the-seo-framework/issues/498) when you empty them. They have never proven to work, and Google has deprecated them. We also removed the transient caching for JSON-LD scripts, as it wasn't helping anyone.
236
+
237
+ On the other hand, we added a new feed indexing option, Discord sharing options (oEmbed, theme color), and the aforementioned advanced query protection option. Support for EDD and Polylang has been expanded, and we reintroduced the hyphen option for titles (which is the new default).
238
+
239
+ In this update, we bring a few other quality-of-life changes, as well. We added a dozen new filters, touched up the interface, streamlined the query handler, and [fixed known corner-case issues and bugs](https://theseoframework.com/?p=3505#detailed).
240
+
241
  = 4.0.4 =
242
 
243
  WordPress 5.3 has a [bug](https://core.trac.wordpress.org/ticket/48623) where the timezone set in PHP is taken into account when creating permalinks. Since this bug can cause canonical URLs with dates to point to a nonexistent page, we're sending out this patch where TSF sets the timezone to flat UTC for its front-end generation.
272
 
273
  *It is our choices, Harry, that show what we truly are, far more than our abilities. - [J.K. Rowling](https://www.jkrowling.com/book/harry-potter-chamber-secrets/)*
274
 
 
 
 
 
275
  **Foreword**
276
 
277
  We wrote a [foreword on 4.0](https://theseoframework.com/about/an-introduction-to-a-thousand-changes/). It's a story on our efforts making this update, and why we're exhilarated bringing you this update... finally.